Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / web / core / modules / settings_tray / js / settings_tray.es6.js
1 /**
2  * @file
3  * Drupal's Settings Tray library.
4  *
5  * @private
6  */
7
8 (($, Drupal) => {
9   const blockConfigureSelector = '[data-settings-tray-edit]';
10   const toggleEditSelector = '[data-drupal-settingstray="toggle"]';
11   const itemsToToggleSelector =
12     '[data-off-canvas-main-canvas], #toolbar-bar, [data-drupal-settingstray="editable"] a, [data-drupal-settingstray="editable"] button';
13   const contextualItemsSelector =
14     '[data-contextual-id] a, [data-contextual-id] button';
15   const quickEditItemSelector = '[data-quickedit-entity-id]';
16
17   /**
18    * Prevent default click events except contextual links.
19    *
20    * In edit mode the default action of click events is suppressed.
21    *
22    * @param {jQuery.Event} event
23    *   The click event.
24    */
25   function preventClick(event) {
26     // Do not prevent contextual links.
27     if ($(event.target).closest('.contextual-links').length) {
28       return;
29     }
30     event.preventDefault();
31   }
32
33   /**
34    * Close any active toolbar tray before entering edit mode.
35    */
36   function closeToolbarTrays() {
37     $(Drupal.toolbar.models.toolbarModel.get('activeTab')).trigger('click');
38   }
39
40   /**
41    * Disables the QuickEdit module editor if open.
42    */
43   function disableQuickEdit() {
44     $('.quickedit-toolbar button.action-cancel').trigger('click');
45   }
46
47   /**
48    * Closes/removes off-canvas.
49    */
50   function closeOffCanvas() {
51     $('.ui-dialog-off-canvas .ui-dialog-titlebar-close').trigger('click');
52   }
53
54   /**
55    * Gets all items that should be toggled with class during edit mode.
56    *
57    * @return {jQuery}
58    *   Items that should be toggled.
59    */
60   function getItemsToToggle() {
61     return $(itemsToToggleSelector).not(contextualItemsSelector);
62   }
63
64   /**
65    * Helper to switch edit mode state.
66    *
67    * @param {boolean} editMode
68    *   True enable edit mode, false disable edit mode.
69    */
70   function setEditModeState(editMode) {
71     if (!document.querySelector('[data-off-canvas-main-canvas]')) {
72       throw new Error(
73         'data-off-canvas-main-canvas is missing from settings-tray-page-wrapper.html.twig',
74       );
75     }
76     editMode = !!editMode;
77     const $editButton = $(toggleEditSelector);
78     let $editables;
79     // Turn on edit mode.
80     if (editMode) {
81       $editButton.text(Drupal.t('Editing'));
82       closeToolbarTrays();
83
84       $editables = $('[data-drupal-settingstray="editable"]').once(
85         'settingstray',
86       );
87       if ($editables.length) {
88         // Use event capture to prevent clicks on links.
89         document
90           .querySelector('[data-off-canvas-main-canvas]')
91           .addEventListener('click', preventClick, true);
92         /**
93          * When a click occurs try and find the settings-tray edit link
94          * and click it.
95          */
96         $editables.not(contextualItemsSelector).on('click.settingstray', e => {
97           // Contextual links are allowed to function in Edit mode.
98           if (
99             $(e.target).closest('.contextual').length ||
100             !localStorage.getItem('Drupal.contextualToolbar.isViewing')
101           ) {
102             return;
103           }
104           $(e.currentTarget)
105             .find(blockConfigureSelector)
106             .trigger('click');
107           disableQuickEdit();
108         });
109         $(quickEditItemSelector)
110           .not(contextualItemsSelector)
111           .on('click.settingstray', e => {
112             /**
113              * For all non-contextual links or the contextual QuickEdit link
114              * close the off-canvas dialog.
115              */
116             if (
117               !$(e.target)
118                 .parent()
119                 .hasClass('contextual') ||
120               $(e.target)
121                 .parent()
122                 .hasClass('quickedit')
123             ) {
124               closeOffCanvas();
125             }
126             // Do not trigger if target is quick edit link to avoid loop.
127             if (
128               $(e.target)
129                 .parent()
130                 .hasClass('contextual') ||
131               $(e.target)
132                 .parent()
133                 .hasClass('quickedit')
134             ) {
135               return;
136             }
137             $(e.currentTarget)
138               .find('li.quickedit a')
139               .trigger('click');
140           });
141       }
142     }
143     // Disable edit mode.
144     else {
145       $editables = $('[data-drupal-settingstray="editable"]').removeOnce(
146         'settingstray',
147       );
148       if ($editables.length) {
149         document
150           .querySelector('[data-off-canvas-main-canvas]')
151           .removeEventListener('click', preventClick, true);
152         $editables.off('.settingstray');
153         $(quickEditItemSelector).off('.settingstray');
154       }
155
156       $editButton.text(Drupal.t('Edit'));
157       closeOffCanvas();
158       disableQuickEdit();
159     }
160     getItemsToToggle().toggleClass('js-settings-tray-edit-mode', editMode);
161     $('.edit-mode-inactive').toggleClass('visually-hidden', editMode);
162   }
163
164   /**
165    * Helper to check the state of the settings-tray mode.
166    *
167    * @todo don't use a class for this.
168    *
169    * @return {boolean}
170    *   State of the settings-tray edit mode.
171    */
172   function isInEditMode() {
173     return $('#toolbar-bar').hasClass('js-settings-tray-edit-mode');
174   }
175
176   /**
177    * Helper to toggle Edit mode.
178    */
179   function toggleEditMode() {
180     setEditModeState(!isInEditMode());
181   }
182
183   /**
184    * Prepares Ajax links to work with off-canvas and Settings Tray module.
185    */
186   function prepareAjaxLinks() {
187     // Find all Ajax instances that use the 'off_canvas' renderer.
188     Drupal.ajax.instances
189       /**
190        * If there is an element and the renderer is 'off_canvas' then we want
191        * to add our changes.
192        */
193       .filter(
194         instance =>
195           instance &&
196           $(instance.element).attr('data-dialog-renderer') === 'off_canvas',
197       )
198       /**
199        * Loop through all Ajax instances that use the 'off_canvas' renderer to
200        * set active editable ID.
201        */
202       .forEach(instance => {
203         // Check to make sure existing dialogOptions aren't overridden.
204         if (!instance.options.data.hasOwnProperty('dialogOptions')) {
205           instance.options.data.dialogOptions = {};
206         }
207         instance.options.data.dialogOptions.settingsTrayActiveEditableId = $(
208           instance.element,
209         )
210           .parents('.settings-tray-editable')
211           .attr('id');
212         instance.progress = { type: 'fullscreen' };
213       });
214   }
215
216   /**
217    * Reacts to contextual links being added.
218    *
219    * @param {jQuery.Event} event
220    *   The `drupalContextualLinkAdded` event.
221    * @param {object} data
222    *   An object containing the data relevant to the event.
223    *
224    * @listens event:drupalContextualLinkAdded
225    */
226   $(document).on('drupalContextualLinkAdded', (event, data) => {
227     /**
228      * When contextual links are add we need to set extra properties on the
229      * instances in Drupal.ajax.instances for them to work with Edit Mode.
230      */
231     prepareAjaxLinks();
232
233     // When the first contextual link is added to the page set Edit Mode.
234     $('body')
235       .once('settings_tray.edit_mode_init')
236       .each(() => {
237         const editMode =
238           localStorage.getItem('Drupal.contextualToolbar.isViewing') ===
239           'false';
240         if (editMode) {
241           setEditModeState(true);
242         }
243       });
244
245     /**
246      * Bind a listener to all 'Quick edit' links for blocks. Click "Edit"
247      * button in toolbar to force Contextual Edit which starts Settings Tray
248      * edit mode also.
249      */
250     data.$el.find(blockConfigureSelector).on('click.settingstray', () => {
251       if (!isInEditMode()) {
252         $(toggleEditSelector)
253           .trigger('click')
254           .trigger('click.settings_tray');
255       }
256       /**
257        * Always disable QuickEdit regardless of whether "EditMode" was just
258        * enabled.
259        */
260       disableQuickEdit();
261     });
262   });
263
264   $(document).on('keyup.settingstray', e => {
265     if (isInEditMode() && e.keyCode === 27) {
266       Drupal.announce(Drupal.t('Exited edit mode.'));
267       toggleEditMode();
268     }
269   });
270
271   /**
272    * Toggle the js-settings-tray-edit-mode class on items that we want to
273    * disable while in edit mode.
274    *
275    * @type {Drupal~behavior}
276    *
277    * @prop {Drupal~behaviorAttach} attach
278    *   Toggle the js-settings-tray-edit-mode class.
279    */
280   Drupal.behaviors.toggleEditMode = {
281     attach() {
282       $(toggleEditSelector)
283         .once('settingstray')
284         .on('click.settingstray', toggleEditMode);
285     },
286   };
287
288   // Manage Active editable class on opening and closing of the dialog.
289   $(window).on({
290     'dialog:beforecreate': (event, dialog, $element, settings) => {
291       if ($element.is('#drupal-off-canvas')) {
292         $('body .settings-tray-active-editable').removeClass(
293           'settings-tray-active-editable',
294         );
295         const $activeElement = $(`#${settings.settingsTrayActiveEditableId}`);
296         if ($activeElement.length) {
297           $activeElement.addClass('settings-tray-active-editable');
298         }
299       }
300     },
301     'dialog:beforeclose': (event, dialog, $element) => {
302       if ($element.is('#drupal-off-canvas')) {
303         $('body .settings-tray-active-editable').removeClass(
304           'settings-tray-active-editable',
305         );
306       }
307     },
308   });
309 })(jQuery, Drupal);