annotate core/modules/ckeditor/js/views/VisualView.es6.js @ 5:12f9dff5fda9 tip

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