Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / web / core / modules / ckeditor / js / views / VisualView.es6.js
1 /**
2  * @file
3  * A Backbone View that provides the visual UX view of CKEditor toolbar
4  *   configuration.
5  */
6
7 (function(Drupal, Backbone, $) {
8   Drupal.ckeditor.VisualView = Backbone.View.extend(
9     /** @lends Drupal.ckeditor.VisualView# */ {
10       events: {
11         'click .ckeditor-toolbar-group-name': 'onGroupNameClick',
12         'click .ckeditor-groupnames-toggle': 'onGroupNamesToggleClick',
13         'click .ckeditor-add-new-group button': 'onAddGroupButtonClick',
14       },
15
16       /**
17        * Backbone View for CKEditor toolbar configuration; visual UX.
18        *
19        * @constructs
20        *
21        * @augments Backbone.View
22        */
23       initialize() {
24         this.listenTo(
25           this.model,
26           'change:isDirty change:groupNamesVisible',
27           this.render,
28         );
29
30         // Add a toggle for the button group names.
31         $(Drupal.theme('ckeditorButtonGroupNamesToggle')).prependTo(
32           this.$el.find('#ckeditor-active-toolbar').parent(),
33         );
34
35         this.render();
36       },
37
38       /**
39        * Render function for rendering the toolbar configuration.
40        *
41        * @param {*} model
42        *   Model used for the view.
43        * @param {string} [value]
44        *   The value that was changed.
45        * @param {object} changedAttributes
46        *   The attributes that was changed.
47        *
48        * @return {Drupal.ckeditor.VisualView}
49        *   The {@link Drupal.ckeditor.VisualView} object.
50        */
51       render(model, value, changedAttributes) {
52         this.insertPlaceholders();
53         this.applySorting();
54
55         // Toggle button group names.
56         let groupNamesVisible = this.model.get('groupNamesVisible');
57         // If a button was just placed in the active toolbar, ensure that the
58         // button group names are visible.
59         if (
60           changedAttributes &&
61           changedAttributes.changes &&
62           changedAttributes.changes.isDirty
63         ) {
64           this.model.set({ groupNamesVisible: true }, { silent: true });
65           groupNamesVisible = true;
66         }
67         this.$el
68           .find('[data-toolbar="active"]')
69           .toggleClass('ckeditor-group-names-are-visible', groupNamesVisible);
70         this.$el
71           .find('.ckeditor-groupnames-toggle')
72           .text(
73             groupNamesVisible
74               ? Drupal.t('Hide group names')
75               : Drupal.t('Show group names'),
76           )
77           .attr('aria-pressed', groupNamesVisible);
78
79         return this;
80       },
81
82       /**
83        * Handles clicks to a button group name.
84        *
85        * @param {jQuery.Event} event
86        *   The click event on the button group.
87        */
88       onGroupNameClick(event) {
89         const $group = $(event.currentTarget).closest(
90           '.ckeditor-toolbar-group',
91         );
92         Drupal.ckeditor.openGroupNameDialog(this, $group);
93
94         event.stopPropagation();
95         event.preventDefault();
96       },
97
98       /**
99        * Handles clicks on the button group names toggle button.
100        *
101        * @param {jQuery.Event} event
102        *   The click event on the toggle button.
103        */
104       onGroupNamesToggleClick(event) {
105         this.model.set(
106           'groupNamesVisible',
107           !this.model.get('groupNamesVisible'),
108         );
109         event.preventDefault();
110       },
111
112       /**
113        * Prompts the user to provide a name for a new button group; inserts it.
114        *
115        * @param {jQuery.Event} event
116        *   The event of the button click.
117        */
118       onAddGroupButtonClick(event) {
119         /**
120          * Inserts a new button if the openGroupNameDialog function returns true.
121          *
122          * @param {bool} success
123          *   A flag that indicates if the user created a new group (true) or
124          *   canceled out of the dialog (false).
125          * @param {jQuery} $group
126          *   A jQuery DOM fragment that represents the new button group. It has
127          *   not been added to the DOM yet.
128          */
129         function insertNewGroup(success, $group) {
130           if (success) {
131             $group.appendTo(
132               $(event.currentTarget)
133                 .closest('.ckeditor-row')
134                 .children('.ckeditor-toolbar-groups'),
135             );
136             // Focus on the new group.
137             $group.trigger('focus');
138           }
139         }
140
141         // Pass in a DOM fragment of a placeholder group so that the new group
142         // name can be applied to it.
143         Drupal.ckeditor.openGroupNameDialog(
144           this,
145           $(Drupal.theme('ckeditorToolbarGroup')),
146           insertNewGroup,
147         );
148
149         event.preventDefault();
150       },
151
152       /**
153        * Handles jQuery Sortable stop sort of a button group.
154        *
155        * @param {jQuery.Event} event
156        *   The event triggered on the group drag.
157        * @param {object} ui
158        *   A jQuery.ui.sortable argument that contains information about the
159        *   elements involved in the sort action.
160        */
161       endGroupDrag(event, ui) {
162         const view = this;
163         Drupal.ckeditor.registerGroupMove(this, ui.item, success => {
164           if (!success) {
165             // Cancel any sorting in the configuration area.
166             view.$el
167               .find('.ckeditor-toolbar-configuration')
168               .find('.ui-sortable')
169               .sortable('cancel');
170           }
171         });
172       },
173
174       /**
175        * Handles jQuery Sortable start sort of a button.
176        *
177        * @param {jQuery.Event} event
178        *   The event triggered on the group drag.
179        * @param {object} ui
180        *   A jQuery.ui.sortable argument that contains information about the
181        *   elements involved in the sort action.
182        */
183       startButtonDrag(event, ui) {
184         this.$el.find('a:focus').trigger('blur');
185
186         // Show the button group names as soon as the user starts dragging.
187         this.model.set('groupNamesVisible', true);
188       },
189
190       /**
191        * Handles jQuery Sortable stop sort of a button.
192        *
193        * @param {jQuery.Event} event
194        *   The event triggered on the button drag.
195        * @param {object} ui
196        *   A jQuery.ui.sortable argument that contains information about the
197        *   elements involved in the sort action.
198        */
199       endButtonDrag(event, ui) {
200         const view = this;
201         Drupal.ckeditor.registerButtonMove(this, ui.item, success => {
202           if (!success) {
203             // Cancel any sorting in the configuration area.
204             view.$el.find('.ui-sortable').sortable('cancel');
205           }
206           // Refocus the target button so that the user can continue from a known
207           // place.
208           ui.item.find('a').trigger('focus');
209         });
210       },
211
212       /**
213        * Invokes jQuery.sortable() on new buttons and groups in a CKEditor config.
214        */
215       applySorting() {
216         // Make the buttons sortable.
217         this.$el
218           .find('.ckeditor-buttons')
219           .not('.ui-sortable')
220           .sortable({
221             // Change this to .ckeditor-toolbar-group-buttons.
222             connectWith: '.ckeditor-buttons',
223             placeholder: 'ckeditor-button-placeholder',
224             forcePlaceholderSize: true,
225             tolerance: 'pointer',
226             cursor: 'move',
227             start: this.startButtonDrag.bind(this),
228             // Sorting within a sortable.
229             stop: this.endButtonDrag.bind(this),
230           })
231           .disableSelection();
232
233         // Add the drag and drop functionality to button groups.
234         this.$el
235           .find('.ckeditor-toolbar-groups')
236           .not('.ui-sortable')
237           .sortable({
238             connectWith: '.ckeditor-toolbar-groups',
239             cancel: '.ckeditor-add-new-group',
240             placeholder: 'ckeditor-toolbar-group-placeholder',
241             forcePlaceholderSize: true,
242             cursor: 'move',
243             stop: this.endGroupDrag.bind(this),
244           });
245
246         // Add the drag and drop functionality to buttons.
247         this.$el.find('.ckeditor-multiple-buttons li').draggable({
248           connectToSortable: '.ckeditor-toolbar-active .ckeditor-buttons',
249           helper: 'clone',
250         });
251       },
252
253       /**
254        * Wraps the invocation of methods to insert blank groups and rows.
255        */
256       insertPlaceholders() {
257         this.insertPlaceholderRow();
258         this.insertNewGroupButtons();
259       },
260
261       /**
262        * Inserts a blank row at the bottom of the CKEditor configuration.
263        */
264       insertPlaceholderRow() {
265         let $rows = this.$el.find('.ckeditor-row');
266         // Add a placeholder row. to the end of the list if one does not exist.
267         if (!$rows.eq(-1).hasClass('placeholder')) {
268           this.$el
269             .find('.ckeditor-toolbar-active')
270             .children('.ckeditor-active-toolbar-configuration')
271             .append(Drupal.theme('ckeditorRow'));
272         }
273         // Update the $rows variable to include the new row.
274         $rows = this.$el.find('.ckeditor-row');
275         // Remove blank rows except the last one.
276         const len = $rows.length;
277         $rows
278           .filter((index, row) => {
279             // Do not remove the last row.
280             if (index + 1 === len) {
281               return false;
282             }
283             return (
284               $(row)
285                 .find('.ckeditor-toolbar-group')
286                 .not('.placeholder').length === 0
287             );
288           })
289           // Then get all rows that are placeholders and remove them.
290           .remove();
291       },
292
293       /**
294        * Inserts a button in each row that will add a new CKEditor button group.
295        */
296       insertNewGroupButtons() {
297         // Insert an add group button to each row.
298         this.$el.find('.ckeditor-row').each(function() {
299           const $row = $(this);
300           const $groups = $row.find('.ckeditor-toolbar-group');
301           const $button = $row.find('.ckeditor-add-new-group');
302           if ($button.length === 0) {
303             $row
304               .children('.ckeditor-toolbar-groups')
305               .append(Drupal.theme('ckeditorNewButtonGroup'));
306           }
307           // If a placeholder group exists, make sure it's at the end of the row.
308           else if (!$groups.eq(-1).hasClass('ckeditor-add-new-group')) {
309             $button.appendTo($row.children('.ckeditor-toolbar-groups'));
310           }
311         });
312       },
313     },
314   );
315 })(Drupal, Backbone, jQuery);