nl_tokens: A context menu
pl_tokens: function ContextMenu ( items , options ) { this . dom = { } ; var me = this ; var dom = this . dom ; this . anchor = undefined ; this . items = items ; this . eventListeners = { } ; this . selection = undefined ; // holds the selection before the menu was opened this . onClose = options ? options . close : undefined ; // create root element var root = document . createElement ( 'div' ) ; root . className = 'jsoneditor-contextmenu-root' ; dom . root = root ; // create a container element var menu = document . createElement ( 'div' ) ; menu . className = 'jsoneditor-contextmenu' ; dom . menu = menu ; root . appendChild ( menu ) ; // create a list to hold the menu items var list = document . createElement ( 'ul' ) ; list . className = 'jsoneditor-menu' ; menu . appendChild ( list ) ; dom . list = list ; dom . items = [ ] ; // list with all buttons // create a (non-visible) button to set the focus to the menu var focusButton = document . createElement ( 'button' ) ; focusButton . type = 'button' ; dom . focusButton = focusButton ; var li = document . createElement ( 'li' ) ; li . style . overflow = 'hidden' ; li . <mask> . height = '0' ; li . appendChild ( focusButton ) ; list . appendChild ( li ) ; function createMenuItems ( list , domItems , items ) { items . forEach ( function ( item ) { if ( item . type == 'separator' ) { // create a separator var separator = document . createElement ( 'div' ) ; separator . className = 'jsoneditor-separator' ; li = document . createElement ( 'li' ) ; li . appendChild ( separator ) ; list . appendChild ( li ) ; } else { var domItem = { } ; // create a menu item var li = document . createElement ( 'li' ) ; list . appendChild ( li ) ; // create a button in the menu item var button = document . createElement ( 'button' ) ; button . type = 'button' ; button . className = item . className ; domItem . button = button ; if ( item . title ) { button . title = item . title ; } if ( item . click ) { button . onclick = function ( event ) { event . preventDefault ( ) ; me . hide ( ) ; item . click ( ) ; } ; } li . appendChild ( button ) ; // create the contents of the button if ( item . submenu ) { // add the icon to the button var divIcon = document . createElement ( 'div' ) ; divIcon . className = 'jsoneditor-icon' ; button . appendChild ( divIcon ) ; var divText = document . createElement ( 'div' ) ; divText . className = 'jsoneditor-text' + ( item . click ? '' : ' jsoneditor-right-margin' ) ; divText . appendChild ( document . createTextNode ( item . text ) ) ; button . appendChild ( divText ) ; var buttonSubmenu ; if ( item . click ) { // submenu and a button with a click handler button . className += ' jsoneditor-default' ; var buttonExpand = document . createElement ( 'button' ) ; buttonExpand . type = 'button' ; domItem . buttonExpand = buttonExpand ; buttonExpand . className = 'jsoneditor-expand' ; buttonExpand . innerHTML = '<div class="jsoneditor-expand"></div>' ; li . appendChild ( buttonExpand ) ; if ( item . submenuTitle ) { buttonExpand . title = item . submenuTitle ; } buttonSubmenu = buttonExpand ; } else { // submenu and a button without a click handler var divExpand = document . createElement ( 'div' ) ; divExpand . className = 'jsoneditor-expand' ; button . appendChild ( divExpand ) ; buttonSubmenu = button ; } // attach a handler to expand/collapse the submenu buttonSubmenu . onclick = function ( event ) { event . preventDefault ( ) ; me . _onExpandItem ( domItem ) ; buttonSubmenu . focus ( ) ; } ; // create the submenu var domSubItems = [ ] ; domItem . subItems = domSubItems ; var ul = document . createElement ( 'ul' ) ; domItem . ul = ul ; ul . className = 'jsoneditor-menu' ; ul . style . height = '0' ; li . appendChild ( ul ) ; createMenuItems ( ul , domSubItems , item . submenu ) ; } else { // no submenu, just a button with clickhandler button . innerHTML = '<div class="jsoneditor-icon"></div>' + '<div class="jsoneditor-text">' + translate ( item . text ) + '</div>' ; } domItems . push ( domItem ) ; } } ) ; } createMenuItems ( list , this . dom . items , items ) ; // TODO: when the editor is small, show the submenu on the right instead of inline? // calculate the max height of the menu with one submenu expanded this . maxHeight = 0 ; // height in pixels items . forEach ( function ( item ) { var height = ( items . length + ( item . submenu ? item . submenu . length : 0 ) ) * 24 ; me . maxHeight = Math . max ( me . maxHeight , height ) ; } ) ; }