Merge branch 'rewriting-version2.0' into module-tools-v2

# Conflicts:
#	src/codex.js
#	src/components/modules/tools.js
This commit is contained in:
Murod Khaydarov 2017-11-25 16:30:05 +03:00
commit 2aac4b45ba
8 changed files with 564 additions and 393 deletions

View file

@ -247,7 +247,7 @@ var CodexEditor =
return module.prepare();
};
return Promise.resolve().then(prepareDecorator(this.moduleInstances['ui'])).then(prepareDecorator(this.moduleInstances['tools'])).catch(function (error) {
return Promise.resolve().then(prepareDecorator(this.moduleInstances.ui)).then(prepareDecorator(this.moduleInstances.tools)).catch(function (error) {
console.log('Error occured', error);
});
@ -5045,7 +5045,6 @@ var CodexEditor =
_classCallCheck(this, Tools);
this.config = config;
this.availabPlugins = {};
this.toolInstances = [];
this.util = __webpack_require__(23);
@ -5063,70 +5062,24 @@ var CodexEditor =
if (!this.config.hasOwnProperty('tools')) {
return false;
return Promise.reject("Can't start without tools");
}
var plugins = this.getListOfPrepareFunctions();
/**
* Preparation Decorator
*
* @param toolBindedPreparationFunction
* @return {Promise}
*/
function waitNextToolPreparation(toolBindedPreparationFunction) {
return this.util.sequence(plugins, this.success, this.fallback);
}
}, {
key: 'success',
value: function success(tool) {
return new Promise(function (resolve, reject) {
console.log('Success!', tool);
}
}, {
key: 'fallback',
value: function fallback(tool) {
toolBindedPreparationFunction().then(resolve).catch(function (error) {
console.log('Plugin is not available because of ', error);
// anyway, go ahead even plugin is not available
resolve();
});
});
}
return new Promise(function (resolvePreparation, rejectPreparation) {
// continue editor initialization if non of tools doesn't need preparation
if (toolPreparationList.length === 0) {
resolvePreparation();
} else {
toolPreparationList.reduce(function (previousToolPrepared, currentToolReadyToPreparation, iteration) {
return previousToolPrepared.then(function () {
return waitNextToolPreparation(currentToolReadyToPreparation);
}).then(function () {
if (iteration == toolPreparationList.length - 1) {
resolvePreparation();
}
});
}, Promise.resolve());
}
});
/**
* - getting class and config
* - push to the toolinstnaces property created instances
*/
// for(let tool in this.config.tools) {
// let toolClass = this.config.tools[tool],
// toolConfig;
//
// if (tool in this.config.toolConfig) {
// toolConfig = this.config.toolConfig[tool];
// } else {
// toolConfig = this.defaultConfig;
// }
//
// this.toolInstances.push(new toolClass(toolConfig));
// }
console.log('Module is not available', tool);
}
/**
@ -5258,15 +5211,6 @@ var CodexEditor =
// */
// return new Promise (function (allPluginsProcessed__) {
//
// /**
// * pluck each element from queue
// * First, send resolved Promise as previous value
// * Each plugins "prepare" method returns a Promise, that's why
// * reduce current element will not be able to continue while can't get
// * a resolved Promise
// *
// * If last plugin is "prepared" then go to the next stage of initialization
// */
// plugins.reduce(function (previousValue, plugin, iteration) {
//
// return previousValue.then(function () {
@ -5332,50 +5276,56 @@ var CodexEditor =
/***/ }),
/* 22 */
/***/ (function(module, exports) {
/***/ (function(module, exports, __webpack_require__) {
'use strict';
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _dom = __webpack_require__(24);
var _dom2 = _interopRequireDefault(_dom);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Module UI
*
* @type {UI}
*/
var className = {
* Module UI
*
* @type {UI}
*/
// let className = {
/**
* @const {string} BLOCK_CLASSNAME - redactor blocks name
*/
BLOCK_CLASSNAME: 'ce-block',
/**
* @const {string} BLOCK_CLASSNAME - redactor blocks name
*/
// BLOCK_CLASSNAME : 'ce-block',
/**
* @const {String} wrapper for plugins content
*/
BLOCK_CONTENT: 'ce-block__content',
/**
* @const {String} wrapper for plugins content
*/
// BLOCK_CONTENT : 'ce-block__content',
/**
* @const {String} BLOCK_STRETCHED - makes block stretched
*/
BLOCK_STRETCHED: 'ce-block--stretched',
/**
* @const {String} BLOCK_STRETCHED - makes block stretched
*/
// BLOCK_STRETCHED : 'ce-block--stretched',
/**
* @const {String} BLOCK_HIGHLIGHTED - adds background
*/
BLOCK_HIGHLIGHTED: 'ce-block--focused',
/**
* @const {String} BLOCK_HIGHLIGHTED - adds background
*/
// BLOCK_HIGHLIGHTED : 'ce-block--focused',
/**
* @const {String} - for all default settings
*/
SETTINGS_ITEM: 'ce-settings__item'
};
/**
* @const {String} - for all default settings
*/
// SETTINGS_ITEM : 'ce-settings__item'
// };
var CSS_ = {
editorWrapper: 'codex-editor',
editorZone: 'ce-redactor'
var CSS = {
editorWrapper: 'codex-editor',
editorZone: 'ce-redactor'
};
/**
@ -5390,103 +5340,127 @@ var CodexEditor =
*
* @property {EditorConfig} config - editor configuration {@link CodexEditor#configuration}
* @property {Object} Editor - available editor modules {@link CodexEditor#moduleInstances}
* @property {Object} nodes -
* @property {Element} nodes.wrapper - element where we need to append redactor
* @property {Element} nodes.wrapper - <codex-editor>
* @property {Element} nodes.redactor - <ce-redactor>
*/
module.exports = function () {
_createClass(UI, null, [{
key: 'name',
_createClass(UI, null, [{
key: 'name',
/**
* Module key name
* @returns {string}
*/
get: function get() {
/**
* Module key name
* @returns {string}
*/
get: function get() {
return 'ui';
}
/**
* @constructor
*
* @param {EditorConfig} config
*/
}]);
function UI(config) {
_classCallCheck(this, UI);
this.config = config;
this.Editor = null;
return 'ui';
}
/**
* Editor modules setter
* @param {object} Editor - available editor modules
* @constructor
*
* @param {EditorConfig} config
*/
}]);
_createClass(UI, [{
key: 'prepare',
function UI(_ref) {
var config = _ref.config;
_classCallCheck(this, UI);
this.config = config;
this.Editor = null;
this.nodes = {
holder: null,
wrapper: null,
redactor: null
};
}
/**
* Editor modules setter
* @param {object} Editor - available editor modules
*/
_createClass(UI, [{
key: 'prepare',
/**
* @protected
*
* Making main interface
*/
value: function prepare() {
var _this = this;
return new Promise(function (resolve, reject) {
/**
* @protected
*
* Making main interface
* Element where we need to append CodeX Editor
* @type {Element}
*/
value: function prepare() {
_this.nodes.holder = document.getElementById(_this.config.holderId);
console.log('ui prepare fired');
if (!_this.nodes.holder) {
return;
return new Promise(function (resolve, reject) {
var wrapper = this.modules.dom.make('DIV', [CSS_.editorWrapper], {}),
redactor = this.modules.dom.make('DIV', [CSS_.editorZone], {}),
toolbar = makeToolBar_();
wrapper.appendChild(toolbar);
wrapper.appendChild(redactor);
/** Save created ui-elements to static nodes state */
editor.nodes.wrapper = wrapper;
editor.nodes.redactor = redactor;
/** Append editor wrapper with redactor zone into holder */
editor.nodes.holder.appendChild(wrapper);
resolve();
})
/** Add toolbox tools */
.then(addTools_)
/** Make container for inline toolbar */
.then(makeInlineToolbar_)
/** Add inline toolbar tools */
.then(addInlineToolbarTools_)
/** Draw wrapper for notifications */
.then(makeNotificationHolder_)
/** Add eventlisteners to redactor elements */
.then(bindEvents_).catch(function () {
editor.core.log("Can't draw editor interface");
});
reject(Error("Holder wasn't found by ID: #" + _this.config.holderId));
return;
}
}, {
key: 'state',
set: function set(Editor) {
this.Editor = Editor;
}
}]);
/**
* Create and save main UI elements
*/
_this.nodes.wrapper = _dom2.default.make('div', CSS.editorWrapper);
_this.nodes.redactor = _dom2.default.make('div', CSS.editorZone);
// toolbar = makeToolBar_();
return UI;
// wrapper.appendChild(toolbar);
_this.nodes.wrapper.appendChild(_this.nodes.redactor);
/**
* Append editor wrapper with redactor zone into holder
*/
_this.nodes.holder.appendChild(_this.nodes.wrapper);
resolve();
})
/** Add toolbox tools */
// .then(addTools_)
/** Make container for inline toolbar */
// .then(makeInlineToolbar_)
/** Add inline toolbar tools */
// .then(addInlineToolbarTools_)
/** Draw wrapper for notifications */
// .then(makeNotificationHolder_)
/** Add eventlisteners to redactor elements */
// .then(bindEvents_)
.catch(function () {
// editor.core.log("Can't draw editor interface");
});
}
}, {
key: 'state',
set: function set(Editor) {
this.Editor = Editor;
}
}]);
return UI;
}();
// /**
// * Codex Editor UI module
@ -5861,18 +5835,190 @@ var CodexEditor =
* Codex Editor Util
*/
module.exports = function () {
function Util() {
_classCallCheck(this, Util);
}
function Util() {
_classCallCheck(this, Util);
}
_createClass(Util, null, [{
key: "sequence",
value: function sequence(chain, success, fallback) {}
}]);
_createClass(Util, null, [{
key: "sequence",
return Util;
/**
* Fires a promise sequence asyncronically
*
* @param chain
* @param success
* @param fallback
* @return {Promise}
*/
value: function sequence(chain, success, fallback) {
return new Promise(function (resolve, reject) {
if (chain.length === 0) {
resolve();
} else {
/**
* pluck each element from queue
* First, send resolved Promise as previous value
* Each plugins "prepare" method returns a Promise, that's why
* reduce current element will not be able to continue while can't get
* a resolved Promise
*/
chain.reduce(function (previousBlock, currentBlock, iteration) {
return previousBlock.then(function () {
return waitNextBlock(currentBlock, success, fallback);
}).then(function () {
// finished
if (iteration == chain.length - 1) {
resolve();
}
});
}, Promise.resolve());
}
});
/**
* Decorator
*
* @param {Function} block
* @param {Function} success
* @param {Function} fallback
*
* @return {Promise}
*/
function waitNextBlock(block, success, fallback) {
return new Promise(function (resolve, reject) {
block().then(function () {
success.call(null, block);
}).then(resolve).catch(function (error) {
fallback(error);
// anyway, go ahead even plugin is not available
resolve();
});
});
}
}
}]);
return Util;
}();
/***/ }),
/* 24 */
/***/ (function(module, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* DOM manupulations helper
*/
var Dom = function () {
function Dom() {
_classCallCheck(this, Dom);
}
_createClass(Dom, null, [{
key: "make",
/**
* Helper for making Elements with classname and attributes
*
* @param {string} tagName - new Element tag name
* @param {array|string} classNames - list or name of CSS classname(s)
* @param {Object} attributes - any attributes
* @return {Element}
*/
value: function make(tagName, classNames, attributes) {
var el = document.createElement(tagName);
if (Array.isArray(classNames)) {
var _el$classList;
(_el$classList = el.classList).add.apply(_el$classList, _toConsumableArray(classNames));
} else if (classNames) {
el.classList.add(classNames);
}
for (var attrName in attributes) {
el[attrName] = attributes[attrName];
}
return el;
}
/**
* Selector Decorator
*
* Returns first match
*
* @param {Element} el - element we searching inside. Default - DOM Document
* @param {String} selector - searching string
*
* @returns {Element}
*/
}, {
key: "find",
value: function find() {
var el = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document;
var selector = arguments[1];
return el.querySelector(selector);
}
/**
* Selector Decorator.
*
* Returns all matches
*
* @param {Element} el - element we searching inside. Default - DOM Document
* @param {String} selector - searching string
* @returns {NodeList}
*/
}, {
key: "findAll",
value: function findAll() {
var el = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document;
var selector = arguments[1];
return el.querySelectorAll(selector);
}
}]);
return Dom;
}();
exports.default = Dom;
;
/***/ })
/******/ ]);
//# sourceMappingURL=codex-editor.js.map

File diff suppressed because one or more lines are too long

View file

@ -1,115 +1,125 @@
/**
* Paragraph Plugin
* Creates DIV tag and adds content to this tag
*/
* @class Paragraph
* @classdesc Paragraph plugin for CodexEditor
*
* @author CodeX Team (team@ifmo.su)
* @copyright CodeX Team 2017
* @license The MIT License (MIT)
* @version 2.0.0
*
*
* @typedef {Object} ParagraphData
* @property {String} text HTML content to insert to paragraph element
*
*/
var paragraph = (function(paragraph_plugin) {
export default class Paragraph {
/**
* @private
* Get the name of the plugin
*
* Make initial paragraph block
* @param {object} JSON with block data
* @return {Element} element to append
* @returns {string} The plugin name
*/
static get name() {
var make_ = function (data) {
return 'paragraph';
/** Create Empty DIV */
var tag = codex.editor.draw.node('DIV', ['ce-paragraph'], {});
if (data && data.text) {
tag.innerHTML = data.text;
}
tag.contentEditable = true;
return tag;
};
}
/**
* @private
* Render plugin`s html and set initial content
*
* Handles input data for save
* @param data
* @param {ParagraphData} data initial plugin content
*/
var prepareDataForSave_ = function(data) {
constructor(data = {}) {
};
/**
* @public
*
* Plugins should have prepare method
* @param config
*/
paragraph_plugin.prepare = function(config) {
};
/*
* @public
*
* Method to render HTML block from JSON
*/
paragraph_plugin.render = function (data) {
return make_(data);
};
/**
* @public
*
* Check output data for validity.
* Should be defined by developer
*/
paragraph_plugin.validate = function(output) {
if (output.text === '')
return;
return output;
};
/**
* @public
*
* Method to extract JSON data from HTML block
*/
paragraph_plugin.save = function (blockContent){
var wrappedText = codex.editor.content.wrapTextWithParagraphs(blockContent.innerHTML),
sanitizerConfig = {
tags : {
p : {},
a: {
href: true,
target: '_blank',
rel: 'nofollow'
},
i: {},
b: {},
}
};
var data = {
"text": codex.editor.sanitizer.clean(wrappedText, sanitizerConfig),
"format": "html",
"introText": '<<same>>'
this._CSS = {
wrapper: 'ce-paragraph'
};
return data;
this._data = {};
};
this.data = data;
paragraph_plugin.destroy = function () {
this._element = this._render();
paragraph = null;
};
}
return paragraph_plugin;
/**
* Create div element and add needed css classes
*
* @returns {HTMLDivElement} Created DIV element
* @private
*/
_render() {
})({});
let div = document.createElement('DIV');
div.classList.add(this._CSS.wrapper);
div.contentEditable = true;
return div;
}
/**
* Check if saved text is empty
*
* @param {ParagraphData} savedData data received from plugins`s element
* @returns {boolean} false if saved text is empty, true otherwise
*/
validate(savedData) {
if (savedData.text.trim() === '') {
return false;
}
return true;
}
/**
* Get plugin`s element HTMLDivElement
*
* @returns {HTMLDivElement} Plugin`s element
*/
get html() {
return this._element;
}
/**
* Get current plugin`s data
*
* @todo sanitize data while saving
*
* @returns {ParagraphData} Current data
*/
get data() {
let text = this._element.innerHTML;
this._data.text = text;
return this._data;
}
/**
* Set new data for plugin
*
* @param {ParagraphData} data data to set
*/
set data(data) {
Object.assign(this._data, data);
this._element.innerHTML = this._data.text || '';
}
}

View file

@ -209,8 +209,9 @@ module.exports = class CodexEditor {
let prepareDecorator = module => module.prepare();
return Promise.resolve()
.then(prepareDecorator(this.moduleInstances['ui']))
.then(prepareDecorator(this.moduleInstances['tools']))
.then(prepareDecorator(this.moduleInstances.ui))
.then(prepareDecorator(this.moduleInstances.tools))
.catch(function (error) {
console.log('Error occured', error);

View file

@ -1,54 +1,37 @@
module.exports = class Dom {
/**
* DOM manupulations helper
*/
export default class Dom {
/**
* Module key name
* @returns {string}
*/
static get name() {
return 'dom';
};
/**
* @param Editor
* @param Editor.modules {@link Tools#list}
* @param Editor.config {@link CodexEditor#configuration}
* @param Editor
*/
set state(Editor) {
this.Editor = Editor;
}
/**
* Draws element with class and properties
* Helper for making Elements with classname and attributes
*
* @param {String} el - Element name
* @param {Array} classList - array of CSS classes
* @param {Object} properties - list of objects/properties
*
* @returns {Element}
* @param {string} tagName - new Element tag name
* @param {array|string} classNames - list or name of CSS classname(s)
* @param {Object} attributes - any attributes
* @return {Element}
*/
make(el, classList, properties) {
static make(tagName, classNames, attributes) {
let element = document.createElement(el);
var el = document.createElement(tagName);
classList.forEach(function (className) {
if ( Array.isArray(classNames) ) {
element.classList.add(className);
el.classList.add(...classNames);
});
} else if( classNames ) {
for(property in properties) {
element.property = properties[property];
el.classList.add(classNames);
}
return element;
for (let attrName in attributes) {
el[attrName] = attributes[attrName];
}
return el;
}
@ -62,7 +45,7 @@ module.exports = class Dom {
*
* @returns {Element}
*/
find(el = document, selector) {
static find(el = document, selector) {
return el.querySelector(selector);
@ -77,7 +60,7 @@ module.exports = class Dom {
* @param {String} selector - searching string
* @returns {NodeList}
*/
findAll(el = document, selector) {
static findAll(el = document, selector) {
return el.querySelectorAll(selector);

View file

@ -63,7 +63,6 @@ module.exports = class Tools {
constructor({ config }) {
this.config = config;
this.availabPlugins = {};
this.toolInstances = [];
this.util = require('../util');
@ -78,83 +77,25 @@ module.exports = class Tools {
if (!this.config.hasOwnProperty('tools')) {
return false;
return Promise.reject("Can't start without tools");
}
let plugins = this.getListOfPrepareFunctions();
/**
* Preparation Decorator
*
* @param toolBindedPreparationFunction
* @return {Promise}
*/
function waitNextToolPreparation(toolBindedPreparationFunction) {
return this.util.sequence(plugins, this.success, this.fallback);
return new Promise(function (resolve, reject) {
}
toolBindedPreparationFunction()
success(tool) {
.then(resolve)
.catch(function (error) {
console.log('Success!', tool);
console.log('Plugin is not available because of ', error);
}
// anyway, go ahead even plugin is not available
resolve();
fallback(tool) {
});
});
}
return new Promise(function (resolvePreparation, rejectPreparation) {
// continue editor initialization if non of tools doesn't need preparation
if (toolPreparationList.length === 0) {
resolvePreparation();
} else {
toolPreparationList.reduce(function (previousToolPrepared, currentToolReadyToPreparation, iteration) {
return previousToolPrepared
.then(() => waitNextToolPreparation(currentToolReadyToPreparation))
.then(() => {
if (iteration == toolPreparationList.length - 1) {
resolvePreparation();
}
});
}, Promise.resolve());
}
});
/**
* - getting class and config
* - push to the toolinstnaces property created instances
*/
// for(let tool in this.config.tools) {
// let toolClass = this.config.tools[tool],
// toolConfig;
//
// if (tool in this.config.toolConfig) {
// toolConfig = this.config.toolConfig[tool];
// } else {
// toolConfig = this.defaultConfig;
// }
//
// this.toolInstances.push(new toolClass(toolConfig));
// }
console.log('Module is not available', tool);
}
@ -284,15 +225,6 @@ module.exports = class Tools {
// */
// return new Promise (function (allPluginsProcessed__) {
//
// /**
// * pluck each element from queue
// * First, send resolved Promise as previous value
// * Each plugins "prepare" method returns a Promise, that's why
// * reduce current element will not be able to continue while can't get
// * a resolved Promise
// *
// * If last plugin is "prepared" then go to the next stage of initialization
// */
// plugins.reduce(function (previousValue, plugin, iteration) {
//
// return previousValue.then(function () {

View file

@ -1,42 +1,45 @@
/**
/**
* Module UI
*
* @type {UI}
*/
let className = {
// let className = {
/**
* @const {string} BLOCK_CLASSNAME - redactor blocks name
*/
BLOCK_CLASSNAME : 'ce-block',
// BLOCK_CLASSNAME : 'ce-block',
/**
* @const {String} wrapper for plugins content
*/
BLOCK_CONTENT : 'ce-block__content',
// BLOCK_CONTENT : 'ce-block__content',
/**
* @const {String} BLOCK_STRETCHED - makes block stretched
*/
BLOCK_STRETCHED : 'ce-block--stretched',
// BLOCK_STRETCHED : 'ce-block--stretched',
/**
* @const {String} BLOCK_HIGHLIGHTED - adds background
*/
BLOCK_HIGHLIGHTED : 'ce-block--focused',
// BLOCK_HIGHLIGHTED : 'ce-block--focused',
/**
* @const {String} - for all default settings
*/
SETTINGS_ITEM : 'ce-settings__item'
};
// SETTINGS_ITEM : 'ce-settings__item'
// };
let CSS_ = {
let CSS = {
editorWrapper : 'codex-editor',
editorZone : 'ce-redactor'
};
import $ from '../dom';
/**
* @class
*
@ -49,6 +52,10 @@ let CSS_ = {
*
* @property {EditorConfig} config - editor configuration {@link CodexEditor#configuration}
* @property {Object} Editor - available editor modules {@link CodexEditor#moduleInstances}
* @property {Object} nodes -
* @property {Element} nodes.wrapper - element where we need to append redactor
* @property {Element} nodes.wrapper - <codex-editor>
* @property {Element} nodes.redactor - <ce-redactor>
*/
module.exports = class UI {
@ -67,11 +74,17 @@ module.exports = class UI {
*
* @param {EditorConfig} config
*/
constructor( config ) {
constructor({ config }) {
this.config = config;
this.Editor = null;
this.nodes = {
holder: null,
wrapper: null,
redactor: null
};
}
@ -92,48 +105,57 @@ module.exports = class UI {
*/
prepare() {
console.log('ui prepare fired');
return new Promise( (resolve, reject) => {
return;
/**
* Element where we need to append CodeX Editor
* @type {Element}
*/
this.nodes.holder = document.getElementById(this.config.holderId);
return new Promise(function (resolve, reject) {
if (!this.nodes.holder) {
let wrapper = this.modules.dom.make('DIV', [ CSS_.editorWrapper ], {}),
redactor = this.modules.dom.make('DIV', [ CSS_.editorZone ], {}),
toolbar = makeToolBar_();
reject(Error("Holder wasn't found by ID: #" + this.config.holderId));
return;
wrapper.appendChild(toolbar);
wrapper.appendChild(redactor);
}
/** Save created ui-elements to static nodes state */
editor.nodes.wrapper = wrapper;
editor.nodes.redactor = redactor;
/**
* Create and save main UI elements
*/
this.nodes.wrapper = $.make('div', CSS.editorWrapper);
this.nodes.redactor = $.make('div', CSS.editorZone);
// toolbar = makeToolBar_();
/** Append editor wrapper with redactor zone into holder */
editor.nodes.holder.appendChild(wrapper);
// wrapper.appendChild(toolbar);
this.nodes.wrapper.appendChild(this.nodes.redactor);
/**
* Append editor wrapper with redactor zone into holder
*/
this.nodes.holder.appendChild(this.nodes.wrapper);
resolve();
})
/** Add toolbox tools */
.then(addTools_)
// .then(addTools_)
/** Make container for inline toolbar */
.then(makeInlineToolbar_)
// .then(makeInlineToolbar_)
/** Add inline toolbar tools */
.then(addInlineToolbarTools_)
// .then(addInlineToolbarTools_)
/** Draw wrapper for notifications */
.then(makeNotificationHolder_)
// .then(makeNotificationHolder_)
/** Add eventlisteners to redactor elements */
.then(bindEvents_)
// .then(bindEvents_)
.catch( function () {
editor.core.log("Can't draw editor interface");
// editor.core.log("Can't draw editor interface");
});

View file

@ -3,8 +3,85 @@
*/
module.exports = class Util {
/**
* Fires a promise sequence asyncronically
*
* @param chain
* @param success
* @param fallback
* @return {Promise}
*/
static sequence(chain, success, fallback) {
return new Promise(function (resolve, reject) {
if (chain.length === 0) {
resolve();
} else {
/**
* pluck each element from queue
* First, send resolved Promise as previous value
* Each plugins "prepare" method returns a Promise, that's why
* reduce current element will not be able to continue while can't get
* a resolved Promise
*/
chain.reduce(function (previousBlock, currentBlock, iteration) {
return previousBlock
.then(() => waitNextBlock(currentBlock, success, fallback))
.then(() => {
// finished
if (iteration == chain.length - 1) {
resolve();
}
});
}, Promise.resolve());
}
});
/**
* Decorator
*
* @param {Function} block
* @param {Function} success
* @param {Function} fallback
*
* @return {Promise}
*/
function waitNextBlock(block, success, fallback) {
return new Promise(function (resolve, reject) {
block()
.then(() => {
success.call(null, block);
})
.then(resolve)
.catch(function (error) {
fallback(error);
// anyway, go ahead even plugin is not available
resolve();
});
});
}
}
};