comparison core/modules/toolbar/js/toolbar.menu.es6.js @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 129ea1e6d783
comparison
equal deleted inserted replaced
-1:000000000000 0:4c8ae668cc8c
1 /**
2 * @file
3 * Builds a nested accordion widget.
4 *
5 * Invoke on an HTML list element with the jQuery plugin pattern.
6 *
7 * @example
8 * $('.toolbar-menu').drupalToolbarMenu();
9 */
10
11 (function ($, Drupal, drupalSettings) {
12 /**
13 * Store the open menu tray.
14 */
15 let activeItem = Drupal.url(drupalSettings.path.currentPath);
16
17 $.fn.drupalToolbarMenu = function () {
18 const ui = {
19 handleOpen: Drupal.t('Extend'),
20 handleClose: Drupal.t('Collapse'),
21 };
22
23 /**
24 * Handle clicks from the disclosure button on an item with sub-items.
25 *
26 * @param {Object} event
27 * A jQuery Event object.
28 */
29 function toggleClickHandler(event) {
30 const $toggle = $(event.target);
31 const $item = $toggle.closest('li');
32 // Toggle the list item.
33 toggleList($item);
34 // Close open sibling menus.
35 const $openItems = $item.siblings().filter('.open');
36 toggleList($openItems, false);
37 }
38
39 /**
40 * Handle clicks from a menu item link.
41 *
42 * @param {Object} event
43 * A jQuery Event object.
44 */
45 function linkClickHandler(event) {
46 // If the toolbar is positioned fixed (and therefore hiding content
47 // underneath), then users expect clicks in the administration menu tray
48 // to take them to that destination but for the menu tray to be closed
49 // after clicking: otherwise the toolbar itself is obstructing the view
50 // of the destination they chose.
51 if (!Drupal.toolbar.models.toolbarModel.get('isFixed')) {
52 Drupal.toolbar.models.toolbarModel.set('activeTab', null);
53 }
54 // Stopping propagation to make sure that once a toolbar-box is clicked
55 // (the whitespace part), the page is not redirected anymore.
56 event.stopPropagation();
57 }
58
59 /**
60 * Toggle the open/close state of a list is a menu.
61 *
62 * @param {jQuery} $item
63 * The li item to be toggled.
64 *
65 * @param {Boolean} switcher
66 * A flag that forces toggleClass to add or a remove a class, rather than
67 * simply toggling its presence.
68 */
69 function toggleList($item, switcher) {
70 const $toggle = $item.children('.toolbar-box').children('.toolbar-handle');
71 switcher = (typeof switcher !== 'undefined') ? switcher : !$item.hasClass('open');
72 // Toggle the item open state.
73 $item.toggleClass('open', switcher);
74 // Twist the toggle.
75 $toggle.toggleClass('open', switcher);
76 // Adjust the toggle text.
77 $toggle
78 .find('.action')
79 // Expand Structure, Collapse Structure.
80 .text((switcher) ? ui.handleClose : ui.handleOpen);
81 }
82
83 /**
84 * Add markup to the menu elements.
85 *
86 * Items with sub-elements have a list toggle attached to them. Menu item
87 * links and the corresponding list toggle are wrapped with in a div
88 * classed with .toolbar-box. The .toolbar-box div provides a positioning
89 * context for the item list toggle.
90 *
91 * @param {jQuery} $menu
92 * The root of the menu to be initialized.
93 */
94 function initItems($menu) {
95 const options = {
96 class: 'toolbar-icon toolbar-handle',
97 action: ui.handleOpen,
98 text: '',
99 };
100 // Initialize items and their links.
101 $menu.find('li > a').wrap('<div class="toolbar-box">');
102 // Add a handle to each list item if it has a menu.
103 $menu.find('li').each((index, element) => {
104 const $item = $(element);
105 if ($item.children('ul.toolbar-menu').length) {
106 const $box = $item.children('.toolbar-box');
107 options.text = Drupal.t('@label', { '@label': $box.find('a').text() });
108 $item.children('.toolbar-box')
109 .append(Drupal.theme('toolbarMenuItemToggle', options));
110 }
111 });
112 }
113
114 /**
115 * Adds a level class to each list based on its depth in the menu.
116 *
117 * This function is called recursively on each sub level of lists elements
118 * until the depth of the menu is exhausted.
119 *
120 * @param {jQuery} $lists
121 * A jQuery object of ul elements.
122 *
123 * @param {number} level
124 * The current level number to be assigned to the list elements.
125 */
126 function markListLevels($lists, level) {
127 level = (!level) ? 1 : level;
128 const $lis = $lists.children('li').addClass(`level-${level}`);
129 $lists = $lis.children('ul');
130 if ($lists.length) {
131 markListLevels($lists, level + 1);
132 }
133 }
134
135 /**
136 * On page load, open the active menu item.
137 *
138 * Marks the trail of the active link in the menu back to the root of the
139 * menu with .menu-item--active-trail.
140 *
141 * @param {jQuery} $menu
142 * The root of the menu.
143 */
144 function openActiveItem($menu) {
145 const pathItem = $menu.find(`a[href="${location.pathname}"]`);
146 if (pathItem.length && !activeItem) {
147 activeItem = location.pathname;
148 }
149 if (activeItem) {
150 const $activeItem = $menu.find(`a[href="${activeItem}"]`).addClass('menu-item--active');
151 const $activeTrail = $activeItem.parentsUntil('.root', 'li').addClass('menu-item--active-trail');
152 toggleList($activeTrail, true);
153 }
154 }
155
156 // Return the jQuery object.
157 return this.each(function (selector) {
158 const $menu = $(this).once('toolbar-menu');
159 if ($menu.length) {
160 // Bind event handlers.
161 $menu
162 .on('click.toolbar', '.toolbar-box', toggleClickHandler)
163 .on('click.toolbar', '.toolbar-box a', linkClickHandler);
164
165 $menu.addClass('root');
166 initItems($menu);
167 markListLevels($menu);
168 // Restore previous and active states.
169 openActiveItem($menu);
170 }
171 });
172 };
173
174 /**
175 * A toggle is an interactive element often bound to a click handler.
176 *
177 * @param {object} options
178 * Options for the button.
179 * @param {string} options.class
180 * Class to set on the button.
181 * @param {string} options.action
182 * Action for the button.
183 * @param {string} options.text
184 * Used as label for the button.
185 *
186 * @return {string}
187 * A string representing a DOM fragment.
188 */
189 Drupal.theme.toolbarMenuItemToggle = function (options) {
190 return `<button class="${options.class}"><span class="action">${options.action}</span><span class="label">${options.text}</span></button>`;
191 };
192 }(jQuery, Drupal, drupalSettings));