first commit
This commit is contained in:
226
media/plg_editors_tinymce/js/tinymce.js
Normal file
226
media/plg_editors_tinymce/js/tinymce.js
Normal file
@ -0,0 +1,226 @@
|
||||
import { JoomlaEditor, JoomlaEditorDecorator } from 'editor-api';
|
||||
|
||||
/**
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
/* global tinymce, tinyMCE */
|
||||
|
||||
// Debounce ReInit per editor ID
|
||||
const reInitQueue = {};
|
||||
const debounceReInit = (editor, element, pluginOptions) => {
|
||||
if (reInitQueue[element.id]) {
|
||||
clearTimeout(reInitQueue[element.id]);
|
||||
}
|
||||
reInitQueue[element.id] = setTimeout(() => {
|
||||
editor.remove();
|
||||
JoomlaEditor.unregister(element.id);
|
||||
Joomla.JoomlaTinyMCE.setupEditor(element, pluginOptions);
|
||||
}, 500);
|
||||
};
|
||||
|
||||
/**
|
||||
* TinyMCE Decorator for JoomlaEditor
|
||||
*/
|
||||
class TinyMCEDecorator extends JoomlaEditorDecorator {
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
getValue() {
|
||||
return this.instance.getContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} value
|
||||
* @returns {TinyMCEDecorator}
|
||||
*/
|
||||
setValue(value) {
|
||||
this.instance.setContent(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
getSelection() {
|
||||
return this.instance.selection.getContent({
|
||||
format: 'text'
|
||||
});
|
||||
}
|
||||
replaceSelection(value) {
|
||||
this.instance.execCommand('mceInsertContent', false, value);
|
||||
return this;
|
||||
}
|
||||
disable(enable) {
|
||||
this.instance.setMode(!enable ? 'readonly' : 'design');
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the editor visibility mode. Used by Toggle button.
|
||||
* Should be implemented by editor provider.
|
||||
*
|
||||
* @param {boolean} show Optional. True to show, false to hide.
|
||||
*
|
||||
* @returns {boolean} Return True when editor become visible, and false when become hidden.
|
||||
*/
|
||||
toggle(show) {
|
||||
let visible = false;
|
||||
if (show || this.instance.isHidden()) {
|
||||
this.instance.show();
|
||||
visible = true;
|
||||
} else {
|
||||
this.instance.hide();
|
||||
}
|
||||
return visible;
|
||||
}
|
||||
}
|
||||
Joomla.JoomlaTinyMCE = {
|
||||
/**
|
||||
* Find all TinyMCE elements and initialize TinyMCE instance for each
|
||||
*
|
||||
* @param {HTMLElement} target Target Element where to search for the editor element
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
setupEditors: target => {
|
||||
const container = target || document;
|
||||
const pluginOptions = Joomla.getOptions('plg_editor_tinymce', {});
|
||||
const editors = container.querySelectorAll('.js-editor-tinymce');
|
||||
editors.forEach(editor => {
|
||||
const currentEditor = editor.querySelector('textarea');
|
||||
const toggleButton = editor.querySelector('.js-tiny-toggler-button');
|
||||
const toggleIcon = toggleButton.querySelector('.icon-eye');
|
||||
|
||||
// Set up the editor
|
||||
Joomla.JoomlaTinyMCE.setupEditor(currentEditor, pluginOptions);
|
||||
|
||||
// Set up the toggle button
|
||||
if (toggleButton) {
|
||||
toggleButton.removeAttribute('disabled');
|
||||
}
|
||||
|
||||
// Find out when editor is interacted
|
||||
editor.addEventListener('click', event => {
|
||||
JoomlaEditor.setActive(currentEditor.id);
|
||||
|
||||
// Check for the click on a toggle button
|
||||
const toggler = event.target.closest('.js-tiny-toggler-button');
|
||||
const ed = JoomlaEditor.getActive();
|
||||
if (toggler && ed) {
|
||||
const visible = ed.toggle();
|
||||
if (toggleIcon) {
|
||||
toggleIcon.setAttribute('class', visible ? 'icon-eye' : 'icon-eye-slash');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Initialize TinyMCE editor instance
|
||||
*
|
||||
* @param {HTMLElement} element
|
||||
* @param {Object} pluginOptions
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
setupEditor: (element, pluginOptions) => {
|
||||
// Check whether the editor already has been set
|
||||
if (JoomlaEditor.get(element.id)) {
|
||||
return;
|
||||
}
|
||||
const name = element ? element.getAttribute('name').replace(/\[\]|\]/g, '').split('[').pop() : 'default'; // Get Editor name
|
||||
const tinyMCEOptions = pluginOptions ? pluginOptions.tinyMCE || {} : {};
|
||||
const defaultOptions = tinyMCEOptions.default || {};
|
||||
// Check specific options by the name
|
||||
let options = tinyMCEOptions[name] ? tinyMCEOptions[name] : defaultOptions;
|
||||
|
||||
// Avoid an unexpected changes, and copy the options object
|
||||
if (options.joomlaMergeDefaults) {
|
||||
options = Joomla.extend(Joomla.extend({}, defaultOptions), options);
|
||||
} else {
|
||||
options = Joomla.extend({}, options);
|
||||
}
|
||||
if (element) {
|
||||
// We already have the Target, so reset the selector and assign given element as target
|
||||
options.selector = null;
|
||||
options.target = element;
|
||||
}
|
||||
|
||||
// Ensure tinymce is initialised in readonly mode if the textarea has readonly applied
|
||||
let readOnlyMode = false;
|
||||
if (element) {
|
||||
readOnlyMode = element.readOnly;
|
||||
}
|
||||
options.setup = editor => {
|
||||
editor.mode.set(readOnlyMode ? 'readonly' : 'design');
|
||||
};
|
||||
|
||||
// We'll take over the onSubmit event
|
||||
options.init_instance_callback = editor => {
|
||||
editor.on('submit', () => {
|
||||
if (editor.isHidden()) {
|
||||
editor.show();
|
||||
}
|
||||
}, true);
|
||||
};
|
||||
|
||||
// Create a new instance
|
||||
const ed = new tinyMCE.Editor(element.id, options, tinymce.EditorManager);
|
||||
// Create a decorator
|
||||
const jEditor = new TinyMCEDecorator(ed, 'tinymce', element.id);
|
||||
|
||||
// Work around iframe behavior, when iframe element changes location in DOM and losing its content.
|
||||
// Re init editor when iframe is reloaded.
|
||||
if (!ed.inline) {
|
||||
let isReady = false;
|
||||
let isRendered = false;
|
||||
const listenIframeReload = () => {
|
||||
const $iframe = ed.getContentAreaContainer().querySelector('iframe');
|
||||
$iframe.addEventListener('load', () => {
|
||||
debounceReInit(ed, element, pluginOptions);
|
||||
});
|
||||
};
|
||||
|
||||
// Make sure iframe is fully loaded.
|
||||
// This works differently in different browsers, so have to listen both "load" and "PostRender" events.
|
||||
ed.on('load', () => {
|
||||
isReady = true;
|
||||
if (isRendered) {
|
||||
listenIframeReload();
|
||||
}
|
||||
});
|
||||
ed.on('PostRender', () => {
|
||||
isRendered = true;
|
||||
if (isReady) {
|
||||
listenIframeReload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Find out when editor is interacted
|
||||
ed.on('focus', () => {
|
||||
JoomlaEditor.setActive(jEditor);
|
||||
});
|
||||
|
||||
// Render the editor
|
||||
ed.render();
|
||||
// Register the editor's instance to JoomlaEditor
|
||||
JoomlaEditor.register(jEditor);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize at an initial page load
|
||||
*/
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
Joomla.JoomlaTinyMCE.setupEditors(document);
|
||||
});
|
||||
|
||||
/**
|
||||
* Initialize when a part of the page was updated
|
||||
*/
|
||||
document.addEventListener('joomla:updated', ({
|
||||
target
|
||||
}) => Joomla.JoomlaTinyMCE.setupEditors(target));
|
||||
Reference in New Issue
Block a user