X-Git-Url: http://www.aleph1.co.uk/gitweb/?a=blobdiff_plain;ds=sidebyside;f=web%2Fcore%2Fmodules%2Feditor%2Fjs%2Feditor.formattedTextEditor.es6.js;fp=web%2Fcore%2Fmodules%2Feditor%2Fjs%2Feditor.formattedTextEditor.es6.js;h=3005a38712f368348f199f07d86184e67728d85b;hb=9917807b03b64faf00f6a1f29dcb6eafc454efa5;hp=0000000000000000000000000000000000000000;hpb=aea91e65e895364e460983b890e295aa5d5540a5;p=yaffs-website diff --git a/web/core/modules/editor/js/editor.formattedTextEditor.es6.js b/web/core/modules/editor/js/editor.formattedTextEditor.es6.js new file mode 100644 index 000000000..3005a3871 --- /dev/null +++ b/web/core/modules/editor/js/editor.formattedTextEditor.es6.js @@ -0,0 +1,227 @@ +/** + * @file + * Text editor-based in-place editor for formatted text content in Drupal. + * + * Depends on editor.module. Works with any (WYSIWYG) editor that implements the + * editor.js API, including the optional attachInlineEditor() and onChange() + * methods. + * For example, assuming that a hypothetical editor's name was "Magical Editor" + * and its editor.js API implementation lived at Drupal.editors.magical, this + * JavaScript would use: + * - Drupal.editors.magical.attachInlineEditor() + */ + +(function ($, Drupal, drupalSettings, _) { + Drupal.quickedit.editors.editor = Drupal.quickedit.EditorView.extend(/** @lends Drupal.quickedit.editors.editor# */{ + + /** + * The text format for this field. + * + * @type {string} + */ + textFormat: null, + + /** + * Indicates whether this text format has transformations. + * + * @type {bool} + */ + textFormatHasTransformations: null, + + /** + * 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. + * + * @type {jQuery} + */ + $textElement: null, + + /** + * @constructs + * + * @augments Drupal.quickedit.EditorView + * + * @param {object} options + * Options for the editor view. + */ + initialize(options) { + Drupal.quickedit.EditorView.prototype.initialize.call(this, options); + + const metadata = Drupal.quickedit.metadata.get(this.fieldModel.get('fieldID'), 'custom'); + this.textFormat = drupalSettings.editor.formats[metadata.format]; + this.textFormatHasTransformations = metadata.formatHasTransformations; + this.textEditor = Drupal.editors[this.textFormat.editor]; + + // Store the actual value of this field. We'll need this to restore the + // original value when the user discards his modifications. + const $fieldItems = this.$el.find('.quickedit-field'); + if ($fieldItems.length) { + this.$textElement = $fieldItems.eq(0); + } + else { + this.$textElement = this.$el; + } + this.model.set('originalValue', this.$textElement.html()); + }, + + /** + * @inheritdoc + * + * @return {jQuery} + * The text element edited. + */ + getEditedElement() { + return this.$textElement; + }, + + /** + * @inheritdoc + * + * @param {object} fieldModel + * The field model. + * @param {string} state + * The current state. + */ + stateChange(fieldModel, state) { + const editorModel = this.model; + const from = fieldModel.previous('state'); + const to = state; + switch (to) { + case 'inactive': + break; + + case 'candidate': + // Detach the text editor when entering the 'candidate' state from one + // of the states where it could have been attached. + if (from !== 'inactive' && from !== 'highlighted') { + this.textEditor.detach(this.$textElement.get(0), this.textFormat); + } + // A field model's editor view revert() method is invoked when an + // 'active' field becomes a 'candidate' field. But, in the case of + // this in-place editor, the content will have been *replaced* if the + // text format has transformation filters. Therefore, if we stop + // in-place editing this entity, revert explicitly. + if (from === 'active' && this.textFormatHasTransformations) { + this.revert(); + } + if (from === 'invalid') { + this.removeValidationErrors(); + } + break; + + case 'highlighted': + break; + + case 'activating': + // When transformation filters have been applied to the formatted text + // of this field, then we'll need to load a re-formatted version of it + // without the transformation filters. + if (this.textFormatHasTransformations) { + const $textElement = this.$textElement; + this._getUntransformedText((untransformedText) => { + $textElement.html(untransformedText); + fieldModel.set('state', 'active'); + }); + } + // When no transformation filters have been applied: start WYSIWYG + // editing immediately! + else { + // Defer updating the model until the current state change has + // propagated, to not trigger a nested state change event. + _.defer(() => { + fieldModel.set('state', 'active'); + }); + } + break; + + case 'active': + var textElement = this.$textElement.get(0); + var toolbarView = fieldModel.toolbarView; + this.textEditor.attachInlineEditor( + textElement, + this.textFormat, + toolbarView.getMainWysiwygToolgroupId(), + toolbarView.getFloatedWysiwygToolgroupId(), + ); + // Set the state to 'changed' whenever the content has changed. + this.textEditor.onChange(textElement, (htmlText) => { + editorModel.set('currentValue', htmlText); + fieldModel.set('state', 'changed'); + }); + break; + + case 'changed': + break; + + case 'saving': + if (from === 'invalid') { + this.removeValidationErrors(); + } + this.save(); + break; + + case 'saved': + break; + + case 'invalid': + this.showValidationErrors(); + break; + } + }, + + /** + * @inheritdoc + * + * @return {object} + * The sttings for the quick edit UI. + */ + getQuickEditUISettings() { + return { padding: true, unifiedToolbar: true, fullWidthToolbar: true, popup: false }; + }, + + /** + * @inheritdoc + */ + revert() { + this.$textElement.html(this.model.get('originalValue')); + }, + + /** + * Loads untransformed text for this field. + * + * More accurately: it re-filters formatted text to exclude transformation + * filters used by the text format. + * + * @param {function} callback + * A callback function that will receive the untransformed text. + * + * @see \Drupal\editor\Ajax\GetUntransformedTextCommand + */ + _getUntransformedText(callback) { + const fieldID = this.fieldModel.get('fieldID'); + + // Create a Drupal.ajax instance to load the form. + const textLoaderAjax = Drupal.ajax({ + url: Drupal.quickedit.util.buildUrl(fieldID, Drupal.url('editor/!entity_type/!id/!field_name/!langcode/!view_mode')), + submit: { nocssjs: true }, + }); + + // Implement a scoped editorGetUntransformedText AJAX command: calls the + // callback. + textLoaderAjax.commands.editorGetUntransformedText = function (ajax, response, status) { + callback(response.data); + }; + + // This will ensure our scoped editorGetUntransformedText AJAX command + // gets called. + textLoaderAjax.execute(); + }, + + }); +}(jQuery, Drupal, drupalSettings, _));