Skip to content
Snippets Groups Projects
Commit 38833e0f authored by Jennifer Hodgdon's avatar Jennifer Hodgdon
Browse files

Issue #2493683 by nod_, dawehner, eiriksm, Wim Leers: JSDoc for JS using Backbone

parent 08344875
No related branches found
No related tags found
2 merge requests!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!789Issue #3210310: Adjust Database API to remove deprecated Drupal 9 code in Drupal 10
Showing
with 800 additions and 354 deletions
......@@ -2,12 +2,16 @@
* @file
* CKEditor button and group configuration user interface.
*/
(function ($, Drupal, _, CKEDITOR) {
"use strict";
Drupal.ckeditor = Drupal.ckeditor || {};
/**
* @type {Drupal~behavior}
*/
Drupal.behaviors.ckeditorAdmin = {
attach: function (context) {
// Process the CKEditor configuration fragment once.
......@@ -69,13 +73,23 @@
/**
* CKEditor configuration UI methods of Backbone objects.
*
* @namespace
*/
Drupal.ckeditor = {
// A hash of View instances.
/**
* A hash of View instances.
*
* @type {object}
*/
views: {},
// A hash of Model instances.
/**
* A hash of Model instances.
*
* @type {object}
*/
models: {},
/**
......@@ -86,11 +100,11 @@
* placeholder, then a process is launched to name that group before the button
* move is translated into configuration.
*
* @param Backbone.View view
* @param {Backbone.View} view
* The Backbone View that invoked this function.
* @param jQuery $button
* @param {jQuery} $button
* A jQuery set that contains an li element that wraps a button element.
* @param function callback
* @param {function} callback
* A callback to invoke after the button group naming modal dialog has been
* closed.
*/
......@@ -118,9 +132,9 @@
* Each row has a placeholder group at the end of the row. A user may not move
* an existing button group past the placeholder group at the end of a row.
*
* @param Backbone.View view
* @param {Backbone.View} view
* The Backbone View that invoked this function.
* @param jQuery $group
* @param {jQuery} $group
* A jQuery set that contains an li element that wraps a group of buttons.
*/
registerGroupMove: function (view, $group) {
......@@ -143,11 +157,11 @@
/**
* Opens a Drupal dialog with a form for changing the title of a button group.
*
* @param Backbone.View view
* @param {Backbone.View} view
* The Backbone View that invoked this function.
* @param jQuery $group
* @param {jQuery} $group
* A jQuery set that contains an li element that wraps a group of buttons.
* @param function callback
* @param {function} callback
* A callback to invoke after the button group naming modal dialog has been
* closed.
*/
......@@ -157,10 +171,11 @@
/**
* Validates the string provided as a button group title.
*
* @param DOM form
* @param {HTMLElement} form
* The form DOM element that contains the input with the new button group
* title string.
* @return Boolean
*
* @return {bool}
* Returns true when an error exists, otherwise returns false.
*/
function validateForm(form) {
......@@ -182,9 +197,9 @@
/**
* Attempts to close the dialog; Validates user input.
*
* @param String action
* @param {string} action
* The dialog action chosen by the user: 'apply' or 'cancel'.
* @param DOM form
* @param {HTMLElement} form
* The form DOM element that contains the input with the new button group
* title string.
*/
......@@ -203,9 +218,9 @@
/**
* Applies a string as the name of a CKEditor button group.
*
* @param jQuery $group
* @param {jQuery} $group
* A jQuery set that contains an li element that wraps a group of buttons.
* @param String name
* @param {string} name
* The new name of the CKEditor button group.
*/
function namePlaceholderGroup($group, name) {
......@@ -336,9 +351,10 @@
};
/**
* Automatically shows/hides settings of buttons-only CKEditor plugins.
*
* @type {Drupal~behavior}
*/
Drupal.behaviors.ckeditorAdminButtonPluginSettings = {
attach: function (context) {
......@@ -411,7 +427,7 @@
/**
* Themes a blank CKEditor row.
*
* @return String
* @return {string}
*/
Drupal.theme.ckeditorRow = function () {
return '<li class="ckeditor-row placeholder" role="group"><ul class="ckeditor-toolbar-groups clearfix"></ul></li>';
......@@ -420,7 +436,7 @@
/**
* Themes a blank CKEditor button group.
*
* @return String
* @return {string}
*/
Drupal.theme.ckeditorToolbarGroup = function () {
var group = '';
......@@ -434,7 +450,7 @@
/**
* Themes a form for changing the title of a CKEditor button group.
*
* @return String
* @return {string}
*/
Drupal.theme.ckeditorButtonGroupNameForm = function () {
return '<form><input name="group-name" required="required"></form>';
......@@ -443,7 +459,7 @@
/**
* Themes a button that will toggle the button group names in active config.
*
* @return String
* @return {string}
*/
Drupal.theme.ckeditorButtonGroupNamesToggle = function () {
return '<a class="ckeditor-groupnames-toggle" role="button" aria-pressed="false"></a>';
......@@ -452,7 +468,7 @@
/**
* Themes a button that will prompt the user to name a new button group.
*
* @return String
* @return {string}
*/
Drupal.theme.ckeditorNewButtonGroup = function () {
return '<li class="ckeditor-add-new-group"><button role="button" aria-label="' + Drupal.t('Add a CKEditor button group to the end of this row.') + '">' + Drupal.t('Add group') + '</button></li>';
......
/**
* @file
* CKEditor 'drupalimage' plugin admin behavior.
*/
(function ($, Drupal, drupalSettings) {
"use strict";
/**
* Provides the summary for the "drupalimage" plugin settings vertical tab.
*
* @type {Drupal~behavior}
*/
Drupal.behaviors.ckeditorDrupalImageSettingsSummary = {
attach: function () {
......
/**
* @file
* CKEditor implementation of {@link Drupal.editors} API.
*/
(function (Drupal, debounce, CKEDITOR, $) {
"use strict";
/**
* @namespace
*/
Drupal.editors.ckeditor = {
/**
* Editor attach callback.
*
* @param {HTMLElement} element
* @param {string} format
*
* @return {bool}
*/
attach: function (element, format) {
this._loadExternalPlugins(format);
// Also pass settings that are Drupal-specific.
......@@ -26,6 +42,15 @@
return !!CKEDITOR.replace(element, format.editorSettings);
},
/**
* Editor detach callback.
*
* @param {HTMLElement} element
* @param {string} format
* @param {string} trigger
*
* @return {bool}
*/
detach: function (element, format, trigger) {
var editor = CKEDITOR.dom.element.get(element).getEditor();
if (editor) {
......@@ -40,6 +65,13 @@
return !!editor;
},
/**
*
* @param {HTMLElement} element
* @param {function} callback
*
* @return {bool}
*/
onChange: function (element, callback) {
var editor = CKEDITOR.dom.element.get(element).getEditor();
if (editor) {
......@@ -50,6 +82,15 @@
return !!editor;
},
/**
*
* @param {HTMLElement} element
* @param {object} format
* @param {string} mainToolbarId
* @param {string} floatedToolbarId
*
* @return {bool}
*/
attachInlineEditor: function (element, format, mainToolbarId, floatedToolbarId) {
this._loadExternalPlugins(format);
// Also pass settings that are Drupal-specific.
......@@ -101,6 +142,9 @@
return !!CKEDITOR.inline(element, settings);
},
/**
* @param {object} format
*/
_loadExternalPlugins: function (format) {
var externalPlugins = format.editorSettings.drupalExternalPlugins;
// Register and load additional CKEditor plugins as necessary.
......@@ -117,8 +161,11 @@
};
Drupal.ckeditor = {
/**
* Variable storing the current dialog's save callback.
*
* @type {?function}
*/
saveCallback: null,
......@@ -128,16 +175,16 @@
* This dynamically loads jQuery UI (if necessary) using the Drupal AJAX
* framework, then opens a dialog at the specified Drupal path.
*
* @param editor
* @param {CKEditor} editor
* The CKEditor instance that is opening the dialog.
* @param string url
* @param {string} url
* The URL that contains the contents of the dialog.
* @param Object existingValues
* @param {object} existingValues
* Existing values that will be sent via POST to the url for the dialog
* contents.
* @param Function saveCallback
* @param {function} saveCallback
* A function to be called upon saving the dialog.
* @param Object dialogSettings
* @param {object} dialogSettings
* An object containing settings to be passed to the jQuery UI.
*/
openDialog: function (editor, url, existingValues, saveCallback, dialogSettings) {
......@@ -156,8 +203,8 @@
dialogSettings.dialogClass = classes.join(' ');
dialogSettings.autoResize = Drupal.checkWidthBreakpoint(600);
// Add a "Loading…" message, hide it underneath the CKEditor toolbar, create
// a Drupal.ajax instance to load the dialog and trigger it.
// Add a "Loading…" message, hide it underneath the CKEditor toolbar,
// create a Drupal.Ajax instance to load the dialog and trigger it.
var $content = $('<div class="ckeditor-dialog-loading"><span style="top: -40px;" class="ckeditor-dialog-loading-link">' + Drupal.t('Loading...') + '</span></div>');
$content.appendTo($target);
......
/**
* @file
* CKEditor SylesCombo admin behavior.
*/
(function ($, Drupal, drupalSettings) {
"use strict";
......@@ -9,6 +14,8 @@
* plugin settings change, to ensure that the corresponding feature metadata is
* immediately updated — i.e. ensure that HTML tags and classes entered here are
* known to be "required", which may affect filter settings.
*
* @type {Drupal~behavior}
*/
Drupal.behaviors.ckeditorStylesComboSettings = {
attach: function (context) {
......@@ -46,10 +53,10 @@
* parsing works identically, but instead of failing on invalid styles, we
* just ignore those.
*
* @param String styles
* @param {string} styles
* The "styles" setting.
*
* @return array
* @return {Array}
* An array containing the "stylesSet" configuration.
*/
_generateStylesSetSetting: function (styles) {
......@@ -93,6 +100,8 @@
/**
* Provides the summary for the "stylescombo" plugin settings vertical tab.
*
* @type {Drupal~behavior}
*/
Drupal.behaviors.ckeditorStylesComboSettingsSummary = {
attach: function () {
......
......@@ -9,26 +9,58 @@
/**
* Backbone model for the CKEditor toolbar configuration state.
*
* @constructor
*
* @augments Backbone.Model
*/
Drupal.ckeditor.Model = Backbone.Model.extend(/** @lends Drupal.ckeditor.Model# */{
/**
* Default values.
*
* @type {object}
*/
defaults: /** @lends Drupal.ckeditor.Model# */{
/**
* The CKEditor configuration that is being manipulated through the UI.
*/
Drupal.ckeditor.Model = Backbone.Model.extend({
defaults: {
// The CKEditor configuration that is being manipulated through the UI.
activeEditorConfig: null,
// The textarea that contains the serialized representation of the active
// CKEditor configuration.
/**
* The textarea that contains the serialized representation of the active
* CKEditor configuration.
*/
$textarea: null,
// Tracks whether the active toolbar DOM structure has been changed. When
// true, activeEditorConfig needs to be updated, and when that is updated,
// $textarea will also be updated.
/**
* Tracks whether the active toolbar DOM structure has been changed. When
* true, activeEditorConfig needs to be updated, and when that is updated,
* $textarea will also be updated.
*/
isDirty: false,
// The configuration for the hidden CKEditor instance that is used to build
// the features metadata.
/**
* The configuration for the hidden CKEditor instance that is used to
* build the features metadata.
*/
hiddenEditorConfig: null,
// A hash, keyed by a feature name, that details CKEditor plugin features.
/**
* A hash, keyed by a feature name, that details CKEditor plugin features.
*/
featuresMetadata: null,
// Whether the button group names are currently visible.
/**
* Whether the button group names are currently visible.
*/
groupNamesVisible: false
},
/**
* @method
*/
sync: function () {
// Push the settings into the textarea.
this.get('$textarea').val(JSON.stringify(this.get('activeEditorConfig')));
......
......@@ -7,8 +7,12 @@
* uses to track where images are being used)
* - use a Drupal-native dialog (that is in fact just an alterable Drupal form
* like any other) instead of CKEditor's own dialogs.
*
* @see \Drupal\editor\Form\EditorImageDialog
*
* @ignore
*/
(function ($, Drupal, CKEDITOR) {
"use strict";
......
......@@ -5,8 +5,11 @@
* This alters the existing CKEditor image2 widget plugin, which is already
* altered by the Drupal Image plugin, to:
* - allow for the data-caption and data-align attributes to be set
* - mimic the upcasting behavior of the caption_filter filter
* - mimic the upcasting behavior of the caption_filter filter.
*
* @ignore
*/
(function (CKEDITOR) {
"use strict";
......@@ -220,9 +223,10 @@
* Function will check first the passed element itself and then all its
* children in DFS order.
*
* @param CKEDITOR.htmlParser.element element
* @param String name
* @return CKEDITOR.htmlParser.element
* @param {CKEDITOR.htmlParser.element} element
* @param {string} name
*
* @return {CKEDITOR.htmlParser.element}
*/
function findElementByName(element, name) {
if (element.name === name) {
......@@ -233,7 +237,8 @@
element.forEach(function (el) {
if (el.name === name) {
found = el;
return false; // Stop here.
// Stop here.
return false;
}
}, CKEDITOR.NODE_ELEMENT);
return found;
......
/**
* @file
* Drupal Link plugin.
*
* @ignore
*/
(function ($, Drupal, drupalSettings, CKEDITOR) {
......@@ -199,6 +201,7 @@
*
* The following selection will all return the link element.
*
* @example
* <a href="#">li^nk</a>
* <a href="#">[link]</a>
* text[<a href="#">link]</a>
......@@ -207,6 +210,8 @@
* [<a href="#"><b>li]nk</b></a>
*
* @param {CKEDITOR.editor} editor
*
* @return {?bool}
*/
function getSelectedLink(editor) {
var selection = editor.getSelection();
......
......@@ -7,11 +7,11 @@
"use strict";
Drupal.ckeditor.AuralView = Backbone.View.extend(/** @lends Drupal.ckeditor.AuralView# */{
/**
* Backbone View for CKEditor toolbar configuration; aural UX (output only).
* @type {object}
*/
Drupal.ckeditor.AuralView = Backbone.View.extend({
events: {
'click .ckeditor-buttons a': 'announceButtonHelp',
'click .ckeditor-multiple-buttons a': 'announceSeparatorHelp',
......@@ -21,7 +21,11 @@
},
/**
* {@inheritdoc}
* Backbone View for CKEditor toolbar configuration; aural UX (output only).
*
* @constructs
*
* @augments Backbone.View
*/
initialize: function () {
// Announce the button and group positions when the model is no longer
......@@ -32,8 +36,8 @@
/**
* Calls announce on buttons and groups when their position is changed.
*
* @param Drupal.ckeditor.ConfigurationModel model
* @param Boolean isDirty
* @param {Drupal.ckeditor.ConfigurationModel} model
* @param {bool} isDirty
* A model attribute that indicates if the changed toolbar configuration
* has been stored or not.
*/
......@@ -57,7 +61,7 @@
/**
* Handles the focus event of elements in the active and available toolbars.
*
* @param jQuery.Event event
* @param {jQuery.Event} event
*/
onFocus: function (event) {
event.stopPropagation();
......@@ -76,7 +80,7 @@
/**
* Announces the current position of a button group.
*
* @param jQuery $group
* @param {jQuery} $group
* A jQuery set that contains an li element that wraps a group of buttons.
*/
announceButtonGroupPosition: function ($group) {
......@@ -106,7 +110,7 @@
/**
* Announces current button position.
*
* @param jQuery $button
* @param {jQuery} $button
* A jQuery set that contains an li element that wraps a button.
*/
announceButtonPosition: function ($button) {
......@@ -166,7 +170,7 @@
/**
* Provides help information when a button is clicked.
*
* @param jQuery.Event event
* @param {jQuery.Event} event
*/
announceButtonHelp: function (event) {
var $link = $(event.currentTarget);
......@@ -194,7 +198,7 @@
/**
* Provides help information when a separator is clicked.
*
* @param jQuery.Event event
* @param {jQuery.Event} event
*/
announceSeparatorHelp: function (event) {
var $link = $(event.currentTarget);
......
......@@ -7,15 +7,19 @@
"use strict";
Drupal.ckeditor.ControllerView = Backbone.View.extend(/** @lends Drupal.ckeditor.ControllerView# */{
/**
* Backbone View acting as a controller for CKEditor toolbar configuration.
* @type {object}
*/
Drupal.ckeditor.ControllerView = Backbone.View.extend({
events: {},
/**
* {@inheritdoc}
* Backbone View acting as a controller for CKEditor toolbar configuration.
*
* @constructs
*
* @augments Backbone.View
*/
initialize: function () {
this.getCKEditorFeatures(this.model.get('hiddenEditorConfig'), this.disableFeaturesDisallowedByFilters.bind(this));
......@@ -28,16 +32,18 @@
/**
* Converts the active toolbar DOM structure to an object representation.
*
* @param Drupal.ckeditor.ConfigurationModel model
* @param {Drupal.ckeditor.ConfigurationModel} model
* The state model for the CKEditor configuration.
* @param Boolean isDirty
* @param {bool} isDirty
* Tracks whether the active toolbar DOM structure has been changed.
* isDirty is toggled back to false in this method.
* @param Object options
* @param {object} options
* An object that includes:
* - Boolean broadcast: (optional) A flag that controls whether a
* CKEditorToolbarChanged event should be fired for configuration
* changes.
* @param {bool} [options.broadcast]
* A flag that controls whether a CKEditorToolbarChanged event should be
* fired for configuration changes.
*
* @fires event:CKEditorToolbarChanged
*/
parseEditorDOM: function (model, isDirty, options) {
if (isDirty) {
......@@ -97,13 +103,13 @@
* In order to get a list of all features needed by CKEditor, we create a
* hidden CKEditor instance, then check the CKEditor's "allowedContent"
* filter settings. Because creating an instance is expensive, a callback
* must be provided that will receive a hash of Drupal.EditorFeature
* must be provided that will receive a hash of {@link Drupal.EditorFeature}
* features keyed by feature (button) name.
*
* @param Object CKEditorConfig
* @param {object} CKEditorConfig
* An object that represents the configuration settings for a CKEditor
* editor component.
* @param Function callback
* @param {function} callback
* A function to invoke when the instanceReady event is fired by the
* CKEditor object.
*/
......@@ -192,9 +198,10 @@
* Retrieves the feature for a given button from featuresMetadata. Returns
* false if the given button is in fact a divider.
*
* @param String button
* @param {string} button
* The name of a CKEditor button.
* @return Object
*
* @return {object}
* The feature metadata object for a button.
*/
getFeatureForButton: function (button) {
......@@ -218,8 +225,8 @@
/**
* Checks buttons against filter settings; disables disallowed buttons.
*
* @param Object features
* A map of Drupal.EditorFeature objects.
* @param {object} features
* A map of {@link Drupal.EditorFeature} objects.
*/
disableFeaturesDisallowedByFilters: function (features) {
this.model.set('featuresMetadata', features);
......@@ -272,7 +279,7 @@
/**
* Sets up broadcasting of CKEditor toolbar configuration changes.
*
* @param jQuery $ckeditorToolbar
* @param {jQuery} $ckeditorToolbar
* The active toolbar DOM element wrapped in jQuery.
*/
broadcastConfigurationChanges: function ($ckeditorToolbar) {
......@@ -329,14 +336,15 @@
/**
* Returns the list of buttons from an editor configuration.
*
* @param Object config
* @param {object} config
* A CKEditor configuration object.
* @return Array
*
* @return {Array}
* A list of buttons in the CKEditor configuration.
*/
getButtonList: function (config) {
var buttons = [];
// Remove the rows
// Remove the rows.
config = _.flatten(config);
// Loop through the button groups and pull out the buttons.
......
......@@ -7,13 +7,14 @@
"use strict";
/**
* Backbone View for CKEditor toolbar configuration; keyboard UX.
*/
Drupal.ckeditor.KeyboardView = Backbone.View.extend({
Drupal.ckeditor.KeyboardView = Backbone.View.extend(/** @lends Drupal.ckeditor.KeyboardView# */{
/**
* {@inheritdoc}
* Backbone View for CKEditor toolbar configuration; keyboard UX.
*
* @constructs
*
* @augments Backbone.View
*/
initialize: function () {
// Add keyboard arrow support.
......@@ -22,7 +23,7 @@
},
/**
* {@inheritdoc}
* @inheritdoc
*/
render: function () {
},
......@@ -30,7 +31,7 @@
/**
* Handles keypresses on a CKEditor configuration button.
*
* @param jQuery.Event event
* @param {jQuery.Event} event
*/
onPressButton: function (event) {
var upDownKeys = [
......@@ -181,7 +182,7 @@
/**
* Handles keypresses on a CKEditor configuration group.
*
* @param jQuery.Event event
* @param {jQuery.Event} event
*/
onPressGroup: function (event) {
var upDownKeys = [
......
/**
* @file
* A Backbone View that provides the visual UX view of CKEditor toolbar configuration.
* A Backbone View that provides the visual UX view of CKEditor toolbar
* configuration.
*/
(function (Drupal, Backbone, $) {
"use strict";
/**
* Backbone View for CKEditor toolbar configuration; visual UX.
*/
Drupal.ckeditor.VisualView = Backbone.View.extend({
Drupal.ckeditor.VisualView = Backbone.View.extend(/** @lends Drupal.ckeditor.VisualView# */{
events: {
'click .ckeditor-toolbar-group-name': 'onGroupNameClick',
......@@ -19,7 +17,11 @@
},
/**
* {@inheritdoc}
* Backbone View for CKEditor toolbar configuration; visual UX.
*
* @constructs
*
* @augments Backbone.View
*/
initialize: function () {
this.listenTo(this.model, 'change:isDirty change:groupNamesVisible', this.render);
......@@ -32,7 +34,12 @@
},
/**
* {@inheritdoc}
*
* @param {*} model
* @param {string} [value]
* @param {object} changedAttributes
*
* @return {Drupal.ckeditor.VisualView}
*/
render: function (model, value, changedAttributes) {
this.insertPlaceholders();
......@@ -57,7 +64,7 @@
/**
* Handles clicks to a button group name.
*
* @param jQuery.Event event
* @param {jQuery.Event} event
*/
onGroupNameClick: function (event) {
var $group = $(event.currentTarget).closest('.ckeditor-toolbar-group');
......@@ -69,6 +76,8 @@
/**
* Handles clicks on the button group names toggle button.
*
* @param {jQuery.Event} event
*/
onGroupNamesToggleClick: function (event) {
this.model.set('groupNamesVisible', !this.model.get('groupNamesVisible'));
......@@ -78,17 +87,17 @@
/**
* Prompts the user to provide a name for a new button group; inserts it.
*
* @param jQuery.Event event
* @param {jQuery.Event} event
*/
onAddGroupButtonClick: function (event) {
/**
* Inserts a new button if the openGroupNameDialog function returns true.
*
* @param Boolean success
* @param {bool} success
* A flag that indicates if the user created a new group (true) or
* canceled out of the dialog (false).
* @param jQuery $group
* @param {jQuery} $group
* A jQuery DOM fragment that represents the new button group. It has
* not been added to the DOM yet.
*/
......@@ -110,8 +119,8 @@
/**
* Handles jQuery Sortable stop sort of a button group.
*
* @param jQuery.Event event
* @param Object ui
* @param {jQuery.Event} event
* @param {object} ui
* A jQuery.ui.sortable argument that contains information about the
* elements involved in the sort action.
*/
......@@ -128,8 +137,8 @@
/**
* Handles jQuery Sortable start sort of a button.
*
* @param jQuery.Event event
* @param Object ui
* @param {jQuery.Event} event
* @param {object} ui
* A jQuery.ui.sortable argument that contains information about the
* elements involved in the sort action.
*/
......@@ -143,8 +152,8 @@
/**
* Handles jQuery Sortable stop sort of a button.
*
* @param jQuery.Event event
* @param Object ui
* @param {jQuery.Event} event
* @param {object} ui
* A jQuery.ui.sortable argument that contains information about the
* elements involved in the sort action.
*/
......
This diff is collapsed.
/**
* @file
* AJAX commands used by Editor module.
*/
......@@ -9,10 +10,18 @@
/**
* Command to save the contents of an editor-provided modal.
*
* This command does not close the open modal. It should be followed by a call
* to Drupal.AjaxCommands.prototype.closeDialog. Editors that are integrated
* with dialogs must independently listen for an editor:dialogsave event to save
* the changes into the contents of their interface.
* This command does not close the open modal. It should be followed by a
* call to `Drupal.AjaxCommands.prototype.closeDialog`. Editors that are
* integrated with dialogs must independently listen for an
* `editor:dialogsave` event to save the changes into the contents of their
* interface.
*
* @param {Drupal.Ajax} [ajax]
* @param {object} response
* @param {Array} response.values
* @param {number} [status]
*
* @fires event:editor:dialogsave
*/
Drupal.AjaxCommands.prototype.editorDialogSave = function (ajax, response, status) {
$(window).trigger('editor:dialogsave', [response.values]);
......
......@@ -10,26 +10,47 @@
* JavaScript would use:
* - Drupal.editors.magical.attachInlineEditor()
*/
(function ($, Drupal, drupalSettings) {
"use strict";
Drupal.quickedit.editors.editor = Drupal.quickedit.EditorView.extend({
Drupal.quickedit.editors.editor = Drupal.quickedit.EditorView.extend(/** @lends Drupal.quickedit.editors.editor# */{
// The text format for this field.
/**
* The text format for this field.
*
* @type {string}
*/
textFormat: null,
// Indicates whether this text format has transformations.
/**
* Indicates whether this text format has transformations.
*
* @type {bool}
*/
textFormatHasTransformations: null,
// Stores a reference to the text editor object for this field.
/**
* Stores a reference to the text editor object for this field.
*
* @type {Drupal.quickedit.EditorModel}
*/
textEditor: null,
// Stores the textual DOM element that is being in-place edited.
/**
* Stores the textual DOM element that is being in-place edited.
*
* @type {jQuery}
*/
$textElement: null,
/**
* {@inheritdoc}
* @constructs
*
* @augments Drupal.quickedit.EditorView
*
* @param {object} options
*/
initialize: function (options) {
Drupal.quickedit.EditorView.prototype.initialize.call(this, options);
......@@ -46,14 +67,19 @@
},
/**
* {@inheritdoc}
* @inheritdoc
*
* @return {jQuery}
*/
getEditedElement: function () {
return this.$textElement;
},
/**
* {@inheritdoc}
* @inheritdoc
*
* @param {object} fieldModel
* @param {string} state
*/
stateChange: function (fieldModel, state) {
var editorModel = this.model;
......@@ -143,14 +169,16 @@
},
/**
* {@inheritdoc}
* @inheritdoc
*
* @return {object}
*/
getQuickEditUISettings: function () {
return {padding: true, unifiedToolbar: true, fullWidthToolbar: true, popup: false};
},
/**
* {@inheritdoc}
* @inheritdoc
*/
revert: function () {
this.$textElement.html(this.model.get('originalValue'));
......@@ -162,7 +190,7 @@
* More accurately: it re-filters formatted text to exclude transformation
* filters used by the text format.
*
* @param Function callback
* @param {function} callback
* A callback function that will receive the untransformed text.
*
* @see \Drupal\editor\Ajax\GetUntransformedTextCommand
......
......@@ -10,10 +10,10 @@
/**
* Finds the text area field associated with the given text format selector.
*
* @param jQuery $formatSelector
* @param {jQuery} $formatSelector
* A text format selector DOM element.
*
* @return DOM
* @return {HTMLElement}
* The text area DOM element, if it was found.
*/
function findFieldForFormatSelector($formatSelector) {
......@@ -26,9 +26,9 @@
/**
* Changes the text editor on a text area.
*
* @param DOM field
* @param {HTMLElement} field
* The text area DOM element.
* @param String newFormatID
* @param {string} newFormatID
* The text format we're changing to; the text editor for the currently
* active text format will be detached, and the text editor for the new text
* format will be attached.
......@@ -58,7 +58,7 @@
/**
* Handles changes in text format.
*
* @param jQuery.Event event
* @param {jQuery.Event} event
*/
function onTextFormatChange(event) {
var $select = $(event.target);
......@@ -129,11 +129,15 @@
/**
* Initialize an empty object for editors to place their attachment code.
*
* @namespace
*/
Drupal.editors = {};
/**
* Enables editors on text_format elements.
*
* @type {Drupal~behavior}
*/
Drupal.behaviors.editor = {
attach: function (context, settings) {
......@@ -214,6 +218,19 @@
}
};
/**
* Attaches editor behaviors to the field.
*
* @param {HTMLElement} field
* The textarea DOM element.
* @param {object} format
* The text format that's being activated, from
* drupalSettings.editor.formats.
*
* @listens event:change
*
* @fires event:formUpdated
*/
Drupal.editorAttach = function (field, format) {
if (format.editor) {
// HTML5 validation cannot ever work for WYSIWYG editors, because WYSIWYG
......@@ -240,6 +257,17 @@
}
};
/**
* Detaches editor behaviors from the field.
*
* @param {HTMLElement} field
* The textarea DOM element.
* @param {object} format
* The text format that's being activated, from
* drupalSettings.editor.formats.
* @param {string} trigger
* Trigger value from the detach behavior.
*/
Drupal.editorDetach = function (field, format, trigger) {
if (format.editor) {
// Restore the HTML5 validation "required" attribute if it was removed in
......@@ -261,13 +289,14 @@
/**
* Filter away XSS attack vectors when switching text formats.
*
* @param DOM field
* @param {HTMLElement} field
* The textarea DOM element.
* @param Object format
* The text format that's being activated, from drupalSettings.editor.formats.
* @param String originalFormatID
* @param {object} format
* The text format that's being activated, from
* drupalSettings.editor.formats.
* @param {string} originalFormatID
* The text format ID of the original text format.
* @param Function callback
* @param {function} callback
* A callback to be called (with no parameters) after the field's value has
* been XSS filtered.
*/
......
......@@ -7,16 +7,32 @@
"use strict";
Drupal.quickedit.editors.form = Drupal.quickedit.EditorView.extend({
/**
* @constructor
*
* @augments Drupal.quickedit.EditorView
*/
Drupal.quickedit.editors.form = Drupal.quickedit.EditorView.extend(/** @lends Drupal.quickedit.editors.form# */{
// Tracks the form container DOM element that is used while in-place editing.
/**
* Tracks form container DOM element that is used while in-place editing.
*
* @type {jQuery}
*/
$formContainer: null,
// Holds the Drupal.ajax object
/**
* Holds the {@link Drupal.Ajax} object.
*
* @type {Drupal.Ajax}
*/
formSaveAjax: null,
/**
* {@inheritdoc}
* @inheritdoc
*
* @param {object} fieldModel
* @param {string} state
*/
stateChange: function (fieldModel, state) {
var from = fieldModel.previous('state');
......@@ -24,28 +40,36 @@
switch (to) {
case 'inactive':
break;
case 'candidate':
if (from !== 'inactive') {
this.removeForm();
}
break;
case 'highlighted':
break;
case 'activating':
// If coming from an invalid state, then the form is already loaded.
if (from !== 'invalid') {
this.loadForm();
}
break;
case 'active':
break;
case 'changed':
break;
case 'saving':
this.save();
break;
case 'saved':
break;
case 'invalid':
this.showValidationErrors();
break;
......@@ -53,7 +77,9 @@
},
/**
* {@inheritdoc}
* @inheritdoc
*
* @return {object}
*/
getQuickEditUISettings: function () {
return {padding: true, unifiedToolbar: true, fullWidthToolbar: true, popup: true};
......@@ -137,7 +163,7 @@
},
/**
* Removes the form for this field and detaches behaviors and event handlers.
* Removes the form for this field, detaches behaviors and event handlers.
*/
removeForm: function () {
if (this.$formContainer === null) {
......@@ -155,7 +181,7 @@
},
/**
* {@inheritdoc}
* @inheritdoc
*/
save: function () {
var $formContainer = this.$formContainer;
......@@ -180,8 +206,8 @@
// First, transition the state to 'saved'.
fieldModel.set('state', 'saved');
// Second, set the 'htmlForOtherViewModes' attribute, so that when this
// field is rerendered, the change can be propagated to other instances of
// this field, which may be displayed in different view modes.
// field is rerendered, the change can be propagated to other instances
// of this field, which may be displayed in different view modes.
fieldModel.set('htmlForOtherViewModes', response.other_view_modes);
// Finally, set the 'html' attribute on the field model. This will cause
// the field to be rerendered.
......@@ -213,7 +239,7 @@
},
/**
* {@inheritdoc}
* @inheritdoc
*/
showValidationErrors: function () {
this.$formContainer
......
/**
* @file
* contentEditable-based in-place editor for plain text content.
* ContentEditable-based in-place editor for plain text content.
*/
(function ($, _, Drupal) {
"use strict";
Drupal.quickedit.editors.plain_text = Drupal.quickedit.EditorView.extend({
Drupal.quickedit.editors.plain_text = Drupal.quickedit.EditorView.extend(/** @lends Drupal.quickedit.editors.plain_text# */{
// Stores the textual DOM element that is being in-place edited.
/**
* Stores the textual DOM element that is being in-place edited.
*/
$textElement: null,
/**
* {@inheritdoc}
* @constructs
*
* @augments Drupal.quickedit.EditorView
*
* @param {object} options
*/
initialize: function (options) {
Drupal.quickedit.EditorView.prototype.initialize.call(this, options);
......@@ -21,7 +27,8 @@
var editorModel = this.model;
var fieldModel = this.fieldModel;
// Store the original value of this field. Necessary for reverting changes.
// Store the original value of this field. Necessary for reverting
// changes.
var $textElement;
var $fieldItems = this.$el.find('.field-item');
if ($fieldItems.length) {
......@@ -32,7 +39,7 @@
}
editorModel.set('originalValue', $.trim(this.$textElement.text()));
// Sets the state to 'changed' whenever the value changes
// Sets the state to 'changed' whenever the value changes.
var previousText = editorModel.get('originalValue');
$textElement.on('keyup paste', function (event) {
var currentText = $.trim($textElement.text());
......@@ -45,14 +52,20 @@
},
/**
* {@inheritdoc}
* @inheritdoc
*
* @return {jQuery}
*/
getEditedElement: function () {
return this.$textElement;
},
/**
* {@inheritdoc}
* @inheritdoc
*
* @param {object} fieldModel
* @param {string} state
* @param {object} options
*/
stateChange: function (fieldModel, state, options) {
var from = fieldModel.previous('state');
......@@ -60,6 +73,7 @@
switch (to) {
case 'inactive':
break;
case 'candidate':
if (from !== 'inactive') {
this.$textElement.removeAttr('contenteditable');
......@@ -68,8 +82,10 @@
this.removeValidationErrors();
}
break;
case 'highlighted':
break;
case 'activating':
// Defer updating the field model until the current state change has
// propagated, to not trigger a nested state change event.
......@@ -77,19 +93,24 @@
fieldModel.set('state', 'active');
});
break;
case 'active':
this.$textElement.attr('contenteditable', 'true');
break;
case 'changed':
break;
case 'saving':
if (from === 'invalid') {
this.removeValidationErrors();
}
this.save(options);
break;
case 'saved':
break;
case 'invalid':
this.showValidationErrors();
break;
......@@ -97,14 +118,16 @@
},
/**
* {@inheritdoc}
* @inheritdoc
*
* @return {object}
*/
getQuickEditUISettings: function () {
return {padding: true, unifiedToolbar: false, fullWidthToolbar: false, popup: false};
},
/**
* {@inheritdoc}
* @inheritdoc
*/
revert: function () {
this.$textElement.html(this.model.get('originalValue'));
......
......@@ -9,18 +9,46 @@
"use strict";
Drupal.quickedit.AppModel = Backbone.Model.extend({
/**
* @constructor
*
* @augments Backbone.Model
*/
Drupal.quickedit.AppModel = Backbone.Model.extend(/** @lends Drupal.quickedit.AppModel# */{
/**
* @type {object}
*
* @prop {Drupal.quickedit.FieldModel} highlightedField
* @prop {Drupal.quickedit.FieldModel} activeField
* @prop {Drupal.dialog~dialogDefinition} activeModal
*/
defaults: /** @lends Drupal.quickedit.AppModel# */{
defaults: {
// The currently state = 'highlighted' Drupal.quickedit.FieldModel, if
// any.
// @see Drupal.quickedit.FieldModel.states
/**
* The currently state='highlighted' Drupal.quickedit.FieldModel, if any.
*
* @type {Drupal.quickedit.FieldModel}
*
* @see Drupal.quickedit.FieldModel.states
*/
highlightedField: null,
// The currently state = 'active' Drupal.quickedit.FieldModel, if any.
// @see Drupal.quickedit.FieldModel.states
/**
* The currently state = 'active' Drupal.quickedit.FieldModel, if any.
*
* @type {Drupal.quickedit.FieldModel}
*
* @see Drupal.quickedit.FieldModel.states
*/
activeField: null,
// Reference to a Drupal.dialog instance if a state change requires
// confirmation.
/**
* Reference to a {@link Drupal.dialog} instance if a state change
* requires confirmation.
*
* @type {Drupal.dialog~dialogDefinition}
*/
activeModal: null
}
......
......@@ -7,10 +7,16 @@
"use strict";
Drupal.quickedit.BaseModel = Backbone.Model.extend({
Drupal.quickedit.BaseModel = Backbone.Model.extend(/** @lends Drupal.quickedit.BaseModel# */{
/**
* {@inheritdoc}
* @constructs
*
* @augments Backbone.Model
*
* @param {object} options
*
* @return {Drupal.quickedit.BaseModel}
*/
initialize: function (options) {
this.__initialized = true;
......@@ -18,7 +24,12 @@
},
/**
* {@inheritdoc}
*
* @param {object|string} key
* @param {*} val
* @param {object} [options]
*
* @return {*}
*/
set: function (key, val, options) {
if (this.__initialized) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment