diff --git a/build/media/webcomponents/js/editor-none/editor-none.js b/build/media/webcomponents/js/editor-none/editor-none.js index f189d1cc5742d..307a60106c1c6 100644 --- a/build/media/webcomponents/js/editor-none/editor-none.js +++ b/build/media/webcomponents/js/editor-none/editor-none.js @@ -1,33 +1,112 @@ -customElements.define('joomla-editor-none', class extends HTMLElement { - connectedCallback() { - this.insertAtCursor = this.insertAtCursor.bind(this); - - const that = this; - /** Register Editor */ - Joomla.editors.instances[that.childNodes[0].id] = { - 'id': that.childNodes[0].id, - 'element': that, - 'getValue': () => { return that.childNodes[0].value; }, - 'setValue': (text) => { return that.childNodes[0].value = text; }, - 'replaceSelection': (text) => { return that.insertAtCursor(text); }, - 'onSave': () => {} - }; - } - - disconnectedCallback() { - /** Remove from the Joomla API */ - delete Joomla.editors.instances[this.childNodes[0].id]; - } - - insertAtCursor(myValue) { - if (this.childNodes[0].selectionStart || this.childNodes[0].selectionStart === 0) { - const startPos = this.childNodes[0].selectionStart; - const endPos = this.childNodes[0].selectionEnd; - this.childNodes[0].value = this.childNodes[0].value.substring(0, startPos) - + myValue - + this.childNodes[0].value.substring(endPos, this.childNodes[0].value.length); - } else { - this.childNodes[0].value += myValue; - } - } -}); \ No newline at end of file +/** + * @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ +window.customElements.define('joomla-editor-none', class extends HTMLElement { + constructor() { + super(); + + // Properties + this.editor = ''; + + // Bindings + this.unregisterEditor = this.unregisterEditor.bind(this); + this.registerEditor = this.registerEditor.bind(this); + this.childrenChange = this.childrenChange.bind(this); + this.getSelection = this.getSelection.bind(this); + + // Watch for children changes. + // eslint-disable-next-line no-return-assign + new MutationObserver(() => this.childrenChange()) + .observe(this, { childList: true }); + } + + /** + * Lifecycle + */ + connectedCallback() { + // Note the mutation observer won't fire for initial contents, + // so childrenChange is also called here. + this.childrenChange(); + } + + /** + * Lifecycle + */ + disconnectedCallback() { + this.unregisterEditor(); + } + + /** + * Get the selected text + */ + getSelection() { + if (document.selection) { + // IE support + this.editor.focus(); + return document.selection.createRange(); + } else if (this.editor.selectionStart || this.editor.selectionStart === 0) { + // MOZILLA/NETSCAPE support + return this.editor.value.substring(this.editor.selectionStart, this.editor.selectionEnd); + } else { + return this.editor.value; + } + } + + /** + * Register the editor + */ + registerEditor() { + if (!window.Joomla + || !window.Joomla.editors + || typeof window.Joomla.editors !== 'object') { + throw new Error('The Joomla API is not correctly registered.'); + } + + window.Joomla.editors.instances[this.editor.id] = { + id: () => this.editor.id, + element: () => this.editor, + // eslint-disable-next-line no-return-assign + getValue: () => this.editor.value, + // eslint-disable-next-line no-return-assign + setValue: text => this.editor.value = text, + // eslint-disable-next-line no-return-assign + getSelection: () => { return this.getSelection(); }, + // eslint-disable-next-line no-return-assign + replaceSelection: text => { + if (this.editor.selectionStart || this.editor.selectionStart === 0) { + this.editor.value = this.editor.value.substring(0, this.editor.selectionStart) + + text + + this.editor.value.substring(this.editor.selectionEnd, this.editor.value.length); + } else { + this.editor.value += text; + } + }, + onSave: () => {}, + }; + } + + /** + * Remove the editor from the Joomla API + */ + unregisterEditor() { + if (this.editor) { + delete window.Joomla.editors.instances[this.editor.id]; + } + } + + /** + * Called when element's child list changes + */ + childrenChange() { + // Ensure the first child is an input with a textarea type. + if (this.firstElementChild + && this.firstElementChild.tagName + && this.firstElementChild.tagName.toLowerCase() === 'textarea' + && this.firstElementChild.getAttribute('id')) { + this.editor = this.firstElementChild; + this.unregisterEditor(); + this.registerEditor(); + } + } +});