Email Friendly GrapesJs Video Block - Almost Done - Need Help With Rerendering

Hey anyone know grapesjs?

I am trying to do an email friendly video code block with poster/img fallbacks based on this: How to Embed HTML5 Video in Email - Email On Acid

The component keeps disappearing when I close grapes and reopen it.

I would post this on stackoverflow but I am asking here first to make sure its not a mautic specific issue with my code as I don’t know how rendering works on close and reopen with mautic?

I have the following code:



      this.editor.DomComponents.addType('videoemail', {
          isComponent: el => {
            let result = '';
            if (/video-fallback/.test(el.innerHTML)) {
              result = {type: 'videoemail'};
            }

            return result;
          },
          model: {
            defaults: {
              type: 'videoemail',
              tagName: 'div',
              videosrc: 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
              poster: 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/BigBuckBunny.jpg',
              href: 'https://example.com',
              traits: [
                {
                  label: 'Source',
                  name: 'videosrc',
                  placeholder: 'https://example.com/video.mp4',
                  changeProp: 1
                },
                {
                  label: 'Poster',
                  name: 'poster',
                  placeholder: 'https://example.com/image.jpg',
                  changeProp: 1
                },
                {
                  label: 'Href',
                  name: 'href',
                  placeholder: 'https://example.com',
                  changeProp: 1
                },
              ]
            },
            init() {
              this.on('change:videosrc', this.updateTraits);
              this.on('change:poster', this.updateTraits);
              this.on('change:href', this.updateTraits);

            },
            updateTraits({view}) {
              view.updateTraits();
            },
          },
          view: {
            tagName: 'div',
            updateTraits() {

              this.getVideoEmail().querySelector('video.the-video').setAttribute('src',this.model.get('videosrc'));
              this.getVideoEmail().querySelector('video.the-video').setAttribute('poster',this.model.get('poster'));
              this.getVideoEmail().querySelector('img.the-img').setAttribute('src',this.model.get('poster'));
              this.getVideoEmail().querySelector('a.the-ahref').setAttribute('href',this.model.get('href'));
              this.getVideoEmail().querySelector('img.the-img').setAttribute('src',this.model.get('poster'));
              this.getVideoEmail().querySelector('a.the-ahref').setAttribute('href',this.model.get('href'));

            },

           getVideoEmail() {
            console.log('ranvidemail');
            if (!this.videoemail) {
                var wrapperdiv = document.createElement('div');
                wrapperdiv.className = this.ppfx + 'videoemail-wrapper';

                var div = document.createElement('div');
                div.className = 'video-wrapper';
                div.style.display = 'none';
                
                var vid = document.createElement('video');
                vid.setAttribute('src',this.model.get('videosrc'));
                vid.setAttribute('poster',this.model.get('poster'));
                vid.setAttribute('controls','controls');
                vid.setAttribute('width','640');
                vid.className = 'the-video';

                var ahref = document.createElement('a');
                ahref.setAttribute('href',this.model.get('href'));
                ahref.className = 'the-ahref';

                var img = document.createElement('img');
                img.setAttribute('src',this.model.get('poster'));
                img.className = 'the-img';

                ahref.appendChild(img);
                vid.appendChild(ahref);
                div.appendChild(vid);



                var div2 = document.createElement('div');
                div2.className = 'video-fallback';

                var ahref2 = document.createElement('a');
                ahref2.setAttribute('href',this.model.get('href'));
                ahref2.className = 'the-ahref';

                var img2 = document.createElement('img');
                img2.setAttribute('src',this.model.get('poster'));
                img2.className = 'the-img';


                ahref2.appendChild(img2);
                div2.appendChild(ahref2);
                wrapperdiv.appendChild(div);
                wrapperdiv.appendChild(div2);
                this.videoemail = wrapperdiv;
              }
              return this.videoemail;

            },
            onRender({el}) {
              console.log('ranrender');
              el.appendChild(this.getVideoEmail());
            }
          }
        });

        this.editor.BlockManager.add("videoemail", {
          label: "Video For Email",
          category: 'Extra',
          attributes: { class: 'fa fa-play-circle-o' },
          content: {
            type: 'videoemail',
            style: {height: '', width: '640px'},
          },
          selectable: true
        });

        console.log('test');
console.log(mQuery('textarea.builder-html'));

    this.editor.DomComponents.addComponent({
  tagName: 'style',
  removable: true, // Can't remove it
  draggable: false, // Can't move it
  copyable: false, // Disable copy/past
  content: `<style>  .video-wrapper {display:none;}
                         @media (-webkit-min-device-pixel-ratio: 0) and (min-device-width:1024px) 
                         {
                           .video-wrapper { display:block!important; }
                           .video-fallback { display:none!important; }
                         }
                          @supports (-webkit-overflow-scrolling:touch) and (color:#ffffffff) {
                             div[class^=video-wrapper] { display:block!important; }
                             div[class^=video-fallback] { display:none!important; }
                          }
                         .video-wrapper { display:block!important; }
                         .video-fallback { display:none!important; }</style>`, // Text inside component
});


    return this.editor;
  }

Here is a jsfiddle with this code:
https://jsfiddle.net/j9pozftd/

The problem is when i close the grapesjs editor and then reopen it (without saving but happens with save too) the component disappears. Im not sure if this is something to do with how mautic saves the current state or im doing something wrong with my grapes js code?

Can anyone lend me a push in the right direction?

Thanks!

Paging @adiux :slight_smile:

1 Like

I found the code area that’s not working for me:

For some reason editor.getHtml() fails to keep my component?

Debugging!