2015-08-17 17:00:26 -07:00
/ * *
* @ file
* Builds a nested accordion widget .
*
* Invoke on an HTML list element with the jQuery plugin pattern .
*
* @ example
* $ ( '.toolbar-menu' ) . drupalToolbarMenu ( ) ;
* /
( function ( $ , Drupal , drupalSettings ) {
2015-10-21 21:44:50 -07:00
'use strict' ;
2015-08-17 17:00:26 -07:00
/ * *
* Store the open menu tray .
* /
var activeItem = Drupal . url ( drupalSettings . path . currentPath ) ;
$ . fn . drupalToolbarMenu = function ( ) {
var ui = {
2015-09-04 13:20:09 -07:00
handleOpen : Drupal . t ( 'Extend' ) ,
handleClose : Drupal . t ( 'Collapse' )
2015-08-17 17:00:26 -07:00
} ;
/ * *
* Handle clicks from the disclosure button on an item with sub - items .
*
* @ param { Object } event
* A jQuery Event object .
* /
function toggleClickHandler ( event ) {
var $toggle = $ ( event . target ) ;
var $item = $toggle . closest ( 'li' ) ;
// Toggle the list item.
toggleList ( $item ) ;
// Close open sibling menus.
var $openItems = $item . siblings ( ) . filter ( '.open' ) ;
toggleList ( $openItems , false ) ;
}
/ * *
* Handle clicks from a menu item link .
*
* @ param { Object } event
* A jQuery Event object .
* /
function linkClickHandler ( event ) {
// If the toolbar is positioned fixed (and therefore hiding content
// underneath), then users expect clicks in the administration menu tray
// to take them to that destination but for the menu tray to be closed
// after clicking: otherwise the toolbar itself is obstructing the view
// of the destination they chose.
if ( ! Drupal . toolbar . models . toolbarModel . get ( 'isFixed' ) ) {
Drupal . toolbar . models . toolbarModel . set ( 'activeTab' , null ) ;
}
// Stopping propagation to make sure that once a toolbar-box is clicked
// (the whitespace part), the page is not redirected anymore.
event . stopPropagation ( ) ;
}
/ * *
* Toggle the open / close state of a list is a menu .
*
* @ param { jQuery } $item
* The li item to be toggled .
*
* @ param { Boolean } switcher
* A flag that forces toggleClass to add or a remove a class , rather than
* simply toggling its presence .
* /
function toggleList ( $item , switcher ) {
var $toggle = $item . children ( '.toolbar-box' ) . children ( '.toolbar-handle' ) ;
switcher = ( typeof switcher !== 'undefined' ) ? switcher : ! $item . hasClass ( 'open' ) ;
// Toggle the item open state.
$item . toggleClass ( 'open' , switcher ) ;
// Twist the toggle.
$toggle . toggleClass ( 'open' , switcher ) ;
// Adjust the toggle text.
$toggle
. find ( '.action' )
// Expand Structure, Collapse Structure.
. text ( ( switcher ) ? ui . handleClose : ui . handleOpen ) ;
}
/ * *
* Add markup to the menu elements .
*
* Items with sub - elements have a list toggle attached to them . Menu item
* links and the corresponding list toggle are wrapped with in a div
* classed with . toolbar - box . The . toolbar - box div provides a positioning
* context for the item list toggle .
*
* @ param { jQuery } $menu
* The root of the menu to be initialized .
* /
function initItems ( $menu ) {
var options = {
2015-09-04 13:20:09 -07:00
class : 'toolbar-icon toolbar-handle' ,
action : ui . handleOpen ,
text : ''
2015-08-17 17:00:26 -07:00
} ;
// Initialize items and their links.
$menu . find ( 'li > a' ) . wrap ( '<div class="toolbar-box">' ) ;
// Add a handle to each list item if it has a menu.
$menu . find ( 'li' ) . each ( function ( index , element ) {
var $item = $ ( element ) ;
if ( $item . children ( 'ul.toolbar-menu' ) . length ) {
var $box = $item . children ( '.toolbar-box' ) ;
options . text = Drupal . t ( '@label' , { '@label' : $box . find ( 'a' ) . text ( ) } ) ;
$item . children ( '.toolbar-box' )
. append ( Drupal . theme ( 'toolbarMenuItemToggle' , options ) ) ;
}
} ) ;
}
/ * *
* Adds a level class to each list based on its depth in the menu .
*
* This function is called recursively on each sub level of lists elements
* until the depth of the menu is exhausted .
*
* @ param { jQuery } $lists
* A jQuery object of ul elements .
*
* @ param { number } level
* The current level number to be assigned to the list elements .
* /
function markListLevels ( $lists , level ) {
level = ( ! level ) ? 1 : level ;
var $lis = $lists . children ( 'li' ) . addClass ( 'level-' + level ) ;
$lists = $lis . children ( 'ul' ) ;
if ( $lists . length ) {
markListLevels ( $lists , level + 1 ) ;
}
}
/ * *
* On page load , open the active menu item .
*
* Marks the trail of the active link in the menu back to the root of the
* menu with . menu - item -- active - trail .
*
* @ param { jQuery } $menu
* The root of the menu .
* /
function openActiveItem ( $menu ) {
var pathItem = $menu . find ( 'a[href="' + location . pathname + '"]' ) ;
if ( pathItem . length && ! activeItem ) {
activeItem = location . pathname ;
}
if ( activeItem ) {
var $activeItem = $menu . find ( 'a[href="' + activeItem + '"]' ) . addClass ( 'menu-item--active' ) ;
var $activeTrail = $activeItem . parentsUntil ( '.root' , 'li' ) . addClass ( 'menu-item--active-trail' ) ;
toggleList ( $activeTrail , true ) ;
}
}
// Return the jQuery object.
return this . each ( function ( selector ) {
var $menu = $ ( this ) . once ( 'toolbar-menu' ) ;
if ( $menu . length ) {
2015-10-08 11:40:12 -07:00
// Bind event handlers.
$menu
. on ( 'click.toolbar' , '.toolbar-box' , toggleClickHandler )
. on ( 'click.toolbar' , '.toolbar-box a' , linkClickHandler ) ;
2015-08-17 17:00:26 -07:00
$menu . addClass ( 'root' ) ;
initItems ( $menu ) ;
markListLevels ( $menu ) ;
// Restore previous and active states.
openActiveItem ( $menu ) ;
}
} ) ;
} ;
/ * *
* A toggle is an interactive element often bound to a click handler .
*
* @ param { object } options
2015-09-04 13:20:09 -07:00
* Options for the button .
2015-08-17 17:00:26 -07:00
* @ param { string } options . class
2015-09-04 13:20:09 -07:00
* Class to set on the button .
2015-08-17 17:00:26 -07:00
* @ param { string } options . action
2015-09-04 13:20:09 -07:00
* Action for the button .
2015-08-17 17:00:26 -07:00
* @ param { string } options . text
2015-09-04 13:20:09 -07:00
* Used as label for the button .
2015-08-17 17:00:26 -07:00
*
* @ return { string }
* A string representing a DOM fragment .
* /
Drupal . theme . toolbarMenuItemToggle = function ( options ) {
return '<button class="' + options [ 'class' ] + '"><span class="action">' + options . action + '</span><span class="label">' + options . text + '</span></button>' ;
} ;
} ( jQuery , Drupal , drupalSettings ) ) ;