annotate core/modules/ckeditor/js/views/VisualView.es6.js @ 19:fa3358dc1485 tip

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