/**
* Functions for HtmlEditorFields in the back end.
* Includes the JS for the ImageUpload forms.
*
* Relies on the jquery.form.js plugin to power the
* ajax / iframe submissions
*/
import $ from 'jQuery';
import i18n from 'i18n';
var ss = typeof window.ss !== 'undefined' ? window.ss : {};
/**
* Wrapper for HTML WYSIWYG libraries, which abstracts library internals
* from interface concerns like inserting and editing links.
* Caution: Incomplete and unstable API.
*/
ss.editorWrappers = {};
ss.editorWrappers.tinyMCE = (function() {
// ID of editor this is assigned to
var editorID;
return {
/**
* Initialise the editor
*
* @param {String} ID of parent textarea domID
*/
init: function(ID) {
editorID = ID;
this.create();
},
/**
* Remove the editor and cleanup
*/
destroy: function() {
tinymce.EditorManager.execCommand('mceRemoveEditor', false, editorID);
},
/**
* Get TinyMCE Editor instance
*
* @returns Editor
*/
getInstance: function() {
return tinymce.EditorManager.get(editorID);
},
/**(
* Invoked when a content-modifying UI is opened.
*/
onopen: function() {
// NOOP
},
/**(
* Invoked when a content-modifying UI is closed.
*/
onclose: function() {
// NOOP
},
/**
* Get config for this data
*
* @returns array
*/
getConfig: function() {
var selector = "#" + editorID,
config = $(selector).data('config'),
self = this;
// Add instance specific data to config
config.selector = selector;
// Ensure save events write back to textarea
config.setup = function(ed) {
ed.on('change', function() {
self.save();
});
};
return config;
},
/**
* Write the HTML back to the original text area field.
*/
save: function() {
var instance = this.getInstance();
instance.save();
// Update change detection
$(instance.getElement()).trigger("change");
},
/**
* Create a new instance based on a textarea field.
*/
create: function() {
var config = this.getConfig();
// hack to set baseURL safely
if(typeof config.baseURL !== 'undefined') {
tinymce.EditorManager.baseURL = config.baseURL;
}
tinymce.init(config);
},
/**
* Request an update to editor content
*/
repaint: function() {
// NOOP
},
/**
* @return boolean
*/
isDirty: function() {
return this.getInstance().isDirty();
},
/**
* HTML representation of the edited content.
*
* Returns: {String}
*/
getContent: function() {
return this.getInstance().getContent();
},
/**
* DOM tree of the edited content
*
* Returns: DOMElement
*/
getDOM: function() {
return this.getInstance().getElement();
},
/**
* Returns: DOMElement
*/
getContainer: function() {
return this.getInstance().getContainer();
},
/**
* Get the closest node matching the current selection.
*
* Returns: {jQuery} DOMElement
*/
getSelectedNode: function() {
return this.getInstance().selection.getNode();
},
/**
* Select the given node within the editor DOM
*
* Parameters: {DOMElement}
*/
selectNode: function(node) {
this.getInstance().selection.select(node);
},
/**
* Replace entire content
*
* @param {String} html
* @param {Object} opts
*/
setContent: function(html, opts) {
this.getInstance().setContent(html, opts);
},
/**
* Insert content at the current caret position
*
* @param {String} html
* @param {Object} opts
*/
insertContent: function(html, opts) {
this.getInstance().insertContent(html, opts);
},
/**
* Replace currently selected content
*
* @param {String} html
*/
replaceContent: function(html, opts) {
this.getInstance().execCommand('mceReplaceContent', false, html, opts);
},
/**
* Insert or update a link in the content area (based on current editor selection)
*
* Parameters: {Object} attrs
*/
insertLink: function(attrs, opts) {
this.getInstance().execCommand("mceInsertLink", false, attrs, opts);
},
/**
* Remove the link from the currently selected node (if any).
*/
removeLink: function() {
this.getInstance().execCommand('unlink', false);
},
/**
* Strip any editor-specific notation from link in order to make it presentable in the UI.
*
* Parameters:
* {Object}
* {DOMElement}
*/
cleanLink: function(href, node) {
var settings = this.getConfig,
cb = settings['urlconverter_callback'];
if(cb) href = eval(cb + "(href, node, true);");
// Turn into relative
if(href.match(new RegExp('^' + tinyMCE.settings['document_base_url'] + '(.*)$'))) {
href = RegExp.$1;
}
// Get rid of TinyMCE's temporary URLs
if(href.match(/^javascript:\s*mctmp/)) href = '';
return href;
},
/**
* Creates a bookmark for the currently selected range,
* which can be used to reselect this range at a later point.
* @return {mixed}
*/
createBookmark: function() {
return this.getInstance().selection.getBookmark();
},
/**
* Selects a bookmarked range previously saved through createBookmark().
* @param {mixed} bookmark
*/
moveToBookmark: function(bookmark) {
this.getInstance().selection.moveToBookmark(bookmark);
this.getInstance().focus();
},
/**
* Removes any selection & de-focuses this editor
*/
blur: function() {
this.getInstance().selection.collapse();
},
/**
* Add new undo point with the current DOM content.
*/
addUndo: function() {
this.getInstance().undoManager.add();
}
};
});
// Override this to switch editor wrappers
ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
$.entwine('ss', function($) {
/**
* Class: textarea.htmleditor
*
* Add tinymce to HtmlEditorFields within the CMS. Works in combination
* with a TinyMCE.init() call which is prepopulated with the used HTMLEditorConfig settings,
* and included in the page as an inline