Issue #2325Opened October 12, 2019by adityaMurarka0 reactions

How to use "append" create a structure for a side-menu in the editor and also is it possible to disable a plugin on selection of another one.

Question

[Question]: 1.) I am trying to create a hamburger sidebar for the full-screen view instead of just the mobile view. But when we have dropped the plugin, on dropping any other plugin it is not getting a proper structure on the body to separate the other content and is overlapping. Is there any way to avoid it.

Code SnippetTEXT
2.) Also on dropping of hamburger side menu, I want the Menu plugin should be disabled. Is there a way to do so.

3.) I would be very helpful if you help it implement it any other way if possible.

For reference: - I have used the menu default plugin and changed a bit to serve my purpose. I am attaching relevant files with respect to the plugin.

**_Index.js_**

`import grapesjs from 'grapesjs';
import loadBlocks from './blocks';
import loadComponents from './components';
import {
  hNavbarRef, navbarRef, navbarItemsRef, menuRef
} from './consts';

export default grapesjs.plugins.add('ef-hamburger', (editor, opts = {}) => {
  let c = opts;

  let defaults = {
    blocks: [hNavbarRef],
    defaultStyle: 1,
    navbarClsPfx: 'navbar',
    labelNavbar: 'navbar',
    labelNavbarContainer: 'Navbar Container',
    labelMenu: 'Navbar Menu',
    labelMenuLink: 'Menu link',
    labelBurger: 'Burger',
    labelBurgerLine: 'Burger Line',
    labelNavbarBlock: 'Hamburger',
    labelNavbarCategory: 'Extra',
    labelHome: 'Home',
    labelAbout: 'About',
    labelContact: 'Contact',
  };

  // Load defaults
  for (let name in defaults) {
    if (!(name in c))
      c[name] = defaults[name];
  }

  loadBlocks(editor, c);
  loadComponents(editor, c);
});
`
**_consts.js_**

`export const
  hNavbarRef = 'h-navbar',
  navbarRef = 'navbar',
  navbarItemsRef = 'navbar-items',
  menuRef = 'navbar-menu';
`

**_component.js_**

`export default (editor, opt = {}) => {
    const c = opt;
    const dc = editor.DomComponents;
    const defaultType = dc.getType('default');
    const defaultModel = defaultType.model;
    const burgerType = 'burger-menu';
  
    dc.addType(burgerType, {
      model: defaultModel.extend({
        defaults: {
          ...defaultModel.prototype.defaults,
          'custom-name': c.labelBurger,
          draggable: false,
          droppable: false,
          copyable: false,
          removable: false,
          script: function () {
            var transEndAdded;
            var isAnimating = 0;
            var stringCollapse = 'gjs-collapse';
            var clickEvent = 'click';
            var transitProp = 'max-height';
            var transitTiming = 'ease-in-out';
            var transitSpeed = 0.25;
  
            var getTransitionEvent = function() {
              var t, el = document.createElement('void');
              var transitions = {
                'transition': 'transitionend',
                'OTransition': 'oTransitionEnd',
                'MozTransition': 'transitionend',
                'WebkitTransition': 'webkitTransitionEnd'
              }
  
              for (t in transitions) {
                if (el.style[t] !== undefined){
                  return transitions[t];
                }
              }
            }
  
            var transitEndEvent = getTransitionEvent();
  
            var getElHeight = function(el) {
              var style = window.getComputedStyle(el);
              var elDisplay = style.display;
              var elPos = style.position;
              var elVis = style.visibility;
              var currentHeight = style.height;
              var elMaxHeight = parseInt(style[transitProp]);
  
              if (elDisplay !== 'none' && elMaxHeight !== '0') {
                return el.offsetHeight;
              }
  
              el.style.height = 'auto';
              el.style.display = 'block';
              el.style.position = 'absolute';
              el.style.visibility = 'hidden';
              var height = el.offsetHeight;
              el.style.height = '';
              el.style.display = '';
              el.style.position = '';
              el.style.visibility = '';
  
              return height;
            };
  
            var toggleSlide = function(el) {
              isAnimating = 1;
              var elMaxHeight = getElHeight(el);
              var elStyle = el.style;
              elStyle.display = 'block';
              elStyle.transition = transitProp + ' ' + transitSpeed + 's ' + transitTiming;
              elStyle.overflowY = 'hidden';
  
              if (elStyle[transitProp] == '') {
                elStyle[transitProp] = 0;
              }
  
              if (parseInt(elStyle[transitProp]) == 0) {
                elStyle[transitProp] = '0';
                setTimeout(function() {
                    elStyle[transitProp] = elMaxHeight + 'px';
                }, 10);
              } else {
                elStyle[transitProp] = '0';
              }
            }
  
            var toggle = function(e) {
              e.preventDefault();
  
              if (isAnimating) {
                return;
              }
  
              var navParent = this.closest(`[data-gjs=navbar]`);
              var navItems = navParent.querySelector(`[data-gjs=navbar-items]`);
              toggleSlide(navItems);
  
              if (!transEndAdded) {
                navItems.addEventListener(transitEndEvent, function() {
                  isAnimating = 0;
                  var itemsStyle = navItems.style;
                  if (parseInt(itemsStyle[transitProp]) == 0) {
                    itemsStyle.displatoggleSlidey = '';
                    itemsStyle[transitProp] = '';
                  }
                });
                transEndAdded = 1;
              }
            };
  
            if ( !(stringCollapse in this ) ) {
              this.addEventListener(clickEvent, toggle);
            }
  
            this[stringCollapse] = 1;
          },
        },
      }, {
        isComponent(el) {
          if(el.getAttribute &&
            el.getAttribute('data-gjs-type') == burgerType) {
            return {type: burgerType};
          }
        },
      }),
      view: defaultType.view,
    });
  }
  `

**_blocks.js_**

`import {
    hNavbarRef,
    navbarRef,
    navbarItemsRef,
    menuRef
  } from "./consts";
  
  export default (editor, opt = {}) => {
    const c = opt;
    const bm = editor.BlockManager;
    const navbarPfx = c.navbarClsPfx || 'navbar';
    const style = c.defaultStyle ? `
    <style>
  
   body
   {
     margin: 0;
     padding: 0;
    //  height:auto;
      width:auto;
     color: black;
     font-family: "Avenir Next", "Avenir", sans-serif;
   }
   
   a
   {
     text-decoration: none;
     color: #232323;
     
     transition: color 0.3s ease;
   }
   
   a:hover
   {
     color: tomato;
   }
   
   #menuToggle
   {
     display: block;
     position: relative;
     top: 50px;
     left: 50px;
     z-index: 1;
     background-color: #d1c8c8
     
     -webkit-user-select: none;
     user-select: none;
   }
   
   #menuToggle input
   {
     display: block;
     width: 40px;
     height: 32px;
     position: absolute;
     top: -7px;
     left: -5px;
     
     cursor: pointer;
     
     opacity: 0; /* hide this */
     z-index: 2; /* and place it over the hamburger */
     
     -webkit-touch-callout: none;
   }
   
   /*
    * Just a quick hamburger
    */
   #menuToggle span
   {
     display: block;
     width: 33px;
     height: 4px;
     margin-bottom: 5px;
     position: relative;
     
     background: #cdcdcd;
     border-radius: 3px;
     
     z-index: 1;
     
     transform-origin: 4px 0px;
     
     transition: transform 0.5s cubic-bezier(0.77,0.2,0.05,1.0),
                 background 0.5s cubic-bezier(0.77,0.2,0.05,1.0),
                 opacity 0.55s ease;
   }
   
   #menuToggle span:first-child
   {
     transform-origin: 0% 0%;
   }
   
   #menuToggle span:nth-last-child(2)
   {
     transform-origin: 0% 100%;
   }
   
   /* 
    * Transform all the slices of hamburger
    * into a crossmark.
    */
   #menuToggle input:checked ~ span
   {
     opacity: 1;
     transform: rotate(45deg) translate(-2px, -1px);
     background: #232323;
   }
   
   /*
    * But let's hide the middle one.
    */
   #menuToggle input:checked ~ span:nth-last-child(3)
   {
     opacity: 0;
     transform: rotate(0deg) scale(0.2, 0.2);
   }
   
   /*
    * Ohyeah and the last one should go the other direction
    */
   #menuToggle input:checked ~ span:nth-last-child(2)
   {
     transform: rotate(-45deg) translate(0, -1px);
   }
   
   /*
    * Make this absolute positioned
    * at the top left of the screen
    */
   #menu
   {
     position: absolute;
     width: 150px;
     margin: -100px 500px 100px -50px;
     padding: 50px;
     padding-top: 125px;
     height:105vh;
     background-color: #d1c8c8;
     list-style-type: none;
     -webkit-font-smoothing: antialiased;
     /* to stop flickering of text in safari */
     
     transform-origin: 0% 0%;
     transform: translate(-100%, 0);
     
     transition: transform 0.5s cubic-bezier(0.77,0.2,0.05,1.0);
   }
   
   #menu li
   {
     padding: 10px 0;
     font-size: 22px;
     
   }
   
   /*
    * And let's slide it in from the left
    */
   #menuToggle input:checked ~ ul
   {
     transform: none;
   }
   .hamburgercontainer {
    width:2em
    height:100vh;

  }
  .full-height {
    height: 100vh;
  }
  
    </style>
    ` : '';
  
      bm.add(hNavbarRef, {
        label: `
          <svg class="gjs-block-svg" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
            // <path class="gjs-block-svg-path" d="M22,9 C22,8.4 21.5,8 20.75,8 L3.25,8 C2.5,8 2,8.4 2,9 L2,15 C2,15.6 2.5,16 3.25,16 L20.75,16 C21.5,16 22,15.6 22,15 L22,9 Z M21,15 L3,15 L3,9 L21,9 L21,15 Z" fill-rule="nonzero"></path>
            <rect class="gjs-block-svg-path" x="15" y="10" width="5" height="1"></rect>
            <rect class="gjs-block-svg-path" x="15" y="10" width="5" height="1"></rect>
            <rect class="gjs-block-svg-path" x="15" y="10" width="5" height="1"></rect>
          </svg>
          <div class="gjs-block-label">${c.labelNavbarBlock}</div>`,
        category: 'Event Gadgets',
        content: `
        <div class = "hamburgercontainer">
        <!--    Made by Erik Terwan    -->
        <!--   24th of November 2015   -->
        <!--        MIT License        -->
     
          <div id="menuToggle">
          
            <!--
            A fake / hidden checkbox is used as click reciever,
            so you can use the :checked selector on it.
            -->
            <input type="checkbox" />
            
            <!--
            Some spans to act as a hamburger.
            
            They are acting like a real hamburger,
            not that McDonalds stuff.
            -->
            <span></span>
            <span></span>
            <span></span>
            
            <!--
            Too bad the menu has to be inside of the button but hey, it's pure CSS magic.
            -->
         

            <ul id="menu">
              <a href="#"><li>Home</li></a>
              <a href="#"><li>About</li></a>
              <a href="#"><li>Info</li></a>
              <a href="#"><li>Contact</li></a>
           
            </ul>
          </div>
          </div>
       
     
          ${style}
        `,
        components:[{
          tagName: 'div',
                removable: true,
                draggable: false,
                copyable: true,
                droppable:false
        }],
      });
  }
  `

![Screenshot from 2019-10-12 18-51-56](https://user-images.githubusercontent.com/50452256/66702114-b18ca900-ed21-11e9-8431-72d3f4c8e04f.png)
![Screenshot from 2019-10-12 18-52-01](https://user-images.githubusercontent.com/50452256/66702115-b2253f80-ed21-11e9-8284-4b92a998ded5.png)

Answers (1)

Related Questions and Answers

Continue research with similar issue discussions.

Paid Plugins That Match This Issue

Curated by issue keywords and label relevance to help you ship faster.

View all plugins

Loading paid plugin recommendations...

Browse Plugin Categories

Jump directly to plugin category pages on the marketplace.