Newer
Older
Alex Pott
committed
/**
* @file
Angie Byron
committed
* Backbone View providing the aural view of CKEditor keyboard UX configuration.
Alex Pott
committed
*/
(function ($, Drupal, Backbone, _) {
Alex Pott
committed
'use strict';
Alex Pott
committed
Jennifer Hodgdon
committed
Drupal.ckeditor.KeyboardView = Backbone.View.extend(/** @lends Drupal.ckeditor.KeyboardView# */{
Alex Pott
committed
/**
Jennifer Hodgdon
committed
* Backbone View for CKEditor toolbar configuration; keyboard UX.
*
* @constructs
*
* @augments Backbone.View
Alex Pott
committed
*/
initialize: function () {
// Add keyboard arrow support.
this.$el.on('keydown.ckeditor', '.ckeditor-buttons a, .ckeditor-multiple-buttons a', this.onPressButton.bind(this));
this.$el.on('keydown.ckeditor', '[data-drupal-ckeditor-type="group"]', this.onPressGroup.bind(this));
},
/**
Jennifer Hodgdon
committed
* @inheritdoc
Alex Pott
committed
*/
render: function () {
},
/**
* Handles keypresses on a CKEditor configuration button.
*
Jennifer Hodgdon
committed
* @param {jQuery.Event} event
Angie Byron
committed
* The keypress event triggered.
Alex Pott
committed
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
*/
onPressButton: function (event) {
var upDownKeys = [
38, // Up arrow.
63232, // Safari up arrow.
40, // Down arrow.
63233 // Safari down arrow.
];
var leftRightKeys = [
37, // Left arrow.
63234, // Safari left arrow.
39, // Right arrow.
63235 // Safari right arrow.
];
// Respond to an enter key press. Prevent the bubbling of the enter key
// press to the button group parent element.
if (event.keyCode === 13) {
event.stopPropagation();
}
// Only take action when a direction key is pressed.
if (_.indexOf(_.union(upDownKeys, leftRightKeys), event.keyCode) > -1) {
var view = this;
var $target = $(event.currentTarget);
var $button = $target.parent();
var $container = $button.parent();
var $group = $button.closest('.ckeditor-toolbar-group');
var $row = $button.closest('.ckeditor-row');
var containerType = $container.data('drupal-ckeditor-button-sorting');
var $availableButtons = this.$el.find('[data-drupal-ckeditor-button-sorting="source"]');
var $activeButtons = this.$el.find('.ckeditor-toolbar-active');
// The current location of the button, just in case it needs to be put
// back.
var $originalGroup = $group;
var dir;
Angie Byron
committed
// Move available buttons between their container and the active
// toolbar.
Alex Pott
committed
if (containerType === 'source') {
Angie Byron
committed
// Move the button to the active toolbar configuration when the down
// or up keys are pressed.
Alex Pott
committed
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
if (_.indexOf([40, 63233], event.keyCode) > -1) {
// Move the button to the first row, first button group index
// position.
$activeButtons.find('.ckeditor-toolbar-group-buttons').eq(0).prepend($button);
}
}
else if (containerType === 'target') {
// Move buttons between sibling buttons in a group and between groups.
if (_.indexOf(leftRightKeys, event.keyCode) > -1) {
// Move left.
var $siblings = $container.children();
var index = $siblings.index($button);
if (_.indexOf([37, 63234], event.keyCode) > -1) {
// Move between sibling buttons.
if (index > 0) {
$button.insertBefore($container.children().eq(index - 1));
}
// Move between button groups and rows.
else {
// Move between button groups.
$group = $container.parent().prev();
if ($group.length > 0) {
$group.find('.ckeditor-toolbar-group-buttons').append($button);
}
// Wrap between rows.
else {
$container.closest('.ckeditor-row').prev().find('.ckeditor-toolbar-group').not('.placeholder').find('.ckeditor-toolbar-group-buttons').eq(-1).append($button);
}
}
}
// Move right.
else if (_.indexOf([39, 63235], event.keyCode) > -1) {
// Move between sibling buttons.
if (index < ($siblings.length - 1)) {
$button.insertAfter($container.children().eq(index + 1));
}
// Move between button groups. Moving right at the end of a row
// will create a new group.
else {
$container.parent().next().find('.ckeditor-toolbar-group-buttons').prepend($button);
}
}
}
// Move buttons between rows and the available button set.
else if (_.indexOf(upDownKeys, event.keyCode) > -1) {
dir = (_.indexOf([38, 63232], event.keyCode) > -1) ? 'prev' : 'next';
$row = $container.closest('.ckeditor-row')[dir]();
// Move the button back into the available button set.
if (dir === 'prev' && $row.length === 0) {
// If this is a divider, just destroy it.
if ($button.data('drupal-ckeditor-type') === 'separator') {
$button
.off()
.remove();
// Focus on the first button in the active toolbar.
$activeButtons.find('.ckeditor-toolbar-group-buttons').eq(0).children().eq(0).children().trigger('focus');
}
// Otherwise, move it.
else {
$availableButtons.prepend($button);
}
}
else {
$row.find('.ckeditor-toolbar-group-buttons').eq(0).prepend($button);
}
}
}
// Move dividers between their container and the active toolbar.
else if (containerType === 'dividers') {
Angie Byron
committed
// Move the button to the active toolbar configuration when the down
// or up keys are pressed.
Alex Pott
committed
if (_.indexOf([40, 63233], event.keyCode) > -1) {
// Move the button to the first row, first button group index
// position.
$button = $button.clone(true);
$activeButtons.find('.ckeditor-toolbar-group-buttons').eq(0).prepend($button);
$target = $button.children();
}
}
view = this;
// Attempt to move the button to the new toolbar position.
Drupal.ckeditor.registerButtonMove(this, $button, function (result) {
// Put the button back if the registration failed.
// If the button was in a row, then it was in the active toolbar
// configuration. The button was probably placed in a new group, but
// that action was canceled.
if (!result && $originalGroup) {
$originalGroup.find('.ckeditor-buttons').append($button);
}
// Otherwise refresh the sortables to acknowledge the new button
// positions.
else {
view.$el.find('.ui-sortable').sortable('refresh');
}
Angie Byron
committed
// Refocus the target button so that the user can continue from a
// known place.
Alex Pott
committed
$target.trigger('focus');
});
event.preventDefault();
event.stopPropagation();
}
},
/**
* Handles keypresses on a CKEditor configuration group.
*
Jennifer Hodgdon
committed
* @param {jQuery.Event} event
Angie Byron
committed
* The keypress event triggered.
Alex Pott
committed
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
*/
onPressGroup: function (event) {
var upDownKeys = [
38, // Up arrow.
63232, // Safari up arrow.
40, // Down arrow.
63233 // Safari down arrow.
];
var leftRightKeys = [
37, // Left arrow.
63234, // Safari left arrow.
39, // Right arrow.
63235 // Safari right arrow.
];
// Respond to an enter key press.
if (event.keyCode === 13) {
var view = this;
// Open the group renaming dialog in the next evaluation cycle so that
// this event can be cancelled and the bubbling wiped out. Otherwise,
// Firefox has issues because the page focus is shifted to the dialog
// along with the keydown event.
window.setTimeout(function () {
Drupal.ckeditor.openGroupNameDialog(view, $(event.currentTarget));
}, 0);
event.preventDefault();
event.stopPropagation();
}
// Respond to direction key presses.
if (_.indexOf(_.union(upDownKeys, leftRightKeys), event.keyCode) > -1) {
var $group = $(event.currentTarget);
var $container = $group.parent();
var $siblings = $container.children();
Alex Pott
committed
var index;
var dir;
Alex Pott
committed
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
// Move groups between sibling groups.
if (_.indexOf(leftRightKeys, event.keyCode) > -1) {
index = $siblings.index($group);
// Move left between sibling groups.
if ((_.indexOf([37, 63234], event.keyCode) > -1)) {
if (index > 0) {
$group.insertBefore($siblings.eq(index - 1));
}
// Wrap between rows. Insert the group before the placeholder group
// at the end of the previous row.
else {
$group.insertBefore($container.closest('.ckeditor-row').prev().find('.ckeditor-toolbar-groups').children().eq(-1));
}
}
// Move right between sibling groups.
else if (_.indexOf([39, 63235], event.keyCode) > -1) {
// Move to the right if the next group is not a placeholder.
if (!$siblings.eq(index + 1).hasClass('placeholder')) {
$group.insertAfter($container.children().eq(index + 1));
}
// Wrap group between rows.
else {
$container.closest('.ckeditor-row').next().find('.ckeditor-toolbar-groups').prepend($group);
}
}
}
// Move groups between rows.
else if (_.indexOf(upDownKeys, event.keyCode) > -1) {
dir = (_.indexOf([38, 63232], event.keyCode) > -1) ? 'prev' : 'next';
$group.closest('.ckeditor-row')[dir]().find('.ckeditor-toolbar-groups').eq(0).prepend($group);
}
Drupal.ckeditor.registerGroupMove(this, $group);
$group.trigger('focus');
event.preventDefault();
event.stopPropagation();
}
}
});
})(jQuery, Drupal, Backbone, _);