diff --git a/src/rich_text_editor/index.js b/src/rich_text_editor/index.js
index 6803c09ee..f98c71d55 100644
--- a/src/rich_text_editor/index.js
+++ b/src/rich_text_editor/index.js
@@ -2,7 +2,6 @@
* * [add](#add)
* * [get](#get)
* * [getAll](#getall)
- * * [remove](#remove)
* * [getToolbarEl](#gettoolbarel)
*
* This module allows to customize the toolbar of the Rich Text Editor and use commands from the HTML Editing APIs.
@@ -28,7 +27,7 @@ import {on, off} from 'utils/mixins'
module.exports = () => {
let config = {};
const defaults = require('./config/config');
- let toolbar, actions, lastEl;
+ let toolbar, actions, lastEl, globalRte;
return {
@@ -65,6 +64,7 @@ module.exports = () => {
actions = config.actions || [];
toolbar = document.createElement('div');
toolbar.className = `${ppfx}rte-toolbar`;
+ globalRte = this.initRte(document.createElement('div'));
//Avoid closing on toolbar clicking
on(toolbar, 'mousedown', e => e.stopPropagation());
@@ -77,48 +77,89 @@ module.exports = () => {
canvas.getToolsEl().appendChild(toolbar);
},
+
/**
- * Add a new action to the RTE toolbar
+ * Init the built-in RTE
+ * @param {HTMLElement} el
+ * @return {RichTextEditor}
+ * @private
+ */
+ initRte(el) {
+ const pfx = this.pfx;
+ const actionbarContainer = toolbar;
+ const actionbar = this.actionbar;
+ const actions = this.actions || config.actions;
+ const classes = {
+ actionbar: `${pfx}actionbar`,
+ button: `${pfx}action`,
+ active: `${pfx}active`,
+ };
+ const rte = new RichTextEditor({
+ el,
+ classes,
+ actions,
+ actionbar,
+ actionbarContainer,
+ });
+
+ if (rte.actionbar) {
+ this.actionbar = rte.actionbar;
+ }
+
+ if (rte.actions) {
+ this.actions = rte.actions;
+ }
+
+ return rte;
+ },
+
+ /**
+ * Add a new action to the built-in RTE toolbar
* @param {string} name Action name
- * @param {Object} opts Action options
+ * @param {Object} action Action options
* @example
* rte.add('bold', {
* icon: 'B',
- * title: 'Bold',
+ * attributes: {title: 'Bold',}
* result: rte => rte.exec('bold')
* });
* rte.add('link', {
* icon: 'L',
- * title: 'Link',
- * result: rte => {
- * const url = window.prompt('Enter the link URL')
- * if (url) rte.exec('createLink', url)
- * }
+ * attributes: {title: 'Link',}
+ * result: rte =>
+ * rte.insertHTML(`${rte.selection()}`)
* });
*/
- add(name, opts = {}) {
- opts.name = name;
- actions.push(opts);
- //gloabl.addAction();
+ add(name, action = {}) {
+ action.name = name;
+ globalRte.getActions().push(action);
+ globalRte.addAction(action, {sync: 1});
},
/**
- * Get the command by its name
- * @param {string} command Command name
- * @return {Model}
+ * Get the action by its name
+ * @param {string} name Action name
+ * @return {Object}
* @example
- * var cm = rte.get('fontSize');
+ * const action = rte.get('bold');
+ * // {name: 'bold', ...}
*/
- get(command) {
- return commands.where({command})[0];
+ get(name) {
+ let result;
+ globalRte.getActions().forEach(action => {
+ if (action.name == name) {
+ result = action;
+ }
+ });
+ return result;
},
/**
- * Returns the collection of commands
- * @return {Collection}
+ * Get all actions
+ * @return {Array}
*/
getAll() {
- return commands;
+ return globalRte.getActions();
},
/**
@@ -153,24 +194,11 @@ module.exports = () => {
enable(view, rte) {
lastEl = view.el;
const em = config.em;
- const pfx = this.pfx;
const el = view.getChildrenContainer();
const customRte = this.customRte;
- const actionbar = this.actionbar;
- const actionbarContainer = toolbar;
- const classes = {
- actionbar: `${pfx}actionbar`,
- button: `${pfx}action`,
- active: `${pfx}active`,
- };
toolbar.style.display = '';
- rte = customRte ? customRte.enable(el, rte) :
- new RichTextEditor({el, actionbarContainer, classes, actionbar}).enable();
-
- if (rte.actionbar) {
- this.actionbar = rte.actionbar;
- }
+ rte = customRte ? customRte.enable(el, rte) : this.initRte(el).enable();
if (em) {
setTimeout(this.udpatePosition.bind(this), 0);
@@ -190,6 +218,7 @@ module.exports = () => {
* */
disable(view, rte) {
const customRte = this.customRte;
+ const style = toolbar.style;
var el = view.getChildrenContainer();
if (customRte) {
@@ -198,13 +227,14 @@ module.exports = () => {
rte.disable();
}
- toolbar.style.display = 'none';
+ style.display = 'none';
+ style.top = 0;
+ style.left = 0;
},
/**
- * Return the toolbar element
+ * Get the toolbar element
* @return {HTMLElement}
- * @private
*/
getToolbarEl() {
return toolbar;
diff --git a/src/rich_text_editor/model/RichTextEditor.js b/src/rich_text_editor/model/RichTextEditor.js
index deed0b457..faf8478c0 100644
--- a/src/rich_text_editor/model/RichTextEditor.js
+++ b/src/rich_text_editor/model/RichTextEditor.js
@@ -5,7 +5,7 @@ import {on, off} from 'utils/mixins'
const RTE_KEY = '_rte';
-const actions = {
+const defActions = {
bold: {
name: 'bold',
icon: 'B',
@@ -38,6 +38,12 @@ const actions = {
},
result: (rte) => rte.insertHTML(`${rte.selection()}`)
},
+ avoid: {
+ name: 'avoid',
+ icon: 'avoid',
+ attributes: {title: 'avoid'},
+ result: (rte) => rte.insertHTML(`Avoid`)
+ },
}
export default class RichTextEditor {
@@ -49,22 +55,25 @@ export default class RichTextEditor {
return el[RTE_KEY];
}
- //el.oninput = e => settings.onChange && settings.onChange(e.target.innerHTML);
- //el.onkeydown = e => (e.which === 9 && e.preventDefault());
el[RTE_KEY] = this;
this.el = el;
this.doc = el.ownerDocument;
+ //el.oninput = e => settings.onChange && settings.onChange(e.target.innerHTML);
+ //el.onkeydown = e => (e.which === 9 && e.preventDefault());
+
this.updateActiveActions = this.updateActiveActions.bind(this);
- settings.actions = settings.actions
- ? settings.actions.map(action => {
+ const settAct = settings.actions || [];
+ settAct.forEach((action, i) => {
if (typeof action === 'string') {
- return actions[action];
- } else if (actions[action.name]) {
- return {...actions[action.name], ...action};
+ action = defActions[action];
+ } else if (defActions[action.name]) {
+ action = {...defActions[action.name], ...action};
}
- return action;
- }) : Object.keys(actions).map(action => actions[action])
+ settAct[i] = action;
+ });
+ const actions = settAct.length ? settAct :
+ Object.keys(defActions).map(action => defActions[action])
settings.classes = { ...{
actionbar: 'actionbar',
@@ -77,6 +86,7 @@ export default class RichTextEditor {
this.actionbar = actionbar;
this.settings = settings;
this.classes = classes;
+ this.actions = actions;
if (!actionbar) {
const actionbarCont = settings.actionbarContainer;
@@ -84,7 +94,7 @@ export default class RichTextEditor {
actionbar.className = classes.actionbar;
actionbarCont.appendChild(actionbar);
this.actionbar = actionbar;
- settings.actions.forEach(action => this.addAction(action))
+ actions.forEach(action => this.addAction(action))
}
settings.styleWithCSS && this.exec('styleWithCSS');
@@ -94,7 +104,7 @@ export default class RichTextEditor {
}
updateActiveActions() {
- this.actions().forEach(action => {
+ this.getActions().forEach(action => {
const btn = action.btn;
const active = this.classes.active;
btn.className = btn.className.replace(active, '').trim();
@@ -110,6 +120,7 @@ export default class RichTextEditor {
this.el.contentEditable = true;
on(this.el, 'mouseup keyup', this.updateActiveActions)
this.syncActions();
+ this.updateActiveActions();
this.el.focus();
return this;
}
@@ -125,7 +136,7 @@ export default class RichTextEditor {
* Sync actions with the current RTE
*/
syncActions() {
- this.actions().forEach(action => {
+ this.getActions().forEach(action => {
const event = action.event || 'click';
action.btn[`on${event}`] = e => {
action.result(this);
@@ -137,8 +148,10 @@ export default class RichTextEditor {
/**
* Add new action to the actionbar
* @param {Object} action
+ * @param {Object} [opts={}]
*/
- addAction(action) {
+ addAction(action, opts = {}) {
+ const sync = opts.sync;
const btn = document.createElement('span');
const icon = action.icon;
const attr = action.attributes || {};
@@ -156,14 +169,18 @@ export default class RichTextEditor {
}
this.actionbarEl().appendChild(btn);
+
+ if (sync) {
+ this.syncActions();
+ }
}
/**
* Get the array of current actions
* @return {Array}
*/
- actions() {
- return this.settings.actions;
+ getActions() {
+ return this.actions;
}
/**