Commit 9501ed4e authored by webchick's avatar webchick
Browse files

Issue #2505363 by eiriksm, nod_, mlevasseur, joshi.rohit100: JSDoc ckeditor module

parent 573ac544
......@@ -10,7 +10,14 @@
Drupal.ckeditor = Drupal.ckeditor || {};
/**
* Sets config behaviour and creates config views for the CKEditor toolbar.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches admin behaviour to the CKEditor buttons.
* @prop {Drupal~behaviorDetach} detach
* Detaches admin behaviour from the CKEditor buttons on 'unload'.
*/
Drupal.behaviors.ckeditorAdmin = {
attach: function (context) {
......@@ -18,14 +25,14 @@
var $configurationForm = $(context).find('.ckeditor-toolbar-configuration').once('ckeditor-configuration');
if ($configurationForm.length) {
var $textarea = $configurationForm
// Hide the textarea that contains the serialized representation of the
// CKEditor configuration.
// Hide the textarea that contains the serialized representation of
// the CKEditor configuration.
.find('.form-item-editor-settings-toolbar-button-groups')
.hide()
// Return the textarea child node from this expression.
.find('textarea');
// The HTML for the CKEditor configuration is assembled on the server and
// The HTML for the CKEditor configuration is assembled on the server
// and sent to the client as a serialized DOM fragment.
$configurationForm.append(drupalSettings.ckeditor.toolbarAdmin);
......@@ -50,15 +57,16 @@
}
},
detach: function (context, settings, trigger) {
// Early-return if the trigger for detachment is something else than unload.
// Early-return if the trigger for detachment is something else than
// unload.
if (trigger !== 'unload') {
return;
}
// We're detaching because CKEditor as text editor has been disabled; this
// really means that all CKEditor toolbar buttons have been removed. Hence,
// all editor features will be removed, so any reactions from filters will
// be undone.
// really means that all CKEditor toolbar buttons have been removed.
// Hence,all editor features will be removed, so any reactions from
// filters will be undone.
var $configurationForm = $(context).find('.ckeditor-toolbar-configuration').findOnce('ckeditor-configuration');
if ($configurationForm.length && Drupal.ckeditor.models && Drupal.ckeditor.models.Model) {
var config = Drupal.ckeditor.models.Model.toJSON().activeEditorConfig;
......@@ -93,20 +101,21 @@
models: {},
/**
* Translates a change in CKEditor config DOM structure into the config model.
* Translates changes in CKEditor config DOM structure to the config model.
*
* If the button is moved within an existing group, the DOM structure is simply
* translated to a configuration model. If the button is moved into a new group
* placeholder, then a process is launched to name that group before the button
* move is translated into configuration.
* If the button is moved within an existing group, the DOM structure is
* simply translated to a configuration model. If the button is moved into a
* new group placeholder, then a process is launched to name that group
* before the button move is translated into configuration.
*
* @param {Backbone.View} view
* The Backbone View that invoked this function.
* @param {jQuery} $button
* A jQuery set that contains an li element that wraps a button element.
* @param {function} callback
* A callback to invoke after the button group naming modal dialog has been
* closed.
* A callback to invoke after the button group naming modal dialog has
* been closed.
*
*/
registerButtonMove: function (view, $button, callback) {
var $group = $button.closest('.ckeditor-toolbar-group');
......@@ -127,10 +136,11 @@
},
/**
* Translates a change in CKEditor config DOM structure into the config model.
* Translates changes in CKEditor config DOM structure to the config model.
*
* 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.
* 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
* The Backbone View that invoked this function.
......@@ -155,15 +165,15 @@
},
/**
* Opens a Drupal dialog with a form for changing the title of a button group.
* Opens a dialog with a form for changing the title of a button group.
*
* @param {Backbone.View} view
* The Backbone View that invoked this function.
* @param {jQuery} $group
* A jQuery set that contains an li element that wraps a group of buttons.
* @param {function} callback
* A callback to invoke after the button group naming modal dialog has been
* closed.
* A callback to invoke after the button group naming modal dialog has
* been closed.
*/
openGroupNameDialog: function (view, $group, callback) {
callback = callback || function () {};
......@@ -172,8 +182,8 @@
* Validates the string provided as a button group title.
*
* @param {HTMLElement} form
* The form DOM element that contains the input with the new button group
* title string.
* The form DOM element that contains the input with the new button
* group title string.
*
* @return {bool}
* Returns true when an error exists, otherwise returns false.
......@@ -200,8 +210,8 @@
* @param {string} action
* The dialog action chosen by the user: 'apply' or 'cancel'.
* @param {HTMLElement} form
* The form DOM element that contains the input with the new button group
* title string.
* The form DOM element that contains the input with the new button
* group title string.
*/
function closeDialog(action, form) {
......@@ -211,7 +221,8 @@
function shutdown() {
dialog.close(action);
// The processing marker can be deleted since the dialog has been closed.
// The processing marker can be deleted since the dialog has been
// closed.
delete view.isProcessing;
}
......@@ -219,13 +230,14 @@
* Applies a string as the name of a CKEditor button group.
*
* @param {jQuery} $group
* A jQuery set that contains an li element that wraps a group of buttons.
* A jQuery set that contains an li element that wraps a group of
* buttons.
* @param {string} name
* The new name of the CKEditor button group.
*/
function namePlaceholderGroup($group, name) {
// If it's currently still a placeholder, then that means we're creating
// a new group, and we must do some extra work.
// If it's currently still a placeholder, then that means we're
// creating a new group, and we must do some extra work.
if ($group.hasClass('placeholder')) {
// Remove all whitespace from the name, lowercase it and ensure
// HTML-safe encoding, then use this as the group ID for CKEditor
......@@ -338,12 +350,13 @@
$(event.target).remove();
}
});
// A modal dialog is used because the user must provide a button group name
// or cancel the button placement before taking any other action.
// A modal dialog is used because the user must provide a button group
// name or cancel the button placement before taking any other action.
dialog.showModal();
$(document.querySelector('.ckeditor-name-toolbar-group').querySelector('input'))
// When editing, set the "group name" input in the form to the current value.
// When editing, set the "group name" input in the form to the current
// value.
.attr('value', $group.attr('data-drupal-ckeditor-toolbar-group-name'))
// Focus on the "group name" input in the form.
.trigger('focus');
......@@ -355,6 +368,9 @@
* Automatically shows/hides settings of buttons-only CKEditor plugins.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches show/hide behaviour to Plugin Settings buttons.
*/
Drupal.behaviors.ckeditorAdminButtonPluginSettings = {
attach: function (context) {
......@@ -374,10 +390,11 @@
$this.data('ckeditorButtonPluginSettingsActiveButtons', []);
});
// Whenever a button is added or removed, check if we should show or hide
// the corresponding plugin settings. (Note that upon initialization, each
// button that already is part of the toolbar still is considered "added",
// hence it also works correctly for buttons that were added previously.)
// Whenever a button is added or removed, check if we should show or
// hide the corresponding plugin settings. (Note that upon
// initialization, each button that already is part of the toolbar still
// is considered "added", hence it also works correctly for buttons that
// were added previously.)
$context
.find('.ckeditor-toolbar-active')
.off('CKEditorToolbarChanged.ckeditorAdminPluginSettings')
......@@ -428,6 +445,7 @@
* Themes a blank CKEditor row.
*
* @return {string}
* A HTML string for a CKEditor row.
*/
Drupal.theme.ckeditorRow = function () {
return '<li class="ckeditor-row placeholder" role="group"><ul class="ckeditor-toolbar-groups clearfix"></ul></li>';
......@@ -437,6 +455,7 @@
* Themes a blank CKEditor button group.
*
* @return {string}
* A HTML string for a CKEditor button group.
*/
Drupal.theme.ckeditorToolbarGroup = function () {
var group = '';
......@@ -451,6 +470,7 @@
* Themes a form for changing the title of a CKEditor button group.
*
* @return {string}
* A HTML string for the form for the title of a CKEditor button group.
*/
Drupal.theme.ckeditorButtonGroupNameForm = function () {
return '<form><input name="group-name" required="required"></form>';
......@@ -460,6 +480,7 @@
* Themes a button that will toggle the button group names in active config.
*
* @return {string}
* A HTML string for the button to toggle group names.
*/
Drupal.theme.ckeditorButtonGroupNamesToggle = function () {
return '<a class="ckeditor-groupnames-toggle" role="button" aria-pressed="false"></a>';
......@@ -469,6 +490,7 @@
* Themes a button that will prompt the user to name a new button group.
*
* @return {string}
* A HTML string for the button to create a name for a new button group.
*/
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>';
......
......@@ -11,6 +11,9 @@
* Provides the summary for the "drupalimage" plugin settings vertical tab.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches summary behaviour to the "drupalimage" settings vertical tab.
*/
Drupal.behaviors.ckeditorDrupalImageSettingsSummary = {
attach: function () {
......
......@@ -16,9 +16,12 @@
* Editor attach callback.
*
* @param {HTMLElement} element
* The element to attach the editor to.
* @param {string} format
* The text format for the editor.
*
* @return {bool}
* Whether the call to `CKEDITOR.replace()` created an editor or not.
*/
attach: function (element, format) {
this._loadExternalPlugins(format);
......@@ -46,10 +49,15 @@
* Editor detach callback.
*
* @param {HTMLElement} element
* The element to detach the editor from.
* @param {string} format
* The text format used for the editor.
* @param {string} trigger
* The event trigger for the detach.
*
* @return {bool}
* Whether the call to `CKEDITOR.dom.element.get(element).getEditor()`
* found an editor or not.
*/
detach: function (element, format, trigger) {
var editor = CKEDITOR.dom.element.get(element).getEditor();
......@@ -66,11 +74,16 @@
},
/**
* Reacts on a change in the editor element.
*
* @param {HTMLElement} element
* The element where the change occured.
* @param {function} callback
* Callback called with the value of the editor.
*
* @return {bool}
* Whether the call to `CKEDITOR.dom.element.get(element).getEditor()`
* found an editor or not.
*/
onChange: function (element, callback) {
var editor = CKEDITOR.dom.element.get(element).getEditor();
......@@ -83,13 +96,19 @@
},
/**
* Attaches an inline editor to a DOM element.
*
* @param {HTMLElement} element
* The element to attach the editor to.
* @param {object} format
* @param {string} mainToolbarId
* @param {string} floatedToolbarId
* The text format used in the editor.
* @param {string} [mainToolbarId]
* The id attribute for the main editor toolbar, if any.
* @param {string} [floatedToolbarId]
* The id attribute for the floated editor toolbar, if any.
*
* @return {bool}
* Whether the call to `CKEDITOR.replace()` created an editor or not.
*/
attachInlineEditor: function (element, format, mainToolbarId, floatedToolbarId) {
this._loadExternalPlugins(format);
......@@ -143,7 +162,10 @@
},
/**
* Loads the required external plugins for the editor.
*
* @param {object} format
* The text format used in the editor.
*/
_loadExternalPlugins: function (format) {
var externalPlugins = format.editorSettings.drupalExternalPlugins;
......
/**
* @file
* CKEditor SylesCombo admin behavior.
* CKEditor StylesCombo admin behavior.
*/
(function ($, Drupal, drupalSettings) {
......@@ -11,21 +11,25 @@
* Ensures that the "stylescombo" button's metadata remains up-to-date.
*
* Triggers the CKEditorPluginSettingsChanged event whenever the "stylescombo"
* 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.
* 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}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches admin behaviour to the "stylescombo" button.
*/
Drupal.behaviors.ckeditorStylesComboSettings = {
attach: function (context) {
var $context = $(context);
// React to changes in the list of user-defined styles: calculate the new
// stylesSet setting up to 2 times per second, and if it is different, fire
// the CKEditorPluginSettingsChanged event with the updated parts of the
// CKEditor configuration. (This will, in turn, cause the hidden CKEditor
// instance to be updated and a drupalEditorFeatureModified event to fire.)
// stylesSet setting up to 2 times per second, and if it is different,
// fire the CKEditorPluginSettingsChanged event with the updated parts of
// the CKEditor configuration. (This will, in turn, cause the hidden
// CKEditor instance to be updated and a drupalEditorFeatureModified event
// to fire.)
var $ckeditorActiveToolbar = $context
.find('.ckeditor-toolbar-configuration')
.find('.ckeditor-toolbar-active');
......@@ -49,9 +53,9 @@
*
* @see \Drupal\ckeditor\Plugin\ckeditor\plugin\StylesCombo::generateStylesSetSetting()
*
* Note that this is a more forgiving implementation than the PHP version: the
* parsing works identically, but instead of failing on invalid styles, we
* just ignore those.
* Note that this is a more forgiving implementation than the PHP version:
* the parsing works identically, but instead of failing on invalid styles,
* we just ignore those.
*
* @param {string} styles
* The "styles" setting.
......@@ -102,6 +106,9 @@
* Provides the summary for the "stylescombo" plugin settings vertical tab.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches summary behaviour to the plugin settings vertical tab.
*/
Drupal.behaviors.ckeditorStylesComboSettingsSummary = {
attach: function () {
......
......@@ -131,10 +131,10 @@
// when shifting state, so might deal with a new instance.
widget = editor.widgets.getByElement(image);
// It's first edit, just after widget instance creation, but before it was
// inserted into DOM. So we need to retrieve the widget wrapper from
// inside the DocumentFragment which we cached above and finalize other
// things (like ready event and flag).
// It's first edit, just after widget instance creation, but before
// it was inserted into DOM. So we need to retrieve the widget
// wrapper from inside the DocumentFragment which we cached above
// and finalize other things (like ready event and flag).
if (firstEdit) {
editor.widgets.finalizeCreation(container);
}
......
......@@ -213,7 +213,8 @@
}
};
};
}, null, null, 20); // Low priority to ensure drupalimage's event handler runs first.
// Low priority to ensure drupalimage's event handler runs first.
}, null, null, 20);
}
});
......@@ -224,9 +225,12 @@
* children in DFS order.
*
* @param {CKEDITOR.htmlParser.element} element
* The element to search.
* @param {string} name
* The element name to search for.
*
* @return {CKEDITOR.htmlParser.element}
* @return {?CKEDITOR.htmlParser.element}
* The found element, or null.
*/
function findElementByName(element, name) {
if (element.name === name) {
......
......@@ -32,14 +32,14 @@
for (var attrIndex = 0; attrIndex < linkDOMElement.attributes.length; attrIndex++) {
attribute = linkDOMElement.attributes.item(attrIndex);
attributeName = attribute.nodeName.toLowerCase();
// Don't consider data-cke-saved- attributes; they're just there to
// work around browser quirks.
// Don't consider data-cke-saved- attributes; they're just there
// to work around browser quirks.
if (attributeName.substring(0, 15) === 'data-cke-saved-') {
continue;
}
// Store the value for this attribute, unless there's a
// data-cke-saved- alternative for it, which will contain the quirk-
// free, original value.
// data-cke-saved- alternative for it, which will contain the
// quirk-free, original value.
existingValues[attributeName] = linkElement.data('cke-saved-' + attributeName) || attribute.nodeValue;
}
}
......@@ -97,8 +97,8 @@
editor.fire('saveSnapshot');
};
// Drupal.t() will not work inside CKEditor plugins because CKEditor
// loads the JavaScript file instead of Drupal. Pull translated strings
// from the plugin settings that are translated server-side.
// loads the JavaScript file instead of Drupal. Pull translated
// strings from the plugin settings that are translated server-side.
var dialogSettings = {
title: linkElement ? editor.config.drupalLink_dialogTitleEdit : editor.config.drupalLink_dialogTitleAdd,
dialogClass: 'editor-link-dialog'
......@@ -210,8 +210,11 @@
* [<a href="#"><b>li]nk</b></a>
*
* @param {CKEDITOR.editor} editor
* The CKEditor editor object
*
* @return {?HTMLElement}
* The selected link element, or null.
*
* @return {?bool}
*/
function getSelectedLink(editor) {
var selection = editor.getSelection();
......
/**
* @file
* A Backbone View that provides the aural view of CKEditor toolbar configuration.
* A Backbone View that provides the aural view of CKEditor toolbar
* configuration.
*/
(function (Drupal, Backbone, $) {
......@@ -37,6 +38,7 @@
* Calls announce on buttons and groups when their position is changed.
*
* @param {Drupal.ckeditor.ConfigurationModel} model
* The ckeditor configuration model.
* @param {bool} isDirty
* A model attribute that indicates if the changed toolbar configuration
* has been stored or not.
......@@ -62,6 +64,7 @@
* Handles the focus event of elements in the active and available toolbars.
*
* @param {jQuery.Event} event
* The focus event that was triggered.
*/
onFocus: function (event) {
event.stopPropagation();
......@@ -171,6 +174,7 @@
* Provides help information when a button is clicked.
*
* @param {jQuery.Event} event
* The click event for the button click.
*/
announceButtonHelp: function (event) {
var $link = $(event.currentTarget);
......@@ -199,6 +203,7 @@
* Provides help information when a separator is clicked.
*
* @param {jQuery.Event} event
* The click event for the separator click.
*/
announceSeparatorHelp: function (event) {
var $link = $(event.currentTarget);
......
......@@ -234,6 +234,10 @@
*
* @param {object} features
* A map of {@link Drupal.EditorFeature} objects.
* @param {object} buttonsToFeatures
* Object containing the button-to-feature mapping.
*
* @see Drupal.ckeditor.ControllerView#getFeatureForButton
*/
disableFeaturesDisallowedByFilters: function (features, buttonsToFeatures) {
this.model.set('featuresMetadata', features);
......
/**
* @file
* A Backbone View that provides the aural view of CKEditor keyboard UX configuration.
* Backbone View providing the aural view of CKEditor keyboard UX configuration.
*/
(function (Drupal, Backbone, $) {
......@@ -32,6 +32,7 @@
* Handles keypresses on a CKEditor configuration button.
*
* @param {jQuery.Event} event
* The keypress event triggered.
*/
onPressButton: function (event) {
var upDownKeys = [
......@@ -69,10 +70,11 @@
var $originalGroup = $group;
var dir;
// Move available buttons between their container and the active toolbar.
// Move available buttons between their container and the active
// toolbar.
if (containerType === 'source') {
// Move the button to the active toolbar configuration when the down or
// up keys are pressed.
// Move the button to the active toolbar configuration when the down
// or up keys are pressed.
if (_.indexOf([40, 63233], event.keyCode) > -1) {
// Move the button to the first row, first button group index
// position.
......@@ -142,8 +144,8 @@
}
// Move dividers between their container and the active toolbar.
else if (containerType === 'dividers') {
// Move the button to the active toolbar configuration when the down or
// up keys are pressed.
// Move the button to the active toolbar configuration when the down
// or up keys are pressed.
if (_.indexOf([40, 63233], event.keyCode) > -1) {
// Move the button to the first row, first button group index
// position.
......@@ -169,8 +171,8 @@
else {
view.$el.find('.ui-sortable').sortable('refresh');
}
// Refocus the target button so that the user can continue from a known
// place.
// Refocus the target button so that the user can continue from a
// known place.
$target.trigger('focus');
});
......@@ -183,6 +185,7 @@
* Handles keypresses on a CKEditor configuration group.
*
* @param {jQuery.Event} event
* The keypress event triggered.
*/
onPressGroup: function (event) {
var upDownKeys = [
......
......@@ -34,12 +34,17 @@
},
/**
* Render function for rendering the toolbar configuration.
*
* @param {*} model
* Model used for the view.
* @param {string} [value]
* The value that was changed.
* @param {object} changedAttributes
* The attributes that was changed.
*
* @return {Drupal.ckeditor.VisualView}
* The {@link Drupal.ckeditor.VisualView} object.
*/
render: function (model, value, changedAttributes) {
this.insertPlaceholders();
......@@ -65,6 +70,7 @@
* Handles clicks to a button group name.
*
* @param {jQuery.Event} event
* The click event on the button group.
*/
onGroupNameClick: function (event) {
var $group = $(event.currentTarget).closest('.ckeditor-toolbar-group');
......@@ -78,6 +84,7 @@
* Handles clicks on the button group names toggle button.
*
* @param {jQuery.Event} event
* The click event on the toggle button.
*/
onGroupNamesToggleClick: function (event) {
this.model.set('groupNamesVisible', !this.model.get('groupNamesVisible'));
......@@ -88,6 +95,7 @@
* Prompts the user to provide a name for a new button group; inserts it.
*
* @param {jQuery.Event} event
* The event of the button click.