Issue #2325💬 AnsweredOpened 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.

快速解答by artf

If you need to customize a component read and understand how they work here: https://grapesjs.com/docs/modules/Components.html You have total control over the component in the canvas by using its View

Read full answer below ↓

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.

代码片段TEXT
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...

Free option

Check the open-source GrapesJS plugins on GitHub or run a quick search in our free catalog.

Browse free plugins →
Premium option

Premium plugins ship with support, regular updates, and production-ready features — save days of integration work.

Browse premium plugins →

Related tutorials

In-depth guides on the same topic.

All tutorials →

Browse Plugin Categories

Jump directly to plugin category pages on the marketplace.