Added Entity and Entity Reference Revisions which got dropped somewhere along the...
[yaffs-website] / web / core / modules / ckeditor / js / views / KeyboardView.es6.js
1 /**
2  * @file
3  * Backbone View providing the aural view of CKEditor keyboard UX configuration.
4  */
5
6 (function($, Drupal, Backbone, _) {
7   Drupal.ckeditor.KeyboardView = Backbone.View.extend(
8     /** @lends Drupal.ckeditor.KeyboardView# */ {
9       /**
10        * Backbone View for CKEditor toolbar configuration; keyboard UX.
11        *
12        * @constructs
13        *
14        * @augments Backbone.View
15        */
16       initialize() {
17         // Add keyboard arrow support.
18         this.$el.on(
19           'keydown.ckeditor',
20           '.ckeditor-buttons a, .ckeditor-multiple-buttons a',
21           this.onPressButton.bind(this),
22         );
23         this.$el.on(
24           'keydown.ckeditor',
25           '[data-drupal-ckeditor-type="group"]',
26           this.onPressGroup.bind(this),
27         );
28       },
29
30       /**
31        * @inheritdoc
32        */
33       render() {},
34
35       /**
36        * Handles keypresses on a CKEditor configuration button.
37        *
38        * @param {jQuery.Event} event
39        *   The keypress event triggered.
40        */
41       onPressButton(event) {
42         const upDownKeys = [
43           38, // Up arrow.
44           63232, // Safari up arrow.
45           40, // Down arrow.
46           63233, // Safari down arrow.
47         ];
48         const leftRightKeys = [
49           37, // Left arrow.
50           63234, // Safari left arrow.
51           39, // Right arrow.
52           63235, // Safari right arrow.
53         ];
54
55         // Respond to an enter key press. Prevent the bubbling of the enter key
56         // press to the button group parent element.
57         if (event.keyCode === 13) {
58           event.stopPropagation();
59         }
60
61         // Only take action when a direction key is pressed.
62         if (_.indexOf(_.union(upDownKeys, leftRightKeys), event.keyCode) > -1) {
63           let view = this;
64           let $target = $(event.currentTarget);
65           let $button = $target.parent();
66           const $container = $button.parent();
67           let $group = $button.closest('.ckeditor-toolbar-group');
68           let $row;
69           const containerType = $container.data(
70             'drupal-ckeditor-button-sorting',
71           );
72           const $availableButtons = this.$el.find(
73             '[data-drupal-ckeditor-button-sorting="source"]',
74           );
75           const $activeButtons = this.$el.find('.ckeditor-toolbar-active');
76           // The current location of the button, just in case it needs to be put
77           // back.
78           const $originalGroup = $group;
79           let dir;
80
81           // Move available buttons between their container and the active
82           // toolbar.
83           if (containerType === 'source') {
84             // Move the button to the active toolbar configuration when the down
85             // or up keys are pressed.
86             if (_.indexOf([40, 63233], event.keyCode) > -1) {
87               // Move the button to the first row, first button group index
88               // position.
89               $activeButtons
90                 .find('.ckeditor-toolbar-group-buttons')
91                 .eq(0)
92                 .prepend($button);
93             }
94           } else if (containerType === 'target') {
95             // Move buttons between sibling buttons in a group and between groups.
96             if (_.indexOf(leftRightKeys, event.keyCode) > -1) {
97               // Move left.
98               const $siblings = $container.children();
99               const index = $siblings.index($button);
100               if (_.indexOf([37, 63234], event.keyCode) > -1) {
101                 // Move between sibling buttons.
102                 if (index > 0) {
103                   $button.insertBefore($container.children().eq(index - 1));
104                 }
105                 // Move between button groups and rows.
106                 else {
107                   // Move between button groups.
108                   $group = $container.parent().prev();
109                   if ($group.length > 0) {
110                     $group
111                       .find('.ckeditor-toolbar-group-buttons')
112                       .append($button);
113                   }
114                   // Wrap between rows.
115                   else {
116                     $container
117                       .closest('.ckeditor-row')
118                       .prev()
119                       .find('.ckeditor-toolbar-group')
120                       .not('.placeholder')
121                       .find('.ckeditor-toolbar-group-buttons')
122                       .eq(-1)
123                       .append($button);
124                   }
125                 }
126               }
127               // Move right.
128               else if (_.indexOf([39, 63235], event.keyCode) > -1) {
129                 // Move between sibling buttons.
130                 if (index < $siblings.length - 1) {
131                   $button.insertAfter($container.children().eq(index + 1));
132                 }
133                 // Move between button groups. Moving right at the end of a row
134                 // will create a new group.
135                 else {
136                   $container
137                     .parent()
138                     .next()
139                     .find('.ckeditor-toolbar-group-buttons')
140                     .prepend($button);
141                 }
142               }
143             }
144             // Move buttons between rows and the available button set.
145             else if (_.indexOf(upDownKeys, event.keyCode) > -1) {
146               dir =
147                 _.indexOf([38, 63232], event.keyCode) > -1 ? 'prev' : 'next';
148               $row = $container.closest('.ckeditor-row')[dir]();
149               // Move the button back into the available button set.
150               if (dir === 'prev' && $row.length === 0) {
151                 // If this is a divider, just destroy it.
152                 if ($button.data('drupal-ckeditor-type') === 'separator') {
153                   $button.off().remove();
154                   // Focus on the first button in the active toolbar.
155                   $activeButtons
156                     .find('.ckeditor-toolbar-group-buttons')
157                     .eq(0)
158                     .children()
159                     .eq(0)
160                     .children()
161                     .trigger('focus');
162                 }
163                 // Otherwise, move it.
164                 else {
165                   $availableButtons.prepend($button);
166                 }
167               } else {
168                 $row
169                   .find('.ckeditor-toolbar-group-buttons')
170                   .eq(0)
171                   .prepend($button);
172               }
173             }
174           }
175           // Move dividers between their container and the active toolbar.
176           else if (containerType === 'dividers') {
177             // Move the button to the active toolbar configuration when the down
178             // or up keys are pressed.
179             if (_.indexOf([40, 63233], event.keyCode) > -1) {
180               // Move the button to the first row, first button group index
181               // position.
182               $button = $button.clone(true);
183               $activeButtons
184                 .find('.ckeditor-toolbar-group-buttons')
185                 .eq(0)
186                 .prepend($button);
187               $target = $button.children();
188             }
189           }
190
191           view = this;
192           // Attempt to move the button to the new toolbar position.
193           Drupal.ckeditor.registerButtonMove(this, $button, result => {
194             // Put the button back if the registration failed.
195             // If the button was in a row, then it was in the active toolbar
196             // configuration. The button was probably placed in a new group, but
197             // that action was canceled.
198             if (!result && $originalGroup) {
199               $originalGroup.find('.ckeditor-buttons').append($button);
200             }
201             // Otherwise refresh the sortables to acknowledge the new button
202             // positions.
203             else {
204               view.$el.find('.ui-sortable').sortable('refresh');
205             }
206             // Refocus the target button so that the user can continue from a
207             // known place.
208             $target.trigger('focus');
209           });
210
211           event.preventDefault();
212           event.stopPropagation();
213         }
214       },
215
216       /**
217        * Handles keypresses on a CKEditor configuration group.
218        *
219        * @param {jQuery.Event} event
220        *   The keypress event triggered.
221        */
222       onPressGroup(event) {
223         const upDownKeys = [
224           38, // Up arrow.
225           63232, // Safari up arrow.
226           40, // Down arrow.
227           63233, // Safari down arrow.
228         ];
229         const leftRightKeys = [
230           37, // Left arrow.
231           63234, // Safari left arrow.
232           39, // Right arrow.
233           63235, // Safari right arrow.
234         ];
235
236         // Respond to an enter key press.
237         if (event.keyCode === 13) {
238           const view = this;
239           // Open the group renaming dialog in the next evaluation cycle so that
240           // this event can be cancelled and the bubbling wiped out. Otherwise,
241           // Firefox has issues because the page focus is shifted to the dialog
242           // along with the keydown event.
243           window.setTimeout(() => {
244             Drupal.ckeditor.openGroupNameDialog(view, $(event.currentTarget));
245           }, 0);
246           event.preventDefault();
247           event.stopPropagation();
248         }
249
250         // Respond to direction key presses.
251         if (_.indexOf(_.union(upDownKeys, leftRightKeys), event.keyCode) > -1) {
252           const $group = $(event.currentTarget);
253           const $container = $group.parent();
254           const $siblings = $container.children();
255           let index;
256           let dir;
257           // Move groups between sibling groups.
258           if (_.indexOf(leftRightKeys, event.keyCode) > -1) {
259             index = $siblings.index($group);
260             // Move left between sibling groups.
261             if (_.indexOf([37, 63234], event.keyCode) > -1) {
262               if (index > 0) {
263                 $group.insertBefore($siblings.eq(index - 1));
264               }
265               // Wrap between rows. Insert the group before the placeholder group
266               // at the end of the previous row.
267               else {
268                 const $rowChildElement = $container
269                   .closest('.ckeditor-row')
270                   .prev()
271                   .find('.ckeditor-toolbar-groups')
272                   .children()
273                   .eq(-1);
274                 $group.insertBefore($rowChildElement);
275               }
276             }
277             // Move right between sibling groups.
278             else if (_.indexOf([39, 63235], event.keyCode) > -1) {
279               // Move to the right if the next group is not a placeholder.
280               if (!$siblings.eq(index + 1).hasClass('placeholder')) {
281                 $group.insertAfter($container.children().eq(index + 1));
282               }
283               // Wrap group between rows.
284               else {
285                 $container
286                   .closest('.ckeditor-row')
287                   .next()
288                   .find('.ckeditor-toolbar-groups')
289                   .prepend($group);
290               }
291             }
292           }
293           // Move groups between rows.
294           else if (_.indexOf(upDownKeys, event.keyCode) > -1) {
295             dir = _.indexOf([38, 63232], event.keyCode) > -1 ? 'prev' : 'next';
296             $group
297               .closest('.ckeditor-row')
298               [dir]()
299               .find('.ckeditor-toolbar-groups')
300               .eq(0)
301               .prepend($group);
302           }
303
304           Drupal.ckeditor.registerGroupMove(this, $group);
305           $group.trigger('focus');
306           event.preventDefault();
307           event.stopPropagation();
308         }
309       },
310     },
311   );
312 })(jQuery, Drupal, Backbone, _);