db backup prior to drupal security update
[yaffs-website] / web / core / modules / outside_in / js / outside_in.js
1 /**
2  * @file
3  * Drupal's Settings Tray library.
4  */
5
6 (function ($, Drupal) {
7
8   'use strict';
9
10   var blockConfigureSelector = '[data-outside-in-edit]';
11   var toggleEditSelector = '[data-drupal-outsidein="toggle"]';
12   var itemsToToggleSelector = '[data-off-canvas-main-canvas], #toolbar-bar, [data-drupal-outsidein="editable"] a, [data-drupal-outsidein="editable"] button';
13   var contextualItemsSelector = '[data-contextual-id] a, [data-contextual-id] button';
14   var quickEditItemSelector = '[data-quickedit-entity-id]';
15
16   /**
17    * Reacts to contextual links being added.
18    *
19    * @param {jQuery.Event} event
20    *   The `drupalContextualLinkAdded` event.
21    * @param {object} data
22    *   An object containing the data relevant to the event.
23    *
24    * @listens event:drupalContextualLinkAdded
25    */
26   $(document).on('drupalContextualLinkAdded', function (event, data) {
27     // Bind Ajax behaviors to all items showing the class.
28     // @todo Fix contextual links to work with use-ajax links in
29     //    https://www.drupal.org/node/2764931.
30     Drupal.attachBehaviors(data.$el[0]);
31
32     // Bind a listener to all 'Quick edit' links for blocks
33     // Click "Edit" button in toolbar to force Contextual Edit which starts
34     // Settings Tray edit mode also.
35     data.$el.find(blockConfigureSelector)
36       .on('click.outsidein', function () {
37         if (!isInEditMode()) {
38           $(toggleEditSelector).trigger('click').trigger('click.outside_in');
39         }
40         // Always disable QuickEdit regardless of whether "EditMode" was just enabled.
41         disableQuickEdit();
42       });
43   });
44
45   $(document).on('keyup.outsidein', function (e) {
46     if (isInEditMode() && e.keyCode === 27) {
47       Drupal.announce(
48         Drupal.t('Exited edit mode.')
49       );
50       toggleEditMode();
51     }
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 check the state of the outside-in mode.
66    *
67    * @todo don't use a class for this.
68    *
69    * @return {boolean}
70    *  State of the outside-in edit mode.
71    */
72   function isInEditMode() {
73     return $('#toolbar-bar').hasClass('js-outside-in-edit-mode');
74   }
75
76   /**
77    * Helper to toggle Edit mode.
78    */
79   function toggleEditMode() {
80     setEditModeState(!isInEditMode());
81   }
82
83   /**
84    * Prevent default click events except contextual links.
85    *
86    * In edit mode the default action of click events is suppressed.
87    *
88    * @param {jQuery.Event} event
89    *   The click event.
90    */
91   function preventClick(event) {
92     // Do not prevent contextual links.
93     if ($(event.target).closest('.contextual-links').length) {
94       return;
95     }
96     event.preventDefault();
97   }
98
99   /**
100    * Close any active toolbar tray before entering edit mode.
101    */
102   function closeToolbarTrays() {
103     $(Drupal.toolbar.models.toolbarModel.get('activeTab')).trigger('click');
104   }
105
106   /**
107    * Disables the QuickEdit module editor if open.
108    */
109   function disableQuickEdit() {
110     $('.quickedit-toolbar button.action-cancel').trigger('click');
111   }
112
113   /**
114    * Closes/removes off-canvas.
115    */
116   function closeOffCanvas() {
117     $('.ui-dialog-off-canvas .ui-dialog-titlebar-close').trigger('click');
118   }
119
120   /**
121    *  Helper to switch edit mode state.
122    *
123    * @param {boolean} editMode
124    *  True enable edit mode, false disable edit mode.
125    */
126   function setEditModeState(editMode) {
127     if (!document.querySelector('[data-off-canvas-main-canvas]')) {
128       throw new Error('data-off-canvas-main-canvas is missing from outside-in-page-wrapper.html.twig');
129     }
130     editMode = !!editMode;
131     var $editButton = $(toggleEditSelector);
132     var $editables;
133     // Turn on edit mode.
134     if (editMode) {
135       $editButton.text(Drupal.t('Editing'));
136       closeToolbarTrays();
137
138       $editables = $('[data-drupal-outsidein="editable"]').once('outsidein');
139       if ($editables.length) {
140         // Use event capture to prevent clicks on links.
141         document.querySelector('[data-off-canvas-main-canvas]').addEventListener('click', preventClick, true);
142
143         // When a click occurs try and find the outside-in edit link
144         // and click it.
145         $editables
146           .not(contextualItemsSelector)
147           .on('click.outsidein', function (e) {
148             // Contextual links are allowed to function in Edit mode.
149             if ($(e.target).closest('.contextual').length || !localStorage.getItem('Drupal.contextualToolbar.isViewing')) {
150               return;
151             }
152             $(e.currentTarget).find(blockConfigureSelector).trigger('click');
153             disableQuickEdit();
154           });
155         $(quickEditItemSelector)
156           .not(contextualItemsSelector)
157           .on('click.outsidein', function (e) {
158             // For all non-contextual links or the contextual QuickEdit link close the off-canvas dialog.
159             if (!$(e.target).parent().hasClass('contextual') || $(e.target).parent().hasClass('quickedit')) {
160               closeOffCanvas();
161             }
162             // Do not trigger if target is quick edit link to avoid loop.
163             if ($(e.target).parent().hasClass('contextual') || $(e.target).parent().hasClass('quickedit')) {
164               return;
165             }
166             $(e.currentTarget).find('li.quickedit a').trigger('click');
167           });
168       }
169     }
170     // Disable edit mode.
171     else {
172       $editables = $('[data-drupal-outsidein="editable"]').removeOnce('outsidein');
173       if ($editables.length) {
174         document.querySelector('[data-off-canvas-main-canvas]').removeEventListener('click', preventClick, true);
175         $editables.off('.outsidein');
176         $(quickEditItemSelector).off('.outsidein');
177       }
178
179       $editButton.text(Drupal.t('Edit'));
180       closeOffCanvas();
181       disableQuickEdit();
182     }
183     getItemsToToggle().toggleClass('js-outside-in-edit-mode', editMode);
184     $('.edit-mode-inactive').toggleClass('visually-hidden', editMode);
185   }
186
187   /**
188    * Attaches contextual's edit toolbar tab behavior.
189    *
190    * @type {Drupal~behavior}
191    *
192    * @prop {Drupal~behaviorAttach} attach
193    *   Attaches contextual toolbar behavior on a contextualToolbar-init event.
194    */
195   Drupal.behaviors.outsideInEdit = {
196     attach: function () {
197       var editMode = localStorage.getItem('Drupal.contextualToolbar.isViewing') === 'false';
198       if (editMode) {
199         setEditModeState(true);
200       }
201     }
202   };
203
204   /**
205    * Toggle the js-outside-edit-mode class on items that we want to disable while in edit mode.
206    *
207    * @type {Drupal~behavior}
208    *
209    * @prop {Drupal~behaviorAttach} attach
210    *   Toggle the js-outside-edit-mode class.
211    */
212   Drupal.behaviors.toggleEditMode = {
213     attach: function () {
214
215       $(toggleEditSelector).once('outsidein').on('click.outsidein', toggleEditMode);
216
217       var search = Drupal.ajax.WRAPPER_FORMAT + '=drupal_dialog';
218       var replace = Drupal.ajax.WRAPPER_FORMAT + '=drupal_dialog_off_canvas';
219       // Loop through all Ajax links and change the format to dialog-off-canvas when
220       // needed.
221       Drupal.ajax.instances
222         .filter(function (instance) {
223           var hasElement = instance && !!instance.element;
224           var rendererOffCanvas = false;
225           var wrapperOffCanvas = false;
226           if (hasElement) {
227             rendererOffCanvas = $(instance.element).attr('data-dialog-renderer') === 'off_canvas';
228             wrapperOffCanvas = instance.options.url.indexOf('drupal_dialog_off_canvas') === -1;
229           }
230           return hasElement && rendererOffCanvas && wrapperOffCanvas;
231         })
232         .forEach(function (instance) {
233           // @todo Move logic for data-dialog-renderer attribute into ajax.js
234           //   https://www.drupal.org/node/2784443
235           instance.options.url = instance.options.url.replace(search, replace);
236           // Check to make sure existing dialogOptions aren't overridden.
237           if (!('dialogOptions' in instance.options.data)) {
238             instance.options.data.dialogOptions = {};
239           }
240           instance.options.data.dialogOptions.outsideInActiveEditableId = $(instance.element).parents('.outside-in-editable').attr('id');
241           instance.progress = {type: 'fullscreen'};
242         });
243     }
244   };
245
246   // Manage Active editable class on opening and closing of the dialog.
247   $(window).on({
248     'dialog:beforecreate': function (event, dialog, $element, settings) {
249       if ($element.is('#drupal-off-canvas')) {
250         $('body .outside-in-active-editable').removeClass('outside-in-active-editable');
251         var $activeElement = $('#' + settings.outsideInActiveEditableId);
252         if ($activeElement.length) {
253           $activeElement.addClass('outside-in-active-editable');
254           settings.dialogClass += ' ui-dialog-outside-in';
255         }
256       }
257     },
258     'dialog:beforeclose': function (event, dialog, $element) {
259       if ($element.is('#drupal-off-canvas')) {
260         $('body .outside-in-active-editable').removeClass('outside-in-active-editable');
261       }
262     }
263   });
264
265 })(jQuery, Drupal);