X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs-website;a=blobdiff_plain;f=web%2Fcore%2Fmodules%2Ftoolbar%2Fjs%2Ftoolbar.menu.es6.js;fp=web%2Fcore%2Fmodules%2Ftoolbar%2Fjs%2Ftoolbar.menu.es6.js;h=03fd41f371dff0e8c61d48fa195f8217852dd6cd;hp=0000000000000000000000000000000000000000;hb=9917807b03b64faf00f6a1f29dcb6eafc454efa5;hpb=aea91e65e895364e460983b890e295aa5d5540a5 diff --git a/web/core/modules/toolbar/js/toolbar.menu.es6.js b/web/core/modules/toolbar/js/toolbar.menu.es6.js new file mode 100644 index 000000000..03fd41f37 --- /dev/null +++ b/web/core/modules/toolbar/js/toolbar.menu.es6.js @@ -0,0 +1,192 @@ +/** + * @file + * Builds a nested accordion widget. + * + * Invoke on an HTML list element with the jQuery plugin pattern. + * + * @example + * $('.toolbar-menu').drupalToolbarMenu(); + */ + +(function ($, Drupal, drupalSettings) { + /** + * Store the open menu tray. + */ + let activeItem = Drupal.url(drupalSettings.path.currentPath); + + $.fn.drupalToolbarMenu = function () { + const ui = { + handleOpen: Drupal.t('Extend'), + handleClose: Drupal.t('Collapse'), + }; + + /** + * Handle clicks from the disclosure button on an item with sub-items. + * + * @param {Object} event + * A jQuery Event object. + */ + function toggleClickHandler(event) { + const $toggle = $(event.target); + const $item = $toggle.closest('li'); + // Toggle the list item. + toggleList($item); + // Close open sibling menus. + const $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) { + const $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) { + const options = { + class: 'toolbar-icon toolbar-handle', + action: ui.handleOpen, + text: '', + }; + // Initialize items and their links. + $menu.find('li > a').wrap('
'); + // Add a handle to each list item if it has a menu. + $menu.find('li').each((index, element) => { + const $item = $(element); + if ($item.children('ul.toolbar-menu').length) { + const $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; + const $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) { + const pathItem = $menu.find(`a[href="${location.pathname}"]`); + if (pathItem.length && !activeItem) { + activeItem = location.pathname; + } + if (activeItem) { + const $activeItem = $menu.find(`a[href="${activeItem}"]`).addClass('menu-item--active'); + const $activeTrail = $activeItem.parentsUntil('.root', 'li').addClass('menu-item--active-trail'); + toggleList($activeTrail, true); + } + } + + // Return the jQuery object. + return this.each(function (selector) { + const $menu = $(this).once('toolbar-menu'); + if ($menu.length) { + // Bind event handlers. + $menu + .on('click.toolbar', '.toolbar-box', toggleClickHandler) + .on('click.toolbar', '.toolbar-box a', linkClickHandler); + + $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 + * Options for the button. + * @param {string} options.class + * Class to set on the button. + * @param {string} options.action + * Action for the button. + * @param {string} options.text + * Used as label for the button. + * + * @return {string} + * A string representing a DOM fragment. + */ + Drupal.theme.toolbarMenuItemToggle = function (options) { + return ``; + }; +}(jQuery, Drupal, drupalSettings));