From 19320da8d1fb4e342f7dd6b2ad2ea8e482690447 Mon Sep 17 00:00:00 2001 From: Murod Khaydarov Date: Tue, 21 Nov 2017 00:17:18 +0300 Subject: [PATCH] trying new architecture --- codex-editor.js | 1011 +++++++++++++++++++++++++++++-------------- codex-editor.js.map | 2 +- codex.js | 56 ++- package.json | 2 +- src/modules/core.js | 337 +++++++-------- src/modules/dom.js | 63 +++ src/modules/draw.js | 26 -- src/modules/ui.js | 159 +++---- webpack.config.js | 2 +- 9 files changed, 1010 insertions(+), 648 deletions(-) create mode 100644 src/modules/dom.js diff --git a/codex-editor.js b/codex-editor.js index 137fd54d..606589c7 100644 --- a/codex-editor.js +++ b/codex-editor.js @@ -74,7 +74,11 @@ var CodexEditor = this._configuration.holderId = config.holderId; this._configuration.placeholder = config.placeholder || 'write your story...'; - this._configuration.sanitizer = config.sanitizer || {}; + this._configuration.sanitizer = config.sanitizer || { + p: true, + b: true, + a: true + }; this._configuration.hideToolbar = config.hideToolbar ? config.hideToolbar : false; } @@ -103,7 +107,7 @@ var CodexEditor = /** Editor version */ get: function get() { - return ("1.7.8"); + return ("2.0.0"); } }]); @@ -113,6 +117,8 @@ var CodexEditor = /** Privates */ + var _this = this; + _classCallCheck(this, CodexEditor); this._configuration = {}; @@ -122,7 +128,11 @@ var CodexEditor = this.eventsDispatcher = new Events(); - this.init(); + return Promise.resolve().then(function () { + return _this.init(); + }).then(function () { + return _this.prepare(); + }); } /** @@ -136,8 +146,9 @@ var CodexEditor = key: 'init', value: function init() { - var Core = __webpack_require__(1), - Tools = __webpack_require__(2); + var Dom = __webpack_require__(1), + Core = __webpack_require__(2), + Ui = __webpack_require__(3); // transport = require('./src/modules/transport'), // renderer = require('./src/modules/renderer'), // saver = require('./src/modules/saver'), @@ -154,13 +165,14 @@ var CodexEditor = // paste = require('./src/modules/paste'); var moduleList = { + 'dom': Dom, 'core': Core, - 'tools': Tools + 'ui': Ui }; for (var moduleName in moduleList) { - var modules = []; + var modules = {}; for (var moduleExtends in moduleList) { @@ -168,7 +180,7 @@ var CodexEditor = continue; } - modules.push(moduleList[moduleExtends]); + modules[moduleExtends] = moduleList[moduleExtends]; } this.moduleInstances[moduleName] = new moduleList[moduleName]({ @@ -178,16 +190,30 @@ var CodexEditor = nodes: this.nodes }); } + } - // this.moduleInstances['core'].prepare(); - Promise.resolve().then(this.moduleInstances['core'].prepare.bind(this.moduleInstances['core'])); - // .then(this.moduleInstances['ui'].prepare) + /** + * @param module - module instance + * @returns {*} + */ + + }, { + key: 'prepare', + value: function prepare(module) { + + function prepareDecorator(module) { + + return module.prepare(); + } + + return Promise.resolve().then(prepareDecorator(this.moduleInstances['core'])).then(prepareDecorator(this.moduleInstances['ui'])); // .then(this.moduleInstances['tools'.prepare]) // .catch(function (error) { // // console.log('Error occured', error); // // }); + } }]); @@ -370,10 +396,102 @@ var CodexEditor = /***/ }), /* 1 */ +/***/ (function(module, exports) { + + "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; }; }(); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + module.exports = function () { + function Dom() { + _classCallCheck(this, Dom); + } + + _createClass(Dom, [{ + key: "make", + + + /** + * Draws element with class and properties + * + * @param {String} el - Element name + * @param {Array} classList - array of CSS classes + * @param {Object} properties - list of objects/properties + * + * @returns {Element} + */ + value: function make(el, classList, properties) { + + var element = document.createElement(el); + + classList.forEach(function (className) { + + element.classList.add(className); + }); + + for (property in properties) { + + element.property = properties[property]; + } + + return element; + } + + /** + * 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; + }(); + +/***/ }), +/* 2 */ /***/ (function(module, exports) { 'use strict'; + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + 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 _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } @@ -405,27 +523,31 @@ var CodexEditor = this.state = {}; } + /** + * @public + * + * Editor preparing method + * @return Promise + */ + + _createClass(Core, [{ key: 'prepare', value: function prepare() { - console.log(this); var self = this; return new Promise(function (resolve, reject) { - console.log(self); - // if (typeof editor.nodes.holder === undefined || editor.nodes.holder === null) { - // - // reject(Error("Holder wasn't found by ID: #" + userSettings.holderId)); - // - // } else { - // - // resolve(); - // - // } - // - // resolve(); + if (_typeof(self.Editor.config.holderId) === undefined) { + + reject(Error("Holder wasn't found by ID: #" + userSettings.holderId)); + } else { + + resolve(); + } + + resolve(); }); } @@ -462,6 +584,127 @@ var CodexEditor = // do nothing } } + + /** + * Native Ajax + * @param {String} settings.url - request URL + * @param {function} settings.beforeSend - returned value will be passed as context to the Success, Error and Progress callbacks + * @param {function} settings.success + * @param {function} settings.progress + */ + + }, { + key: 'ajax', + value: function ajax(settings) { + + if (!settings || !settings.url) { + + return; + } + + var XMLHTTP = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'), + encodedString, + isFormData, + prop; + + settings.async = true; + settings.type = settings.type || 'GET'; + settings.data = settings.data || ''; + settings['content-type'] = settings['content-type'] || 'application/json; charset=utf-8'; + + if (settings.type == 'GET' && settings.data) { + + settings.url = /\?/.test(settings.url) ? settings.url + '&' + settings.data : settings.url + '?' + settings.data; + } else { + + encodedString = ''; + for (prop in settings.data) { + + encodedString += prop + '=' + encodeURIComponent(settings.data[prop]) + '&'; + } + } + + if (settings.withCredentials) { + + XMLHTTP.withCredentials = true; + } + + /** + * Value returned in beforeSend funtion will be passed as context to the other response callbacks + * If beforeSend returns false, AJAX will be blocked + */ + var responseContext = void 0, + beforeSendResult = void 0; + + if (typeof settings.beforeSend === 'function') { + + beforeSendResult = settings.beforeSend.call(); + + if (beforeSendResult === false) { + + return; + } + } + + XMLHTTP.open(settings.type, settings.url, settings.async); + + /** + * If we send FormData, we need no content-type header + */ + isFormData = isFormData_(settings.data); + + if (!isFormData) { + + if (settings.type !== 'POST') { + + XMLHTTP.setRequestHeader('Content-type', settings['content-type']); + } else { + + XMLHTTP.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + } + } + + XMLHTTP.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + + responseContext = beforeSendResult || XMLHTTP; + + if (typeof settings.progress === 'function') { + + XMLHTTP.upload.onprogress = settings.progress.bind(responseContext); + } + + XMLHTTP.onreadystatechange = function () { + + if (XMLHTTP.readyState === 4) { + + if (XMLHTTP.status === 200) { + + if (typeof settings.success === 'function') { + + settings.success.call(responseContext, XMLHTTP.responseText); + } + } else { + + if (typeof settings.error === 'function') { + + settings.error.call(responseContext, XMLHTTP.responseText, XMLHTTP.status); + } + } + } + }; + + if (isFormData) { + + // Sending FormData + XMLHTTP.send(settings.data); + } else { + + // POST requests + XMLHTTP.send(encodedString); + } + + return XMLHTTP; + } }]); return Core; @@ -470,59 +713,6 @@ var CodexEditor = // // let editor = codex.editor; // - // /** - // * @public - // * - // * Editor preparing method - // * @return Promise - // */ - // core.prepare = function (userSettings) { - // - // return new Promise(function (resolve, reject) { - // - // if ( userSettings ) { - // - // editor.settings.tools = userSettings.tools || editor.settings.tools; - // - // } - // - // if (userSettings.data) { - // - // editor.state.blocks = userSettings.data; - // - // } - // - // if (userSettings.initialBlockPlugin) { - // - // editor.settings.initialBlockPlugin = userSettings.initialBlockPlugin; - // - // } - // - // if (userSettings.sanitizer) { - // - // editor.settings.sanitizer = userSettings.sanitizer; - // - // } - // - // editor.hideToolbar = userSettings.hideToolbar; - // - // editor.settings.placeholder = userSettings.placeholder || ''; - // - // editor.nodes.holder = document.getElementById(userSettings.holderId || editor.settings.holderId); - // - // if (typeof editor.nodes.holder === undefined || editor.nodes.holder === null) { - // - // reject(Error("Holder wasn't found by ID: #" + userSettings.holderId)); - // - // } else { - // - // resolve(); - // - // } - // - // }); - // - // }; // // /** // * @protected @@ -576,145 +766,6 @@ var CodexEditor = // }; // // /** - // * Native Ajax - // * @param {String} settings.url - request URL - // * @param {function} settings.beforeSend - returned value will be passed as context to the Success, Error and Progress callbacks - // * @param {function} settings.success - // * @param {function} settings.progress - // */ - // core.ajax = function (settings) { - // - // if (!settings || !settings.url) { - // - // return; - // - // } - // - // var XMLHTTP = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'), - // encodedString, - // isFormData, - // prop; - // - // - // settings.async = true; - // settings.type = settings.type || 'GET'; - // settings.data = settings.data || ''; - // settings['content-type'] = settings['content-type'] || 'application/json; charset=utf-8'; - // - // if (settings.type == 'GET' && settings.data) { - // - // settings.url = /\?/.test(settings.url) ? settings.url + '&' + settings.data : settings.url + '?' + settings.data; - // - // } else { - // - // encodedString = ''; - // for(prop in settings.data) { - // - // encodedString += (prop + '=' + encodeURIComponent(settings.data[prop]) + '&'); - // - // } - // - // } - // - // if (settings.withCredentials) { - // - // XMLHTTP.withCredentials = true; - // - // } - // - // /** - // * Value returned in beforeSend funtion will be passed as context to the other response callbacks - // * If beforeSend returns false, AJAX will be blocked - // */ - // let responseContext, - // beforeSendResult; - // - // if (typeof settings.beforeSend === 'function') { - // - // beforeSendResult = settings.beforeSend.call(); - // - // if (beforeSendResult === false) { - // - // return; - // - // } - // - // } - // - // XMLHTTP.open( settings.type, settings.url, settings.async ); - // - // /** - // * If we send FormData, we need no content-type header - // */ - // isFormData = isFormData_(settings.data); - // - // if (!isFormData) { - // - // if (settings.type !== 'POST') { - // - // XMLHTTP.setRequestHeader('Content-type', settings['content-type']); - // - // } else { - // - // XMLHTTP.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); - // - // } - // - // } - // - // XMLHTTP.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); - // - // responseContext = beforeSendResult || XMLHTTP; - // - // if (typeof settings.progress === 'function') { - // - // XMLHTTP.upload.onprogress = settings.progress.bind(responseContext); - // - // } - // - // XMLHTTP.onreadystatechange = function () { - // - // if (XMLHTTP.readyState === 4) { - // - // if (XMLHTTP.status === 200) { - // - // if (typeof settings.success === 'function') { - // - // settings.success.call(responseContext, XMLHTTP.responseText); - // - // } - // - // } else { - // - // if (typeof settings.error === 'function') { - // - // settings.error.call(responseContext, XMLHTTP.responseText, XMLHTTP.status); - // - // } - // - // } - // - // } - // - // }; - // - // if (isFormData) { - // - // // Sending FormData - // XMLHTTP.send(settings.data); - // - // } else { - // - // // POST requests - // XMLHTTP.send(encodedString); - // - // } - // - // return XMLHTTP; - // - // }; - // - // /** // * Appends script to head of document // * @return Promise // */ @@ -818,180 +869,472 @@ var CodexEditor = // })({}); /***/ }), -/* 2 */ +/* 3 */ /***/ (function(module, exports) { - "use strict"; + '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; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + /** + * Module UI + * + * @type {UI} + */ + var className = { + + /** + * @const {string} BLOCK_CLASSNAME - redactor blocks name + */ + BLOCK_CLASSNAME: 'ce-block', + + /** + * @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_HIGHLIGHTED - adds background + */ + BLOCK_HIGHLIGHTED: 'ce-block--focused', + + /** + * @const {String} - for all default settings + */ + SETTINGS_ITEM: 'ce-settings__item' + }; + + var CSS_ = { + editorWrapper: 'codex-editor', + editorZone: 'ce-redactor' + }; + module.exports = function () { - function Tools() { - _classCallCheck(this, Tools); + function UI(Editor) { + _classCallCheck(this, UI); + + this.Editor = Editor; + + this.modules = this.Editor.modules; } - _createClass(Tools, [{ - key: "prepare", - value: function prepare() {} + /** + * @protected + * + * Making main interface + */ + + + _createClass(UI, [{ + key: 'prepare', + value: function prepare() { + + 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"); + }); + } }]); - return Tools; + return UI; }(); // /** - // * Module working with plugins - // */ - // module.exports = (function () { + // * Codex Editor UI module + // * + // * @author Codex Team + // * @version 1.2.0 + // */ + // + // module.exports = (function (ui) { // // let editor = codex.editor; // // /** - // * Initialize plugins before using - // * Ex. Load scripts or call some internal methods - // * @return Promise + // * Basic editor classnames // */ - // function prepare() { + // ui.prepare = function () { // - // return new Promise(function (resolve_, reject_) { + // - // Promise.resolve() - // - // /** - // * Compose a sequence of plugins that requires preparation - // */ - // .then(function () { - // - // let pluginsRequiresPreparation = [], - // allPlugins = editor.tools; - // - // for ( let pluginName in allPlugins ) { - // - // let plugin = allPlugins[pluginName]; - // - // if (plugin.prepare && typeof plugin.prepare != 'function' || !plugin.prepare) { - // - // continue; - // - // } - // - // pluginsRequiresPreparation.push(plugin); - // - // } - // - // /** - // * If no one passed plugins requires preparation, finish prepare() and go ahead - // */ - // if (!pluginsRequiresPreparation.length) { - // - // resolve_(); - // - // } - // - // return pluginsRequiresPreparation; - // - // }) - // - // /** Wait plugins while they prepares */ - // .then(waitAllPluginsPreparation_) - // - // .then(function () { - // - // editor.core.log('Plugins loaded', 'info'); - // resolve_(); - // - // }).catch(function (error) { - // - // reject_(error); - // - // }); - // - // }); - // - // } + // }; // // /** - // * @param {array} plugins - list of tools that requires preparation - // * @return {Promise} resolved while all plugins will be ready or failed - // */ - // function waitAllPluginsPreparation_(plugins) { + // * @private + // * Draws inline toolbar zone + // */ + // var makeInlineToolbar_ = function () { + // + // var container = editor.draw.inlineToolbar(); + // + // /** Append to redactor new inline block */ + // editor.nodes.inlineToolbar.wrapper = container; + // + // /** Draw toolbar buttons */ + // editor.nodes.inlineToolbar.buttons = editor.draw.inlineToolbarButtons(); + // + // /** Buttons action or settings */ + // editor.nodes.inlineToolbar.actions = editor.draw.inlineToolbarActions(); + // + // /** Append to inline toolbar buttons as part of it */ + // editor.nodes.inlineToolbar.wrapper.appendChild(editor.nodes.inlineToolbar.buttons); + // editor.nodes.inlineToolbar.wrapper.appendChild(editor.nodes.inlineToolbar.actions); + // + // editor.nodes.wrapper.appendChild(editor.nodes.inlineToolbar.wrapper); + // + // }; + // + // var makeToolBar_ = function () { + // + // let toolbar = editor.draw.toolbar(), + // blockButtons = makeToolbarSettings_(), + // toolbarContent = makeToolbarContent_(); + // + // /** Appending first-level block buttons */ + // toolbar.appendChild(blockButtons); + // + // /** Append toolbarContent to toolbar */ + // toolbar.appendChild(toolbarContent); + // + // /** Make toolbar global */ + // editor.nodes.toolbar = toolbar; + // + // return toolbar; + // + // }; + // + // var makeToolbarContent_ = function () { + // + // let toolbarContent = editor.draw.toolbarContent(), + // toolbox = editor.draw.toolbox(), + // plusButton = editor.draw.plusButton(); + // + // /** Append plus button */ + // toolbarContent.appendChild(plusButton); + // + // /** Appending toolbar tools */ + // toolbarContent.appendChild(toolbox); + // + // /** Make Toolbox and plusButton global */ + // editor.nodes.toolbox = toolbox; + // editor.nodes.plusButton = plusButton; + // + // return toolbarContent; + // + // }; + // + // var makeToolbarSettings_ = function () { + // + // let blockSettings = editor.draw.blockSettings(), + // blockButtons = editor.draw.blockButtons(), + // defaultSettings = editor.draw.defaultSettings(), + // showSettingsButton = editor.draw.settingsButton(), + // showTrashButton = editor.toolbar.settings.makeRemoveBlockButton(), + // pluginSettings = editor.draw.pluginsSettings(); + // + // /** Add default and plugins settings */ + // blockSettings.appendChild(pluginSettings); + // blockSettings.appendChild(defaultSettings); // // /** - // * @calls allPluginsProcessed__ when all plugins prepared or failed - // */ - // return new Promise (function (allPluginsProcessed__) { + // * Make blocks buttons + // * This block contains settings button and remove block button + // */ + // blockButtons.appendChild(showSettingsButton); + // blockButtons.appendChild(showTrashButton); + // blockButtons.appendChild(blockSettings); // + // /** Make BlockSettings, PluginSettings, DefaultSettings global */ + // editor.nodes.blockSettings = blockSettings; + // editor.nodes.pluginSettings = pluginSettings; + // editor.nodes.defaultSettings = defaultSettings; + // editor.nodes.showSettingsButton = showSettingsButton; + // editor.nodes.showTrashButton = showTrashButton; + // + // return blockButtons; + // + // }; + // + // /** Draw notifications holder */ + // var makeNotificationHolder_ = function () { + // + // /** Append block with notifications to the document */ + // editor.nodes.notifications = editor.notifications.createHolder(); + // + // }; + // + // /** + // * @private + // * Append tools passed in editor.tools + // */ + // var addTools_ = function () { + // + // var tool, + // toolName, + // toolButton; + // + // for ( toolName in editor.settings.tools ) { + // + // tool = editor.settings.tools[toolName]; + // + // editor.tools[toolName] = tool; + // + // if (!tool.iconClassname && tool.displayInToolbox) { + // + // editor.core.log('Toolbar icon classname missed. Tool %o skipped', 'warn', toolName); + // continue; + // + // } + // + // if (typeof tool.render != 'function') { + // + // editor.core.log('render method missed. Tool %o skipped', 'warn', toolName); + // continue; + // + // } + // + // if (!tool.displayInToolbox) { + // + // continue; + // + // } else { + // + // /** if tools is for toolbox */ + // toolButton = editor.draw.toolbarButton(toolName, tool.iconClassname); + // + // editor.nodes.toolbox.appendChild(toolButton); + // + // editor.nodes.toolbarButtons[toolName] = toolButton; + // + // } + // + // } + // + // }; + // + // var addInlineToolbarTools_ = function () { + // + // var tools = { + // + // bold: { + // icon : 'ce-icon-bold', + // command : 'bold' + // }, + // + // italic: { + // icon : 'ce-icon-italic', + // command : 'italic' + // }, + // + // link: { + // icon : 'ce-icon-link', + // command : 'createLink' + // } + // }; + // + // var toolButton, + // tool; + // + // for(var name in tools) { + // + // tool = tools[name]; + // + // toolButton = editor.draw.toolbarButtonInline(name, tool.icon); + // + // editor.nodes.inlineToolbar.buttons.appendChild(toolButton); // /** - // * 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 + // * Add callbacks to this buttons // */ - // plugins.reduce(function (previousValue, plugin, iteration) { + // editor.ui.setInlineToolbarButtonBehaviour(toolButton, tool.command); // - // return previousValue.then(function () { + // } // - // /** - // * Wait till plugins prepared - // * @calls pluginIsReady__ when plugin is ready or failed - // */ - // return new Promise ( function (pluginIsReady__) { + // }; // - // callPluginsPrepareMethod_( plugin ) + // /** + // * @private + // * Bind editor UI events + // */ + // var bindEvents_ = function () { // - // .then( pluginIsReady__ ) - // .then( function () { + // editor.core.log('ui.bindEvents fired', 'info'); // - // plugin.available = true; + // // window.addEventListener('error', function (errorMsg, url, lineNumber) { + // // editor.notifications.errorThrown(errorMsg, event); + // // }, false ); // - // }) + // /** All keydowns on Document */ + // editor.listeners.add(document, 'keydown', editor.callback.globalKeydown, false); // - // .catch(function (error) { + // /** All keydowns on Redactor zone */ + // editor.listeners.add(editor.nodes.redactor, 'keydown', editor.callback.redactorKeyDown, false); // - // editor.core.log(`Plugin «${plugin.type}» was not loaded. Preparation failed because %o`, 'warn', error); - // plugin.available = false; - // plugin.loadingMessage = error; + // /** All keydowns on Document */ + // editor.listeners.add(document, 'keyup', editor.callback.globalKeyup, false ); // - // /** Go ahead even some plugin has problems */ - // pluginIsReady__(); + // /** + // * Mouse click to radactor + // */ + // editor.listeners.add(editor.nodes.redactor, 'click', editor.callback.redactorClicked, false ); // - // }) + // /** + // * Clicks to the Plus button + // */ + // editor.listeners.add(editor.nodes.plusButton, 'click', editor.callback.plusButtonClicked, false); // - // .then(function () { + // /** + // * Clicks to SETTINGS button in toolbar + // */ + // editor.listeners.add(editor.nodes.showSettingsButton, 'click', editor.callback.showSettingsButtonClicked, false ); // - // /** If last plugin has problems then just ignore and continue */ - // if (iteration == plugins.length - 1) { + // /** Bind click listeners on toolbar buttons */ + // for (var button in editor.nodes.toolbarButtons) { // - // allPluginsProcessed__(); + // editor.listeners.add(editor.nodes.toolbarButtons[button], 'click', editor.callback.toolbarButtonClicked, false); // - // } + // } // - // }); + // }; // - // }); + // ui.addBlockHandlers = function (block) { // - // }); + // if (!block) return; // - // }, Promise.resolve() ); + // /** + // * Block keydowns + // */ + // editor.listeners.add(block, 'keydown', editor.callback.blockKeydown, false); + // + // /** + // * Pasting content from another source + // * We have two type of sanitization + // * First - uses deep-first search algorithm to get sub nodes, + // * sanitizes whole Block_content and replaces cleared nodes + // * This method is deprecated + // * Method is used in editor.callback.blockPaste(event) + // * + // * Secont - uses Mutation observer. + // * Observer "observe" DOM changes and send changings to callback. + // * Callback gets changed node, not whole Block_content. + // * Inserted or changed node, which we've gotten have been cleared and replaced with diry node + // * + // * Method is used in editor.callback.blockPasteViaSanitize(event) + // * + // * @uses html-janitor + // * @example editor.callback.blockPasteViaSanitize(event), the second method. + // * + // */ + // editor.listeners.add(block, 'paste', editor.paste.blockPasteCallback, false); + // + // /** + // * Show inline toolbar for selected text + // */ + // editor.listeners.add(block, 'mouseup', editor.toolbar.inline.show, false); + // editor.listeners.add(block, 'keyup', editor.toolbar.inline.show, false); + // + // }; + // + // /** getting all contenteditable elements */ + // ui.saveInputs = function () { + // + // var redactor = editor.nodes.redactor; + // + // editor.state.inputs = []; + // + // /** Save all inputs in global variable state */ + // var inputs = redactor.querySelectorAll('[contenteditable], input, textarea'); + // + // Array.prototype.map.call(inputs, function (current) { + // + // if (!current.type || current.type == 'text' || current.type == 'textarea') { + // + // editor.state.inputs.push(current); + // + // } // // }); // - // } + // }; // - // var callPluginsPrepareMethod_ = function (plugin) { + // /** + // * Adds first initial block on empty redactor + // */ + // ui.addInitialBlock = function () { // - // return plugin.prepare( plugin.config || {} ); + // var initialBlockType = editor.settings.initialBlockPlugin, + // initialBlock; + // + // if ( !editor.tools[initialBlockType] ) { + // + // editor.core.log('Plugin %o was not implemented and can\'t be used as initial block', 'warn', initialBlockType); + // return; + // + // } + // + // initialBlock = editor.tools[initialBlockType].render(); + // + // initialBlock.setAttribute('data-placeholder', editor.settings.placeholder); + // + // editor.content.insertBlock({ + // type : initialBlockType, + // block : initialBlock + // }); + // + // editor.content.workingNodeChanged(initialBlock); // // }; // - // return { - // prepare: prepare + // ui.setInlineToolbarButtonBehaviour = function (button, type) { + // + // editor.listeners.add(button, 'mousedown', function (event) { + // + // editor.toolbar.inline.toolClicked(event, type); + // + // }, false); + // // }; // - // }()); + // return ui; + // + // })({}); /***/ }) /******/ ]); diff --git a/codex-editor.js.map b/codex-editor.js.map index 74c63191..2e18edd0 100644 --- a/codex-editor.js.map +++ b/codex-editor.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///webpack/bootstrap fcccbb43242d9418e0a9","webpack:///./codex.js","webpack:///./src/modules/core.js","webpack:///./src/modules/tools.js"],"names":["module","exports","config","_configuration","holderId","placeholder","sanitizer","hideToolbar","configuration","moduleInstances","eventsDispatcher","Events","init","Core","require","Tools","moduleList","moduleName","modules","moduleExtends","push","state","nodes","Promise","resolve","then","prepare","bind","subscribers","eventName","callback","data","reduce","previousData","currentHandler","newData","Editor","console","log","self","reject","msg","type","args","window","e"],"mappings":"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AP,CAAgBK,IAAhB,EAAwBD,GAAxB,EAA6BE,IAA7B,EAAZ,KACKC,OAAOP,OAAP,CAAgBK,IAAhB,EAAwBD,GAAxB;AAER;AAEJ,cATD,CASE,OAAMI,CAAN,EAAS;AACP;AACH;AAEJ;AA7EL;;AAAA;AAAA;AAgFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,W;;;;;;;;;;;;ACnbA7C,QAAOC,OAAP;AAEI,sBAAc;AAAA;AAEb;;AAJL;AAAA;AAAA,mCAMc,CAET;AARL;;AAAA;AAAA;AAWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,S","file":"codex-editor.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap fcccbb43242d9418e0a9","/**\n * Codex Editor\n *\n *\n *\n *\n * @author CodeX Team\n */\nmodule.exports = class CodexEditor {\n\n /** Editor version */\n static get version() {\n\n return VERSION;\n\n }\n\n /**\n * Setting for configuration\n * @param config\n */\n set configuration(config = {}) {\n\n this._configuration.holderId = config.holderId;\n this._configuration.placeholder = config.placeholder || 'write your story...';\n this._configuration.sanitizer = config.sanitizer || {\n\n };\n\n this._configuration.hideToolbar = config.hideToolbar ? config.hideToolbar : false;\n\n }\n\n /**\n * Returns private property\n * @returns {{}|*}\n */\n get configuration() {\n\n return this._configuration;\n\n }\n\n /**\n * @param config\n *\n * @property this.configuration - editor instance configuration\n * @property this.moduleInstances - editor module instances\n */\n constructor(config) {\n\n 'use strict';\n\n /** Privates */\n this._configuration = {};\n\n this.configuration = config;\n this.moduleInstances = [];\n\n this.eventsDispatcher = new Events();\n\n this.init();\n\n }\n\n /**\n * Initializes modules:\n * First: requiring modules from path\n * Second: memorizing the instances\n */\n init() {\n\n let Core = require('./src/modules/core'),\n Tools = require('./src/modules/tools');\n // transport = require('./src/modules/transport'),\n // renderer = require('./src/modules/renderer'),\n // saver = require('./src/modules/saver'),\n // content = require('./src/modules/content'),\n // toolbar = require('./src/modules/toolbar/toolbar'),\n // callbacks = require('./src/modules/callbacks'),\n // draw = require('./src/modules/draw'),\n // caret = require('./src/modules/caret'),\n // notifications = require('./src/modules/notifications'),\n // parser = require('./src/modules/parser'),\n // sanitizer = require('./src/modules/sanitizer'),\n // listeners = require('./src/modules/listeners'),\n // destroyer = require('./src/modules/destroyer'),\n // paste = require('./src/modules/paste');\n\n let moduleList = {\n 'core' : Core,\n 'tools' : Tools\n };\n\n for(let moduleName in moduleList) {\n\n let modules = [];\n\n for(let moduleExtends in moduleList) {\n\n if (moduleExtends === moduleName) {\n\n continue;\n\n }\n modules.push(moduleList[moduleExtends]);\n\n }\n\n this.moduleInstances[moduleName] = new moduleList[moduleName]({\n modules : modules,\n config : this.configuration,\n state : this.state,\n nodes : this.nodes\n });\n\n }\n\n // this.moduleInstances['core'].prepare();\n Promise.resolve()\n .then(this.moduleInstances['core'].prepare.bind(this.moduleInstances['core']));\n // .then(this.moduleInstances['ui'].prepare)\n // .then(this.moduleInstances['tools'.prepare])\n // .catch(function (error) {\n //\n // console.log('Error occured', error);\n //\n // });\n\n }\n\n};\n\nclass Events {\n\n constructor() {\n\n this.subscribers = {};\n\n }\n\n on(eventName, callback) {\n\n if (!(eventName in this.subscribers)) {\n\n this.subscribers[eventName] = [];\n\n }\n\n // group by events\n this.subscribers[eventName].push(callback);\n\n }\n\n emit(eventName, data) {\n\n this.subscribers[eventName].reduce(function (previousData, currentHandler) {\n\n let newData = currentHandler(previousData);\n\n return newData ? newData : previousData;\n\n }, data);\n\n }\n\n}\n// module.exports = (function (editor) {\n//\n// 'use strict';\n//\n// editor.version = VERSION;\n// editor.scriptPrefix = 'cdx-script-';\n//\n// var init = function () {\n//\n// editor.core = require('./modules/core');\n// editor.tools = require('./modules/tools');\n// editor.ui = require('./modules/ui');\n// editor.transport = require('./modules/transport');\n// editor.renderer = require('./modules/renderer');\n// editor.saver = require('./modules/saver');\n// editor.content = require('./modules/content');\n// editor.toolbar = require('./modules/toolbar/toolbar');\n// editor.callback = require('./modules/callbacks');\n// editor.draw = require('./modules/draw');\n// editor.caret = require('./modules/caret');\n// editor.notifications = require('./modules/notifications');\n// editor.parser = require('./modules/parser');\n// editor.sanitizer = require('./modules/sanitizer');\n// editor.listeners = require('./modules/listeners');\n// editor.destroyer = require('./modules/destroyer');\n// editor.paste = require('./modules/paste');\n//\n// };\n//\n// /**\n// * @public\n// * holds initial settings\n// */\n// editor.settings = {\n// tools : ['paragraph', 'header', 'picture', 'list', 'quote', 'code', 'twitter', 'instagram', 'smile'],\n// holderId : 'codex-editor',\n//\n// // Type of block showing on empty editor\n// initialBlockPlugin: 'paragraph'\n// };\n//\n// /**\n// * public\n// *\n// * Static nodes\n// */\n// editor.nodes = {\n// holder : null,\n// wrapper : null,\n// toolbar : null,\n// inlineToolbar : {\n// wrapper : null,\n// buttons : null,\n// actions : null\n// },\n// toolbox : null,\n// notifications : null,\n// plusButton : null,\n// showSettingsButton: null,\n// showTrashButton : null,\n// blockSettings : null,\n// pluginSettings : null,\n// defaultSettings : null,\n// toolbarButtons : {}, // { type : DomEl, ... }\n// redactor : null\n// };\n//\n// /**\n// * @public\n// *\n// * Output state\n// */\n// editor.state = {\n// jsonOutput : [],\n// blocks : [],\n// inputs : []\n// };\n//\n// /**\n// * @public\n// * Editor plugins\n// */\n// editor.tools = {};\n//\n// /**\n// * Initialization\n// * @uses Promise cEditor.core.prepare\n// * @param {Object} userSettings\n// * @param {Array} userSettings.tools list of plugins\n// * @param {String} userSettings.holderId Element's id to append editor\n// *\n// * Load user defined tools\n// * Tools must contain this important objects :\n// * @param {String} type - this is a type of plugin. It can be used as plugin name\n// * @param {String} iconClassname - this a icon in toolbar\n// * @param {Object} make - what should plugin do, when it is clicked\n// * @param {Object} appendCallback - callback after clicking\n// * @param {Element} settings - what settings does it have\n// * @param {Object} render - plugin get JSON, and should return HTML\n// * @param {Object} save - plugin gets HTML content, returns JSON\n// * @param {Boolean} displayInToolbox - will be displayed in toolbox. Default value is TRUE\n// * @param {Boolean} enableLineBreaks - inserts new block or break lines. Default value is FALSE\n// *\n// * @example\n// * - type : 'header',\n// * - iconClassname : 'ce-icon-header',\n// * - make : headerTool.make,\n// * - appendCallback : headerTool.appendCallback,\n// * - settings : headerTool.makeSettings(),\n// * - render : headerTool.render,\n// * - save : headerTool.save,\n// * - displayInToolbox : true,\n// * - enableLineBreaks : false\n// */\n// editor.start = function (userSettings) {\n//\n// init();\n//\n// editor.core.prepare(userSettings)\n//\n// // If all ok, make UI, bind events and parse initial-content\n// .then(editor.ui.prepare)\n// .then(editor.tools.prepare)\n// .then(editor.sanitizer.prepare)\n// .then(editor.paste.prepare)\n// .then(editor.transport.prepare)\n// .then(editor.renderer.makeBlocksFromData)\n// .then(editor.ui.saveInputs)\n// .catch(function (error) {\n//\n// editor.core.log('Initialization failed with error: %o', 'warn', error);\n//\n// });\n//\n// };\n//\n// return editor;\n//\n// })({});\n\n\n\n// WEBPACK FOOTER //\n// ./codex.js","/**\n * Codex Editor Core\n *\n * @author Codex Team\n * @version 1.1.3\n */\nmodule.exports = class Core {\n\n /** Editor script prefixes */\n static get scriptPrefix() {\n\n return 'cdx-script-';\n\n }\n\n constructor(Editor) {\n\n this.Editor = Editor;\n\n this.sanitizer = null;\n this.state = {};\n\n }\n\n prepare() {\n\n console.log(this);\n let self = this;\n\n return new Promise(function (resolve, reject) {\n\n console.log(self);\n // if (typeof editor.nodes.holder === undefined || editor.nodes.holder === null) {\n //\n // reject(Error(\"Holder wasn't found by ID: #\" + userSettings.holderId));\n //\n // } else {\n //\n // resolve();\n //\n // }\n //\n // resolve();\n\n });\n\n }\n\n /**\n * Core custom logger\n *\n * @param msg\n * @param type\n * @param args\n */\n log(msg, type, args) {\n\n type = type || 'log';\n\n if (!args) {\n\n args = msg || 'undefined';\n msg = '[codex-editor]: %o';\n\n } else {\n\n msg = '[codex-editor]: ' + msg;\n\n }\n\n try{\n\n if ( 'console' in window && window.console[ type ] ) {\n\n if ( args ) window.console[ type ]( msg, args );\n else window.console[ type ]( msg );\n\n }\n\n } catch(e) {\n // do nothing\n }\n\n }\n\n};\n// module.exports = (function (core) {\n//\n// let editor = codex.editor;\n//\n// /**\n// * @public\n// *\n// * Editor preparing method\n// * @return Promise\n// */\n// core.prepare = function (userSettings) {\n//\n// return new Promise(function (resolve, reject) {\n//\n// if ( userSettings ) {\n//\n// editor.settings.tools = userSettings.tools || editor.settings.tools;\n//\n// }\n//\n// if (userSettings.data) {\n//\n// editor.state.blocks = userSettings.data;\n//\n// }\n//\n// if (userSettings.initialBlockPlugin) {\n//\n// editor.settings.initialBlockPlugin = userSettings.initialBlockPlugin;\n//\n// }\n//\n// if (userSettings.sanitizer) {\n//\n// editor.settings.sanitizer = userSettings.sanitizer;\n//\n// }\n//\n// editor.hideToolbar = userSettings.hideToolbar;\n//\n// editor.settings.placeholder = userSettings.placeholder || '';\n//\n// editor.nodes.holder = document.getElementById(userSettings.holderId || editor.settings.holderId);\n//\n// if (typeof editor.nodes.holder === undefined || editor.nodes.holder === null) {\n//\n// reject(Error(\"Holder wasn't found by ID: #\" + userSettings.holderId));\n//\n// } else {\n//\n// resolve();\n//\n// }\n//\n// });\n//\n// };\n//\n// /**\n// * @protected\n// *\n// * Helper for insert one element after another\n// */\n// core.insertAfter = function (target, element) {\n//\n// target.parentNode.insertBefore(element, target.nextSibling);\n//\n// };\n//\n// /**\n// * @const\n// *\n// * Readable DOM-node types map\n// */\n// core.nodeTypes = {\n// TAG : 1,\n// TEXT : 3,\n// COMMENT : 8,\n// DOCUMENT_FRAGMENT: 11\n// };\n//\n// /**\n// * @const\n// * Readable keys map\n// */\n// core.keys = { BACKSPACE: 8, TAB: 9, ENTER: 13, SHIFT: 16, CTRL: 17, ALT: 18, ESC: 27, SPACE: 32, LEFT: 37, UP: 38, DOWN: 40, RIGHT: 39, DELETE: 46, META: 91 };\n//\n// /**\n// * @protected\n// *\n// * Check object for DOM node\n// */\n// core.isDomNode = function (el) {\n//\n// return el && typeof el === 'object' && el.nodeType && el.nodeType == this.nodeTypes.TAG;\n//\n// };\n//\n// /**\n// * Checks passed object for emptiness\n// * @require ES5 - Object.keys\n// * @param {object}\n// */\n// core.isEmpty = function ( obj ) {\n//\n// return Object.keys(obj).length === 0;\n//\n// };\n//\n// /**\n// * Native Ajax\n// * @param {String} settings.url - request URL\n// * @param {function} settings.beforeSend - returned value will be passed as context to the Success, Error and Progress callbacks\n// * @param {function} settings.success\n// * @param {function} settings.progress\n// */\n// core.ajax = function (settings) {\n//\n// if (!settings || !settings.url) {\n//\n// return;\n//\n// }\n//\n// var XMLHTTP = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'),\n// encodedString,\n// isFormData,\n// prop;\n//\n//\n// settings.async = true;\n// settings.type = settings.type || 'GET';\n// settings.data = settings.data || '';\n// settings['content-type'] = settings['content-type'] || 'application/json; charset=utf-8';\n//\n// if (settings.type == 'GET' && settings.data) {\n//\n// settings.url = /\\?/.test(settings.url) ? settings.url + '&' + settings.data : settings.url + '?' + settings.data;\n//\n// } else {\n//\n// encodedString = '';\n// for(prop in settings.data) {\n//\n// encodedString += (prop + '=' + encodeURIComponent(settings.data[prop]) + '&');\n//\n// }\n//\n// }\n//\n// if (settings.withCredentials) {\n//\n// XMLHTTP.withCredentials = true;\n//\n// }\n//\n// /**\n// * Value returned in beforeSend funtion will be passed as context to the other response callbacks\n// * If beforeSend returns false, AJAX will be blocked\n// */\n// let responseContext,\n// beforeSendResult;\n//\n// if (typeof settings.beforeSend === 'function') {\n//\n// beforeSendResult = settings.beforeSend.call();\n//\n// if (beforeSendResult === false) {\n//\n// return;\n//\n// }\n//\n// }\n//\n// XMLHTTP.open( settings.type, settings.url, settings.async );\n//\n// /**\n// * If we send FormData, we need no content-type header\n// */\n// isFormData = isFormData_(settings.data);\n//\n// if (!isFormData) {\n//\n// if (settings.type !== 'POST') {\n//\n// XMLHTTP.setRequestHeader('Content-type', settings['content-type']);\n//\n// } else {\n//\n// XMLHTTP.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');\n//\n// }\n//\n// }\n//\n// XMLHTTP.setRequestHeader('X-Requested-With', 'XMLHttpRequest');\n//\n// responseContext = beforeSendResult || XMLHTTP;\n//\n// if (typeof settings.progress === 'function') {\n//\n// XMLHTTP.upload.onprogress = settings.progress.bind(responseContext);\n//\n// }\n//\n// XMLHTTP.onreadystatechange = function () {\n//\n// if (XMLHTTP.readyState === 4) {\n//\n// if (XMLHTTP.status === 200) {\n//\n// if (typeof settings.success === 'function') {\n//\n// settings.success.call(responseContext, XMLHTTP.responseText);\n//\n// }\n//\n// } else {\n//\n// if (typeof settings.error === 'function') {\n//\n// settings.error.call(responseContext, XMLHTTP.responseText, XMLHTTP.status);\n//\n// }\n//\n// }\n//\n// }\n//\n// };\n//\n// if (isFormData) {\n//\n// // Sending FormData\n// XMLHTTP.send(settings.data);\n//\n// } else {\n//\n// // POST requests\n// XMLHTTP.send(encodedString);\n//\n// }\n//\n// return XMLHTTP;\n//\n// };\n//\n// /**\n// * Appends script to head of document\n// * @return Promise\n// */\n// core.importScript = function (scriptPath, instanceName) {\n//\n// return new Promise(function (resolve, reject) {\n//\n// let script;\n//\n// /** Script is already loaded */\n// if ( !instanceName ) {\n//\n// reject('Instance name is missed');\n//\n// } else if ( document.getElementById(editor.scriptPrefix + instanceName) ) {\n//\n// resolve(scriptPath);\n//\n// }\n//\n// script = document.createElement('SCRIPT');\n// script.async = true;\n// script.defer = true;\n// script.id = editor.scriptPrefix + instanceName;\n//\n// script.onload = function () {\n//\n// resolve(scriptPath);\n//\n// };\n//\n// script.onerror = function () {\n//\n// reject(scriptPath);\n//\n// };\n//\n// script.src = scriptPath;\n// document.head.appendChild(script);\n//\n// });\n//\n// };\n//\n// /**\n// * Function for checking is it FormData object to send.\n// * @param {Object} object to check\n// * @return boolean\n// */\n// var isFormData_ = function (object) {\n//\n// return object instanceof FormData;\n//\n// };\n//\n// /**\n// * Check block\n// * @param target\n// * @description Checks target is it native input\n// */\n// core.isNativeInput = function (target) {\n//\n// var nativeInputAreas = ['INPUT', 'TEXTAREA'];\n//\n// return nativeInputAreas.indexOf(target.tagName) != -1;\n//\n// };\n//\n// /**\n// * Check if block is empty\n// * We should check block textContent, child native inputs and some exceptions like IMG and IFRAME\n// *\n// * @param block\n// * @returns {boolean}\n// */\n// core.isBlockEmpty = function (block) {\n//\n// const EXCEPTION_TAGS = ['IMG', 'IFRAME'];\n//\n// var nativeInputs = block.querySelectorAll('textarea, input'),\n// nativeInputsAreEmpty = true,\n// textContentIsEmpty = !block.textContent.trim();\n//\n// Array.prototype.forEach.call(nativeInputs, function (input) {\n//\n// if (input.type == 'textarea' || input.type == 'text') {\n//\n// nativeInputsAreEmpty = nativeInputsAreEmpty && !input.value.trim();\n//\n// }\n//\n// });\n//\n// return textContentIsEmpty && nativeInputsAreEmpty && !EXCEPTION_TAGS.includes(block.tagName);\n//\n// };\n//\n//\n// return core;\n//\n// })({});\n\n\n\n// WEBPACK FOOTER //\n// ./src/modules/core.js","module.exports = class Tools {\n\n constructor() {\n\n }\n\n prepare() {\n\n }\n\n};\n// /**\n// * Module working with plugins\n// */\n// module.exports = (function () {\n//\n// let editor = codex.editor;\n//\n// /**\n// * Initialize plugins before using\n// * Ex. Load scripts or call some internal methods\n// * @return Promise\n// */\n// function prepare() {\n//\n// return new Promise(function (resolve_, reject_) {\n//\n// Promise.resolve()\n//\n// /**\n// * Compose a sequence of plugins that requires preparation\n// */\n// .then(function () {\n//\n// let pluginsRequiresPreparation = [],\n// allPlugins = editor.tools;\n//\n// for ( let pluginName in allPlugins ) {\n//\n// let plugin = allPlugins[pluginName];\n//\n// if (plugin.prepare && typeof plugin.prepare != 'function' || !plugin.prepare) {\n//\n// continue;\n//\n// }\n//\n// pluginsRequiresPreparation.push(plugin);\n//\n// }\n//\n// /**\n// * If no one passed plugins requires preparation, finish prepare() and go ahead\n// */\n// if (!pluginsRequiresPreparation.length) {\n//\n// resolve_();\n//\n// }\n//\n// return pluginsRequiresPreparation;\n//\n// })\n//\n// /** Wait plugins while they prepares */\n// .then(waitAllPluginsPreparation_)\n//\n// .then(function () {\n//\n// editor.core.log('Plugins loaded', 'info');\n// resolve_();\n//\n// }).catch(function (error) {\n//\n// reject_(error);\n//\n// });\n//\n// });\n//\n// }\n//\n// /**\n// * @param {array} plugins - list of tools that requires preparation\n// * @return {Promise} resolved while all plugins will be ready or failed\n// */\n// function waitAllPluginsPreparation_(plugins) {\n//\n// /**\n// * @calls allPluginsProcessed__ when all plugins prepared or failed\n// */\n// return new Promise (function (allPluginsProcessed__) {\n//\n// /**\n// * pluck each element from queue\n// * First, send resolved Promise as previous value\n// * Each plugins \"prepare\" method returns a Promise, that's why\n// * reduce current element will not be able to continue while can't get\n// * a resolved Promise\n// *\n// * If last plugin is \"prepared\" then go to the next stage of initialization\n// */\n// plugins.reduce(function (previousValue, plugin, iteration) {\n//\n// return previousValue.then(function () {\n//\n// /**\n// * Wait till plugins prepared\n// * @calls pluginIsReady__ when plugin is ready or failed\n// */\n// return new Promise ( function (pluginIsReady__) {\n//\n// callPluginsPrepareMethod_( plugin )\n//\n// .then( pluginIsReady__ )\n// .then( function () {\n//\n// plugin.available = true;\n//\n// })\n//\n// .catch(function (error) {\n//\n// editor.core.log(`Plugin «${plugin.type}» was not loaded. Preparation failed because %o`, 'warn', error);\n// plugin.available = false;\n// plugin.loadingMessage = error;\n//\n// /** Go ahead even some plugin has problems */\n// pluginIsReady__();\n//\n// })\n//\n// .then(function () {\n//\n// /** If last plugin has problems then just ignore and continue */\n// if (iteration == plugins.length - 1) {\n//\n// allPluginsProcessed__();\n//\n// }\n//\n// });\n//\n// });\n//\n// });\n//\n// }, Promise.resolve() );\n//\n// });\n//\n// }\n//\n// var callPluginsPrepareMethod_ = function (plugin) {\n//\n// return plugin.prepare( plugin.config || {} );\n//\n// };\n//\n// return {\n// prepare: prepare\n// };\n//\n// }());\n\n\n// WEBPACK FOOTER //\n// ./src/modules/tools.js"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/bootstrap 040944ccfc51cf018e75","webpack:///./codex.js","webpack:///./src/modules/dom.js","webpack:///./src/modules/core.js","webpack:///./src/modules/ui.js"],"names":["module","exports","config","_configuration","holderId","placeholder","sanitizer","p","b","a","hideToolbar","configuration","moduleInstances","eventsDispatcher","Events","Promise","resolve","then","init","prepare","Dom","require","Core","Ui","moduleList","moduleName","modules","moduleExtends","state","nodes","prepareDecorator","subscribers","eventName","callback","push","data","reduce","previousData","currentHandler","newData","el","classList","properties","element","document","createElement","forEach","className","add","property","selector","querySelector","querySelectorAll","Editor","self","reject","undefined","Error","userSettings","msg","type","args","window","console","e","settings","url","XMLHTTP","XMLHttpRequest","ActiveXObject","encodedString","isFormData","prop","async","test","encodeURIComponent","withCredentials","responseContext","beforeSendResult","beforeSend","call","open","isFormData_","setRequestHeader","progress","upload","onprogress","bind","onreadystatechange","readyState","status","success","responseText","error","send","BLOCK_CLASSNAME","BLOCK_CONTENT","BLOCK_STRETCHED","BLOCK_HIGHLIGHTED","SETTINGS_ITEM","CSS_","editorWrapper","editorZone","wrapper","dom","make","redactor","toolbar","makeToolBar_","appendChild","editor","holder","addTools_","makeInlineToolbar_","addInlineToolbarTools_","makeNotificationHolder_","bindEvents_","catch","core","log"],"mappings":"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AAIC,UAAUD,eAAeD,YAAf,CAAd;;AAEA,wBAAOE,UAAUA,OAAV,GAAoBF,YAA3B;AAEH,cAND,EAMGF,IANH;AAQH;;;;;AAGL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,W;;;;;;;;;;;;ACrUAnC,QAAOC,OAAP;AAAA;AAAA;AAAA;;AAAA;AAAA;;;AAEI;;;;;;;;;AAFJ,8BAWSuC,EAXT,EAWaC,SAXb,EAWwBC,UAXxB,EAWoC;;AAE5B,iBAAIC,UAAUC,SAASC,aAAT,CAAuBL,EAAvB,CAAd;;AAEAC,uBAAUK,OAAV,CAAkB,UAAUC,SAAV,EAAqB;;AAEnCJ,yBAAQF,SAAR,CAAkBO,GAAlB,CAAsBD,SAAtB;AAEH,cAJD;;AAMA,kBAAIE,QAAJ,IAAgBP,UAAhB,EAA4B;;AAExBC,yBAAQM,QAAR,GAAmBP,WAAWO,QAAX,CAAnB;AAEH;;AAED,oBAAON,OAAP;AAEH;;AAED;;;;;;;;;;;AA/BJ;AAAA;AAAA,gCAyCkC;AAAA,iBAAzBH,EAAyB,uEAApBI,QAAoB;AAAA,iBAAVM,QAAU;;;AAE1B,oBAAOV,GAAGW,aAAH,CAAiBD,QAAjB,CAAP;AAEH;;AAED;;;;;;;;;;AA/CJ;AAAA;AAAA,mCAwDqC;AAAA,iBAAzBV,EAAyB,uEAApBI,QAAoB;AAAA,iBAAVM,QAAU;;;AAE7B,oBAAOV,GAAGY,gBAAH,CAAoBF,QAApB,CAAP;AAEH;AA5DL;;AAAA;AAAA,K;;;;;;;;;;;;;;ACAA;;;;;;AAMAlD,QAAOC,OAAP;AAAA;AAAA;;;AAEI;AAFJ,6BAG8B;;AAEtB,oBAAO,aAAP;AAEH;AAPL;;AASI,mBAAYoD,MAAZ,EAAoB;AAAA;;AAEhB,cAAKA,MAAL,GAAcA,MAAd;;AAEA,cAAK/C,SAAL,GAAiB,IAAjB;AACA,cAAKsB,KAAL,GAAa,EAAb;AAEH;;AAED;;;;;;;;AAlBJ;AAAA;AAAA,mCAwBc;;AAEN,iBAAI0B,OAAO,IAAX;;AAEA,oBAAO,IAAIvC,OAAJ,CAAY,UAAUC,OAAV,EAAmBuC,MAAnB,EAA2B;;AAE1C,qBAAI,QAAOD,KAAKD,MAAL,CAAYnD,MAAZ,CAAmBE,QAA1B,MAAuCoD,SAA3C,EAAuD;;AAEnDD,4BAAOE,MAAM,iCAAiCC,aAAatD,QAApD,CAAP;AAEH,kBAJD,MAIO;;AAEHY;AAEH;;AAEDA;AAEH,cAdM,CAAP;AAgBH;;AAED;;;;;;;;AA9CJ;AAAA;AAAA,6BAqDQ2C,GArDR,EAqDaC,IArDb,EAqDmBC,IArDnB,EAqDyB;;AAEjBD,oBAAOA,QAAQ,KAAf;;AAEA,iBAAI,CAACC,IAAL,EAAW;;AAEPA,wBAAQF,OAAO,WAAf;AACAA,uBAAO,yBAAP;AAEH,cALD,MAKO;;AAEHA,uBAAO,0BAA0BA,GAAjC;AAEH;;AAED,iBAAG;;AAEC,qBAAK,aAAaG,MAAb,IAAuBA,OAAOC,OAAP,CAAgBH,IAAhB,CAA5B,EAAqD;;AAEjD,yBAAKC,IAAL,EAAYC,OAAOC,OAAP,CAAgBH,IAAhB,EAAwBD,GAAxB,EAA6BE,IAA7B,EAAZ,KACKC,OAAOC,OAAP,CAAgBH,IAAhB,EAAwBD,GAAxB;AAER;AAEJ,cATD,CASE,OAAMK,CAAN,EAAS;AACP;AACH;AAEJ;;AAED;;;;;;;;AAnFJ;AAAA;AAAA,8BA0FSC,QA1FT,EA0FmB;;AAEX,iBAAI,CAACA,QAAD,IAAa,CAACA,SAASC,GAA3B,EAAgC;;AAE5B;AAEH;;AAED,iBAAIC,UAAUL,OAAOM,cAAP,GAAwB,IAAIA,cAAJ,EAAxB,GAA+C,IAAIC,aAAJ,CAAkB,mBAAlB,CAA7D;AAAA,iBACIC,aADJ;AAAA,iBAEIC,UAFJ;AAAA,iBAGIC,IAHJ;;AAMAP,sBAASQ,KAAT,GAA2B,IAA3B;AACAR,sBAASL,IAAT,GAA2BK,SAASL,IAAT,IAAiB,KAA5C;AACAK,sBAAS9B,IAAT,GAA2B8B,SAAS9B,IAAT,IAAiB,EAA5C;AACA8B,sBAAS,cAAT,IAA2BA,SAAS,cAAT,KAA4B,iCAAvD;;AAEA,iBAAIA,SAASL,IAAT,IAAiB,KAAjB,IAA0BK,SAAS9B,IAAvC,EAA6C;;AAEzC8B,0BAASC,GAAT,GAAe,KAAKQ,IAAL,CAAUT,SAASC,GAAnB,IAA0BD,SAASC,GAAT,GAAe,GAAf,GAAqBD,SAAS9B,IAAxD,GAA+D8B,SAASC,GAAT,GAAe,GAAf,GAAqBD,SAAS9B,IAA5G;AAEH,cAJD,MAIO;;AAEHmC,iCAAgB,EAAhB;AACA,sBAAIE,IAAJ,IAAYP,SAAS9B,IAArB,EAA2B;;AAEvBmC,sCAAkBE,OAAO,GAAP,GAAaG,mBAAmBV,SAAS9B,IAAT,CAAcqC,IAAd,CAAnB,CAAb,GAAuD,GAAzE;AAEH;AAEJ;;AAED,iBAAIP,SAASW,eAAb,EAA8B;;AAE1BT,yBAAQS,eAAR,GAA0B,IAA1B;AAEH;;AAED;;;;AAIA,iBAAIC,wBAAJ;AAAA,iBACIC,yBADJ;;AAGA,iBAAI,OAAOb,SAASc,UAAhB,KAA+B,UAAnC,EAA+C;;AAE3CD,oCAAmBb,SAASc,UAAT,CAAoBC,IAApB,EAAnB;;AAEA,qBAAIF,qBAAqB,KAAzB,EAAgC;;AAE5B;AAEH;AAEJ;;AAEDX,qBAAQc,IAAR,CAAchB,SAASL,IAAvB,EAA6BK,SAASC,GAAtC,EAA2CD,SAASQ,KAApD;;AAEA;;;AAGAF,0BAAaW,YAAYjB,SAAS9B,IAArB,CAAb;;AAEA,iBAAI,CAACoC,UAAL,EAAiB;;AAEb,qBAAIN,SAASL,IAAT,KAAkB,MAAtB,EAA8B;;AAE1BO,6BAAQgB,gBAAR,CAAyB,cAAzB,EAAyClB,SAAS,cAAT,CAAzC;AAEH,kBAJD,MAIO;;AAEHE,6BAAQgB,gBAAR,CAAyB,cAAzB,EAAyC,mCAAzC;AAEH;AAEJ;;AAEDhB,qBAAQgB,gBAAR,CAAyB,kBAAzB,EAA6C,gBAA7C;;AAEAN,+BAAkBC,oBAAoBX,OAAtC;;AAEA,iBAAI,OAAOF,SAASmB,QAAhB,KAA6B,UAAjC,EAA6C;;AAEzCjB,yBAAQkB,MAAR,CAAeC,UAAf,GAA4BrB,SAASmB,QAAT,CAAkBG,IAAlB,CAAuBV,eAAvB,CAA5B;AAEH;;AAEDV,qBAAQqB,kBAAR,GAA6B,YAAY;;AAErC,qBAAIrB,QAAQsB,UAAR,KAAuB,CAA3B,EAA8B;;AAE1B,yBAAItB,QAAQuB,MAAR,KAAmB,GAAvB,EAA4B;;AAExB,6BAAI,OAAOzB,SAAS0B,OAAhB,KAA4B,UAAhC,EAA4C;;AAExC1B,sCAAS0B,OAAT,CAAiBX,IAAjB,CAAsBH,eAAtB,EAAuCV,QAAQyB,YAA/C;AAEH;AAEJ,sBARD,MAQO;;AAEH,6BAAI,OAAO3B,SAAS4B,KAAhB,KAA0B,UAA9B,EAA0C;;AAEtC5B,sCAAS4B,KAAT,CAAeb,IAAf,CAAoBH,eAApB,EAAqCV,QAAQyB,YAA7C,EAA2DzB,QAAQuB,MAAnE;AAEH;AAEJ;AAEJ;AAEJ,cAxBD;;AA0BA,iBAAInB,UAAJ,EAAgB;;AAEZ;AACAJ,yBAAQ2B,IAAR,CAAa7B,SAAS9B,IAAtB;AAEH,cALD,MAKO;;AAEH;AACAgC,yBAAQ2B,IAAR,CAAaxB,aAAb;AAEH;;AAED,oBAAOH,OAAP;AAEH;AA5NL;;AAAA;AAAA;AA+NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,W;;;;;;;;;;;;AClYA;;;;;AAKA,KAAIpB,YAAY;;AAEZ;;;AAGAgD,sBAAkB,UALN;;AAOZ;;;AAGAC,oBAAgB,mBAVJ;;AAYZ;;;AAGAC,sBAAkB,qBAfN;;AAiBZ;;;AAGAC,wBAAoB,mBApBR;;AAsBZ;;;AAGAC,oBAAgB;AAzBJ,EAAhB;;AA4BA,KAAIC,OAAO;AACPC,oBAAgB,cADT;AAEPC,iBAAgB;AAFT,EAAX;;AAKAtG,QAAOC,OAAP;AAEI,iBAAYoD,MAAZ,EAAoB;AAAA;;AAEhB,cAAKA,MAAL,GAAcA,MAAd;;AAEA,cAAK3B,OAAL,GAAe,KAAK2B,MAAL,CAAY3B,OAA3B;AAEH;;AAED;;;;;;;AAVJ;AAAA;AAAA,mCAec;;AAEN,oBAAO,IAAIX,OAAJ,CAAY,UAAUC,OAAV,EAAmBuC,MAAnB,EAA2B;;AAE1C,qBAAIgD,UAAW,KAAK7E,OAAL,CAAa8E,GAAb,CAAiBC,IAAjB,CAAsB,KAAtB,EAA6B,CAAEL,KAAKC,aAAP,CAA7B,EAAqD,EAArD,CAAf;AAAA,qBACIK,WAAW,KAAKhF,OAAL,CAAa8E,GAAb,CAAiBC,IAAjB,CAAsB,KAAtB,EAA6B,CAAEL,KAAKE,UAAP,CAA7B,EAAkD,EAAlD,CADf;AAAA,qBAEIK,UAAWC,cAFf;;AAIAL,yBAAQM,WAAR,CAAoBF,OAApB;AACAJ,yBAAQM,WAAR,CAAoBH,QAApB;;AAEA;AACAI,wBAAOjF,KAAP,CAAa0E,OAAb,GAAwBA,OAAxB;AACAO,wBAAOjF,KAAP,CAAa6E,QAAb,GAAwBA,QAAxB;;AAEA;AACAI,wBAAOjF,KAAP,CAAakF,MAAb,CAAoBF,WAApB,CAAgCN,OAAhC;;AAEAvF;AAEH,cAlBM;;AAoBP;AApBO,cAqBNC,IArBM,CAqBD+F,SArBC;;AAuBP;AAvBO,cAwBN/F,IAxBM,CAwBDgG,kBAxBC;;AA0BP;AA1BO,cA2BNhG,IA3BM,CA2BDiG,sBA3BC;;AA6BP;AA7BO,cA8BNjG,IA9BM,CA8BDkG,uBA9BC;;AAgCP;AAhCO,cAiCNlG,IAjCM,CAiCDmG,WAjCC,EAmCNC,KAnCM,CAmCC,YAAY;;AAEhBP,wBAAOQ,IAAP,CAAYC,GAAZ,CAAgB,6BAAhB;AAEH,cAvCM,CAAP;AAyCH;AA1DL;;AAAA;AAAA;AA6DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,W","file":"codex-editor.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 040944ccfc51cf018e75","/**\n * Codex Editor\n *\n *\n *\n *\n * @author CodeX Team\n */\nmodule.exports = class CodexEditor {\n\n /** Editor version */\n static get version() {\n\n return VERSION;\n\n }\n\n /**\n * Setting for configuration\n * @param config\n */\n set configuration(config = {}) {\n\n this._configuration.holderId = config.holderId;\n this._configuration.placeholder = config.placeholder || 'write your story...';\n this._configuration.sanitizer = config.sanitizer || {\n p: true,\n b: true,\n a: true\n };\n\n this._configuration.hideToolbar = config.hideToolbar ? config.hideToolbar : false;\n\n }\n\n /**\n * Returns private property\n * @returns {{}|*}\n */\n get configuration() {\n\n return this._configuration;\n\n }\n\n /**\n * @param config\n *\n * @property this.configuration - editor instance configuration\n * @property this.moduleInstances - editor module instances\n */\n constructor(config) {\n\n 'use strict';\n\n /** Privates */\n this._configuration = {};\n\n this.configuration = config;\n this.moduleInstances = [];\n\n this.eventsDispatcher = new Events();\n\n return Promise.resolve()\n .then(() => this.init())\n .then(() => this.prepare());\n\n }\n\n /**\n * Initializes modules:\n * First: requiring modules from path\n * Second: memorizing the instances\n */\n init() {\n\n let Dom = require('./src/modules/dom'),\n Core = require('./src/modules/core'),\n Ui = require('./src/modules/ui');\n // transport = require('./src/modules/transport'),\n // renderer = require('./src/modules/renderer'),\n // saver = require('./src/modules/saver'),\n // content = require('./src/modules/content'),\n // toolbar = require('./src/modules/toolbar/toolbar'),\n // callbacks = require('./src/modules/callbacks'),\n // draw = require('./src/modules/draw'),\n // caret = require('./src/modules/caret'),\n // notifications = require('./src/modules/notifications'),\n // parser = require('./src/modules/parser'),\n // sanitizer = require('./src/modules/sanitizer'),\n // listeners = require('./src/modules/listeners'),\n // destroyer = require('./src/modules/destroyer'),\n // paste = require('./src/modules/paste');\n\n let moduleList = {\n 'dom' : Dom,\n 'core' : Core,\n 'ui' : Ui\n };\n\n for(let moduleName in moduleList) {\n\n let modules = {};\n\n for(let moduleExtends in moduleList) {\n\n if (moduleExtends === moduleName) {\n\n continue;\n\n }\n modules[moduleExtends] = moduleList[moduleExtends];\n\n }\n\n this.moduleInstances[moduleName] = new moduleList[moduleName]({\n modules : modules,\n config : this.configuration,\n state : this.state,\n nodes : this.nodes\n });\n\n }\n\n }\n\n /**\n * @param module - module instance\n * @returns {*}\n */\n prepare(module) {\n\n function prepareDecorator(module) {\n\n return module.prepare();\n\n }\n\n return Promise.resolve()\n .then(prepareDecorator(this.moduleInstances['core']))\n .then(prepareDecorator(this.moduleInstances['ui']));\n // .then(this.moduleInstances['tools'.prepare])\n // .catch(function (error) {\n //\n // console.log('Error occured', error);\n //\n // });\n\n\n }\n\n};\n\nclass Events {\n\n constructor() {\n\n this.subscribers = {};\n\n }\n\n on(eventName, callback) {\n\n if (!(eventName in this.subscribers)) {\n\n this.subscribers[eventName] = [];\n\n }\n\n // group by events\n this.subscribers[eventName].push(callback);\n\n }\n\n emit(eventName, data) {\n\n this.subscribers[eventName].reduce(function (previousData, currentHandler) {\n\n let newData = currentHandler(previousData);\n\n return newData ? newData : previousData;\n\n }, data);\n\n }\n\n}\n// module.exports = (function (editor) {\n//\n// 'use strict';\n//\n// editor.version = VERSION;\n// editor.scriptPrefix = 'cdx-script-';\n//\n// var init = function () {\n//\n// editor.core = require('./modules/core');\n// editor.tools = require('./modules/tools');\n// editor.ui = require('./modules/ui');\n// editor.transport = require('./modules/transport');\n// editor.renderer = require('./modules/renderer');\n// editor.saver = require('./modules/saver');\n// editor.content = require('./modules/content');\n// editor.toolbar = require('./modules/toolbar/toolbar');\n// editor.callback = require('./modules/callbacks');\n// editor.draw = require('./modules/draw');\n// editor.caret = require('./modules/caret');\n// editor.notifications = require('./modules/notifications');\n// editor.parser = require('./modules/parser');\n// editor.sanitizer = require('./modules/sanitizer');\n// editor.listeners = require('./modules/listeners');\n// editor.destroyer = require('./modules/destroyer');\n// editor.paste = require('./modules/paste');\n//\n// };\n//\n// /**\n// * @public\n// * holds initial settings\n// */\n// editor.settings = {\n// tools : ['paragraph', 'header', 'picture', 'list', 'quote', 'code', 'twitter', 'instagram', 'smile'],\n// holderId : 'codex-editor',\n//\n// // Type of block showing on empty editor\n// initialBlockPlugin: 'paragraph'\n// };\n//\n// /**\n// * public\n// *\n// * Static nodes\n// */\n// editor.nodes = {\n// holder : null,\n// wrapper : null,\n// toolbar : null,\n// inlineToolbar : {\n// wrapper : null,\n// buttons : null,\n// actions : null\n// },\n// toolbox : null,\n// notifications : null,\n// plusButton : null,\n// showSettingsButton: null,\n// showTrashButton : null,\n// blockSettings : null,\n// pluginSettings : null,\n// defaultSettings : null,\n// toolbarButtons : {}, // { type : DomEl, ... }\n// redactor : null\n// };\n//\n// /**\n// * @public\n// *\n// * Output state\n// */\n// editor.state = {\n// jsonOutput : [],\n// blocks : [],\n// inputs : []\n// };\n//\n// /**\n// * @public\n// * Editor plugins\n// */\n// editor.tools = {};\n//\n// /**\n// * Initialization\n// * @uses Promise cEditor.core.prepare\n// * @param {Object} userSettings\n// * @param {Array} userSettings.tools list of plugins\n// * @param {String} userSettings.holderId Element's id to append editor\n// *\n// * Load user defined tools\n// * Tools must contain this important objects :\n// * @param {String} type - this is a type of plugin. It can be used as plugin name\n// * @param {String} iconClassname - this a icon in toolbar\n// * @param {Object} make - what should plugin do, when it is clicked\n// * @param {Object} appendCallback - callback after clicking\n// * @param {Element} settings - what settings does it have\n// * @param {Object} render - plugin get JSON, and should return HTML\n// * @param {Object} save - plugin gets HTML content, returns JSON\n// * @param {Boolean} displayInToolbox - will be displayed in toolbox. Default value is TRUE\n// * @param {Boolean} enableLineBreaks - inserts new block or break lines. Default value is FALSE\n// *\n// * @example\n// * - type : 'header',\n// * - iconClassname : 'ce-icon-header',\n// * - make : headerTool.make,\n// * - appendCallback : headerTool.appendCallback,\n// * - settings : headerTool.makeSettings(),\n// * - render : headerTool.render,\n// * - save : headerTool.save,\n// * - displayInToolbox : true,\n// * - enableLineBreaks : false\n// */\n// editor.start = function (userSettings) {\n//\n// init();\n//\n// editor.core.prepare(userSettings)\n//\n// // If all ok, make UI, bind events and parse initial-content\n// .then(editor.ui.prepare)\n// .then(editor.tools.prepare)\n// .then(editor.sanitizer.prepare)\n// .then(editor.paste.prepare)\n// .then(editor.transport.prepare)\n// .then(editor.renderer.makeBlocksFromData)\n// .then(editor.ui.saveInputs)\n// .catch(function (error) {\n//\n// editor.core.log('Initialization failed with error: %o', 'warn', error);\n//\n// });\n//\n// };\n//\n// return editor;\n//\n// })({});\n\n\n\n// WEBPACK FOOTER //\n// ./codex.js","module.exports = class Dom {\n\n /**\n * Draws element with class and properties\n *\n * @param {String} el - Element name\n * @param {Array} classList - array of CSS classes\n * @param {Object} properties - list of objects/properties\n *\n * @returns {Element}\n */\n make(el, classList, properties) {\n\n let element = document.createElement(el);\n\n classList.forEach(function (className) {\n\n element.classList.add(className);\n\n });\n\n for(property in properties) {\n\n element.property = properties[property];\n\n }\n\n return element;\n\n }\n\n /**\n * Selector Decorator\n *\n * Returns first match\n *\n * @param {Element} el - element we searching inside. Default - DOM Document\n * @param {String} selector - searching string\n *\n * @returns {Element}\n */\n find(el = document, selector) {\n\n return el.querySelector(selector);\n\n }\n\n /**\n * Selector Decorator.\n *\n * Returns all matches\n *\n * @param {Element} el - element we searching inside. Default - DOM Document\n * @param {String} selector - searching string\n * @returns {NodeList}\n */\n findAll(el = document, selector) {\n\n return el.querySelectorAll(selector);\n\n }\n\n};\n\n\n// WEBPACK FOOTER //\n// ./src/modules/dom.js","/**\n * Codex Editor Core\n *\n * @author Codex Team\n * @version 1.1.3\n */\nmodule.exports = class Core {\n\n /** Editor script prefixes */\n static get scriptPrefix() {\n\n return 'cdx-script-';\n\n }\n\n constructor(Editor) {\n\n this.Editor = Editor;\n\n this.sanitizer = null;\n this.state = {};\n\n }\n\n /**\n * @public\n *\n * Editor preparing method\n * @return Promise\n */\n prepare() {\n\n let self = this;\n\n return new Promise(function (resolve, reject) {\n\n if (typeof self.Editor.config.holderId === undefined ) {\n\n reject(Error(\"Holder wasn't found by ID: #\" + userSettings.holderId));\n\n } else {\n\n resolve();\n\n }\n\n resolve();\n\n });\n\n }\n\n /**\n * Core custom logger\n *\n * @param msg\n * @param type\n * @param args\n */\n log(msg, type, args) {\n\n type = type || 'log';\n\n if (!args) {\n\n args = msg || 'undefined';\n msg = '[codex-editor]: %o';\n\n } else {\n\n msg = '[codex-editor]: ' + msg;\n\n }\n\n try{\n\n if ( 'console' in window && window.console[ type ] ) {\n\n if ( args ) window.console[ type ]( msg, args );\n else window.console[ type ]( msg );\n\n }\n\n } catch(e) {\n // do nothing\n }\n\n }\n\n /**\n * Native Ajax\n * @param {String} settings.url - request URL\n * @param {function} settings.beforeSend - returned value will be passed as context to the Success, Error and Progress callbacks\n * @param {function} settings.success\n * @param {function} settings.progress\n */\n ajax(settings) {\n\n if (!settings || !settings.url) {\n\n return;\n\n }\n\n var XMLHTTP = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'),\n encodedString,\n isFormData,\n prop;\n\n\n settings.async = true;\n settings.type = settings.type || 'GET';\n settings.data = settings.data || '';\n settings['content-type'] = settings['content-type'] || 'application/json; charset=utf-8';\n\n if (settings.type == 'GET' && settings.data) {\n\n settings.url = /\\?/.test(settings.url) ? settings.url + '&' + settings.data : settings.url + '?' + settings.data;\n\n } else {\n\n encodedString = '';\n for(prop in settings.data) {\n\n encodedString += (prop + '=' + encodeURIComponent(settings.data[prop]) + '&');\n\n }\n\n }\n\n if (settings.withCredentials) {\n\n XMLHTTP.withCredentials = true;\n\n }\n\n /**\n * Value returned in beforeSend funtion will be passed as context to the other response callbacks\n * If beforeSend returns false, AJAX will be blocked\n */\n let responseContext,\n beforeSendResult;\n\n if (typeof settings.beforeSend === 'function') {\n\n beforeSendResult = settings.beforeSend.call();\n\n if (beforeSendResult === false) {\n\n return;\n\n }\n\n }\n\n XMLHTTP.open( settings.type, settings.url, settings.async );\n\n /**\n * If we send FormData, we need no content-type header\n */\n isFormData = isFormData_(settings.data);\n\n if (!isFormData) {\n\n if (settings.type !== 'POST') {\n\n XMLHTTP.setRequestHeader('Content-type', settings['content-type']);\n\n } else {\n\n XMLHTTP.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');\n\n }\n\n }\n\n XMLHTTP.setRequestHeader('X-Requested-With', 'XMLHttpRequest');\n\n responseContext = beforeSendResult || XMLHTTP;\n\n if (typeof settings.progress === 'function') {\n\n XMLHTTP.upload.onprogress = settings.progress.bind(responseContext);\n\n }\n\n XMLHTTP.onreadystatechange = function () {\n\n if (XMLHTTP.readyState === 4) {\n\n if (XMLHTTP.status === 200) {\n\n if (typeof settings.success === 'function') {\n\n settings.success.call(responseContext, XMLHTTP.responseText);\n\n }\n\n } else {\n\n if (typeof settings.error === 'function') {\n\n settings.error.call(responseContext, XMLHTTP.responseText, XMLHTTP.status);\n\n }\n\n }\n\n }\n\n };\n\n if (isFormData) {\n\n // Sending FormData\n XMLHTTP.send(settings.data);\n\n } else {\n\n // POST requests\n XMLHTTP.send(encodedString);\n\n }\n\n return XMLHTTP;\n\n }\n\n};\n// module.exports = (function (core) {\n//\n// let editor = codex.editor;\n//\n//\n// /**\n// * @protected\n// *\n// * Helper for insert one element after another\n// */\n// core.insertAfter = function (target, element) {\n//\n// target.parentNode.insertBefore(element, target.nextSibling);\n//\n// };\n//\n// /**\n// * @const\n// *\n// * Readable DOM-node types map\n// */\n// core.nodeTypes = {\n// TAG : 1,\n// TEXT : 3,\n// COMMENT : 8,\n// DOCUMENT_FRAGMENT: 11\n// };\n//\n// /**\n// * @const\n// * Readable keys map\n// */\n// core.keys = { BACKSPACE: 8, TAB: 9, ENTER: 13, SHIFT: 16, CTRL: 17, ALT: 18, ESC: 27, SPACE: 32, LEFT: 37, UP: 38, DOWN: 40, RIGHT: 39, DELETE: 46, META: 91 };\n//\n// /**\n// * @protected\n// *\n// * Check object for DOM node\n// */\n// core.isDomNode = function (el) {\n//\n// return el && typeof el === 'object' && el.nodeType && el.nodeType == this.nodeTypes.TAG;\n//\n// };\n//\n// /**\n// * Checks passed object for emptiness\n// * @require ES5 - Object.keys\n// * @param {object}\n// */\n// core.isEmpty = function ( obj ) {\n//\n// return Object.keys(obj).length === 0;\n//\n// };\n//\n// /**\n// * Appends script to head of document\n// * @return Promise\n// */\n// core.importScript = function (scriptPath, instanceName) {\n//\n// return new Promise(function (resolve, reject) {\n//\n// let script;\n//\n// /** Script is already loaded */\n// if ( !instanceName ) {\n//\n// reject('Instance name is missed');\n//\n// } else if ( document.getElementById(editor.scriptPrefix + instanceName) ) {\n//\n// resolve(scriptPath);\n//\n// }\n//\n// script = document.createElement('SCRIPT');\n// script.async = true;\n// script.defer = true;\n// script.id = editor.scriptPrefix + instanceName;\n//\n// script.onload = function () {\n//\n// resolve(scriptPath);\n//\n// };\n//\n// script.onerror = function () {\n//\n// reject(scriptPath);\n//\n// };\n//\n// script.src = scriptPath;\n// document.head.appendChild(script);\n//\n// });\n//\n// };\n//\n// /**\n// * Function for checking is it FormData object to send.\n// * @param {Object} object to check\n// * @return boolean\n// */\n// var isFormData_ = function (object) {\n//\n// return object instanceof FormData;\n//\n// };\n//\n// /**\n// * Check block\n// * @param target\n// * @description Checks target is it native input\n// */\n// core.isNativeInput = function (target) {\n//\n// var nativeInputAreas = ['INPUT', 'TEXTAREA'];\n//\n// return nativeInputAreas.indexOf(target.tagName) != -1;\n//\n// };\n//\n// /**\n// * Check if block is empty\n// * We should check block textContent, child native inputs and some exceptions like IMG and IFRAME\n// *\n// * @param block\n// * @returns {boolean}\n// */\n// core.isBlockEmpty = function (block) {\n//\n// const EXCEPTION_TAGS = ['IMG', 'IFRAME'];\n//\n// var nativeInputs = block.querySelectorAll('textarea, input'),\n// nativeInputsAreEmpty = true,\n// textContentIsEmpty = !block.textContent.trim();\n//\n// Array.prototype.forEach.call(nativeInputs, function (input) {\n//\n// if (input.type == 'textarea' || input.type == 'text') {\n//\n// nativeInputsAreEmpty = nativeInputsAreEmpty && !input.value.trim();\n//\n// }\n//\n// });\n//\n// return textContentIsEmpty && nativeInputsAreEmpty && !EXCEPTION_TAGS.includes(block.tagName);\n//\n// };\n//\n//\n// return core;\n//\n// })({});\n\n\n\n// WEBPACK FOOTER //\n// ./src/modules/core.js","/**\n * Module UI\n *\n * @type {UI}\n */\nlet className = {\n\n /**\n * @const {string} BLOCK_CLASSNAME - redactor blocks name\n */\n BLOCK_CLASSNAME : 'ce-block',\n\n /**\n * @const {String} wrapper for plugins content\n */\n BLOCK_CONTENT : 'ce-block__content',\n\n /**\n * @const {String} BLOCK_STRETCHED - makes block stretched\n */\n BLOCK_STRETCHED : 'ce-block--stretched',\n\n /**\n * @const {String} BLOCK_HIGHLIGHTED - adds background\n */\n BLOCK_HIGHLIGHTED : 'ce-block--focused',\n\n /**\n * @const {String} - for all default settings\n */\n SETTINGS_ITEM : 'ce-settings__item'\n};\n\nlet CSS_ = {\n editorWrapper : 'codex-editor',\n editorZone : 'ce-redactor'\n};\n\nmodule.exports = class UI {\n\n constructor(Editor) {\n\n this.Editor = Editor;\n\n this.modules = this.Editor.modules;\n\n }\n\n /**\n * @protected\n *\n * Making main interface\n */\n prepare() {\n\n return new Promise(function (resolve, reject) {\n\n let wrapper = this.modules.dom.make('DIV', [ CSS_.editorWrapper ], {}),\n redactor = this.modules.dom.make('DIV', [ CSS_.editorZone ], {}),\n toolbar = makeToolBar_();\n\n wrapper.appendChild(toolbar);\n wrapper.appendChild(redactor);\n\n /** Save created ui-elements to static nodes state */\n editor.nodes.wrapper = wrapper;\n editor.nodes.redactor = redactor;\n\n /** Append editor wrapper with redactor zone into holder */\n editor.nodes.holder.appendChild(wrapper);\n\n resolve();\n\n })\n\n /** Add toolbox tools */\n .then(addTools_)\n\n /** Make container for inline toolbar */\n .then(makeInlineToolbar_)\n\n /** Add inline toolbar tools */\n .then(addInlineToolbarTools_)\n\n /** Draw wrapper for notifications */\n .then(makeNotificationHolder_)\n\n /** Add eventlisteners to redactor elements */\n .then(bindEvents_)\n\n .catch( function () {\n\n editor.core.log(\"Can't draw editor interface\");\n\n });\n\n }\n\n};\n// /**\n// * Codex Editor UI module\n// *\n// * @author Codex Team\n// * @version 1.2.0\n// */\n//\n// module.exports = (function (ui) {\n//\n// let editor = codex.editor;\n//\n// /**\n// * Basic editor classnames\n// */\n// ui.prepare = function () {\n//\n\n//\n// };\n//\n// /**\n// * @private\n// * Draws inline toolbar zone\n// */\n// var makeInlineToolbar_ = function () {\n//\n// var container = editor.draw.inlineToolbar();\n//\n// /** Append to redactor new inline block */\n// editor.nodes.inlineToolbar.wrapper = container;\n//\n// /** Draw toolbar buttons */\n// editor.nodes.inlineToolbar.buttons = editor.draw.inlineToolbarButtons();\n//\n// /** Buttons action or settings */\n// editor.nodes.inlineToolbar.actions = editor.draw.inlineToolbarActions();\n//\n// /** Append to inline toolbar buttons as part of it */\n// editor.nodes.inlineToolbar.wrapper.appendChild(editor.nodes.inlineToolbar.buttons);\n// editor.nodes.inlineToolbar.wrapper.appendChild(editor.nodes.inlineToolbar.actions);\n//\n// editor.nodes.wrapper.appendChild(editor.nodes.inlineToolbar.wrapper);\n//\n// };\n//\n// var makeToolBar_ = function () {\n//\n// let toolbar = editor.draw.toolbar(),\n// blockButtons = makeToolbarSettings_(),\n// toolbarContent = makeToolbarContent_();\n//\n// /** Appending first-level block buttons */\n// toolbar.appendChild(blockButtons);\n//\n// /** Append toolbarContent to toolbar */\n// toolbar.appendChild(toolbarContent);\n//\n// /** Make toolbar global */\n// editor.nodes.toolbar = toolbar;\n//\n// return toolbar;\n//\n// };\n//\n// var makeToolbarContent_ = function () {\n//\n// let toolbarContent = editor.draw.toolbarContent(),\n// toolbox = editor.draw.toolbox(),\n// plusButton = editor.draw.plusButton();\n//\n// /** Append plus button */\n// toolbarContent.appendChild(plusButton);\n//\n// /** Appending toolbar tools */\n// toolbarContent.appendChild(toolbox);\n//\n// /** Make Toolbox and plusButton global */\n// editor.nodes.toolbox = toolbox;\n// editor.nodes.plusButton = plusButton;\n//\n// return toolbarContent;\n//\n// };\n//\n// var makeToolbarSettings_ = function () {\n//\n// let blockSettings = editor.draw.blockSettings(),\n// blockButtons = editor.draw.blockButtons(),\n// defaultSettings = editor.draw.defaultSettings(),\n// showSettingsButton = editor.draw.settingsButton(),\n// showTrashButton = editor.toolbar.settings.makeRemoveBlockButton(),\n// pluginSettings = editor.draw.pluginsSettings();\n//\n// /** Add default and plugins settings */\n// blockSettings.appendChild(pluginSettings);\n// blockSettings.appendChild(defaultSettings);\n//\n// /**\n// * Make blocks buttons\n// * This block contains settings button and remove block button\n// */\n// blockButtons.appendChild(showSettingsButton);\n// blockButtons.appendChild(showTrashButton);\n// blockButtons.appendChild(blockSettings);\n//\n// /** Make BlockSettings, PluginSettings, DefaultSettings global */\n// editor.nodes.blockSettings = blockSettings;\n// editor.nodes.pluginSettings = pluginSettings;\n// editor.nodes.defaultSettings = defaultSettings;\n// editor.nodes.showSettingsButton = showSettingsButton;\n// editor.nodes.showTrashButton = showTrashButton;\n//\n// return blockButtons;\n//\n// };\n//\n// /** Draw notifications holder */\n// var makeNotificationHolder_ = function () {\n//\n// /** Append block with notifications to the document */\n// editor.nodes.notifications = editor.notifications.createHolder();\n//\n// };\n//\n// /**\n// * @private\n// * Append tools passed in editor.tools\n// */\n// var addTools_ = function () {\n//\n// var tool,\n// toolName,\n// toolButton;\n//\n// for ( toolName in editor.settings.tools ) {\n//\n// tool = editor.settings.tools[toolName];\n//\n// editor.tools[toolName] = tool;\n//\n// if (!tool.iconClassname && tool.displayInToolbox) {\n//\n// editor.core.log('Toolbar icon classname missed. Tool %o skipped', 'warn', toolName);\n// continue;\n//\n// }\n//\n// if (typeof tool.render != 'function') {\n//\n// editor.core.log('render method missed. Tool %o skipped', 'warn', toolName);\n// continue;\n//\n// }\n//\n// if (!tool.displayInToolbox) {\n//\n// continue;\n//\n// } else {\n//\n// /** if tools is for toolbox */\n// toolButton = editor.draw.toolbarButton(toolName, tool.iconClassname);\n//\n// editor.nodes.toolbox.appendChild(toolButton);\n//\n// editor.nodes.toolbarButtons[toolName] = toolButton;\n//\n// }\n//\n// }\n//\n// };\n//\n// var addInlineToolbarTools_ = function () {\n//\n// var tools = {\n//\n// bold: {\n// icon : 'ce-icon-bold',\n// command : 'bold'\n// },\n//\n// italic: {\n// icon : 'ce-icon-italic',\n// command : 'italic'\n// },\n//\n// link: {\n// icon : 'ce-icon-link',\n// command : 'createLink'\n// }\n// };\n//\n// var toolButton,\n// tool;\n//\n// for(var name in tools) {\n//\n// tool = tools[name];\n//\n// toolButton = editor.draw.toolbarButtonInline(name, tool.icon);\n//\n// editor.nodes.inlineToolbar.buttons.appendChild(toolButton);\n// /**\n// * Add callbacks to this buttons\n// */\n// editor.ui.setInlineToolbarButtonBehaviour(toolButton, tool.command);\n//\n// }\n//\n// };\n//\n// /**\n// * @private\n// * Bind editor UI events\n// */\n// var bindEvents_ = function () {\n//\n// editor.core.log('ui.bindEvents fired', 'info');\n//\n// // window.addEventListener('error', function (errorMsg, url, lineNumber) {\n// // editor.notifications.errorThrown(errorMsg, event);\n// // }, false );\n//\n// /** All keydowns on Document */\n// editor.listeners.add(document, 'keydown', editor.callback.globalKeydown, false);\n//\n// /** All keydowns on Redactor zone */\n// editor.listeners.add(editor.nodes.redactor, 'keydown', editor.callback.redactorKeyDown, false);\n//\n// /** All keydowns on Document */\n// editor.listeners.add(document, 'keyup', editor.callback.globalKeyup, false );\n//\n// /**\n// * Mouse click to radactor\n// */\n// editor.listeners.add(editor.nodes.redactor, 'click', editor.callback.redactorClicked, false );\n//\n// /**\n// * Clicks to the Plus button\n// */\n// editor.listeners.add(editor.nodes.plusButton, 'click', editor.callback.plusButtonClicked, false);\n//\n// /**\n// * Clicks to SETTINGS button in toolbar\n// */\n// editor.listeners.add(editor.nodes.showSettingsButton, 'click', editor.callback.showSettingsButtonClicked, false );\n//\n// /** Bind click listeners on toolbar buttons */\n// for (var button in editor.nodes.toolbarButtons) {\n//\n// editor.listeners.add(editor.nodes.toolbarButtons[button], 'click', editor.callback.toolbarButtonClicked, false);\n//\n// }\n//\n// };\n//\n// ui.addBlockHandlers = function (block) {\n//\n// if (!block) return;\n//\n// /**\n// * Block keydowns\n// */\n// editor.listeners.add(block, 'keydown', editor.callback.blockKeydown, false);\n//\n// /**\n// * Pasting content from another source\n// * We have two type of sanitization\n// * First - uses deep-first search algorithm to get sub nodes,\n// * sanitizes whole Block_content and replaces cleared nodes\n// * This method is deprecated\n// * Method is used in editor.callback.blockPaste(event)\n// *\n// * Secont - uses Mutation observer.\n// * Observer \"observe\" DOM changes and send changings to callback.\n// * Callback gets changed node, not whole Block_content.\n// * Inserted or changed node, which we've gotten have been cleared and replaced with diry node\n// *\n// * Method is used in editor.callback.blockPasteViaSanitize(event)\n// *\n// * @uses html-janitor\n// * @example editor.callback.blockPasteViaSanitize(event), the second method.\n// *\n// */\n// editor.listeners.add(block, 'paste', editor.paste.blockPasteCallback, false);\n//\n// /**\n// * Show inline toolbar for selected text\n// */\n// editor.listeners.add(block, 'mouseup', editor.toolbar.inline.show, false);\n// editor.listeners.add(block, 'keyup', editor.toolbar.inline.show, false);\n//\n// };\n//\n// /** getting all contenteditable elements */\n// ui.saveInputs = function () {\n//\n// var redactor = editor.nodes.redactor;\n//\n// editor.state.inputs = [];\n//\n// /** Save all inputs in global variable state */\n// var inputs = redactor.querySelectorAll('[contenteditable], input, textarea');\n//\n// Array.prototype.map.call(inputs, function (current) {\n//\n// if (!current.type || current.type == 'text' || current.type == 'textarea') {\n//\n// editor.state.inputs.push(current);\n//\n// }\n//\n// });\n//\n// };\n//\n// /**\n// * Adds first initial block on empty redactor\n// */\n// ui.addInitialBlock = function () {\n//\n// var initialBlockType = editor.settings.initialBlockPlugin,\n// initialBlock;\n//\n// if ( !editor.tools[initialBlockType] ) {\n//\n// editor.core.log('Plugin %o was not implemented and can\\'t be used as initial block', 'warn', initialBlockType);\n// return;\n//\n// }\n//\n// initialBlock = editor.tools[initialBlockType].render();\n//\n// initialBlock.setAttribute('data-placeholder', editor.settings.placeholder);\n//\n// editor.content.insertBlock({\n// type : initialBlockType,\n// block : initialBlock\n// });\n//\n// editor.content.workingNodeChanged(initialBlock);\n//\n// };\n//\n// ui.setInlineToolbarButtonBehaviour = function (button, type) {\n//\n// editor.listeners.add(button, 'mousedown', function (event) {\n//\n// editor.toolbar.inline.toolClicked(event, type);\n//\n// }, false);\n//\n// };\n//\n// return ui;\n//\n// })({});\n\n\n\n// WEBPACK FOOTER //\n// ./src/modules/ui.js"],"sourceRoot":""} \ No newline at end of file diff --git a/codex.js b/codex.js index 689c5716..b0bf3d19 100644 --- a/codex.js +++ b/codex.js @@ -24,7 +24,9 @@ module.exports = class CodexEditor { this._configuration.holderId = config.holderId; this._configuration.placeholder = config.placeholder || 'write your story...'; this._configuration.sanitizer = config.sanitizer || { - + p: true, + b: true, + a: true }; this._configuration.hideToolbar = config.hideToolbar ? config.hideToolbar : false; @@ -59,7 +61,9 @@ module.exports = class CodexEditor { this.eventsDispatcher = new Events(); - this.init(); + return Promise.resolve() + .then(() => this.init()) + .then(() => this.prepare()); } @@ -70,8 +74,9 @@ module.exports = class CodexEditor { */ init() { - let Core = require('./src/modules/core'), - Tools = require('./src/modules/tools'); + let Dom = require('./src/modules/dom'), + Core = require('./src/modules/core'), + Ui = require('./src/modules/ui'); // transport = require('./src/modules/transport'), // renderer = require('./src/modules/renderer'), // saver = require('./src/modules/saver'), @@ -88,13 +93,14 @@ module.exports = class CodexEditor { // paste = require('./src/modules/paste'); let moduleList = { - 'core' : Core, - 'tools' : Tools + 'dom' : Dom, + 'core' : Core, + 'ui' : Ui }; for(let moduleName in moduleList) { - let modules = []; + let modules = {}; for(let moduleExtends in moduleList) { @@ -103,7 +109,7 @@ module.exports = class CodexEditor { continue; } - modules.push(moduleList[moduleExtends]); + modules[moduleExtends] = moduleList[moduleExtends]; } @@ -116,16 +122,30 @@ module.exports = class CodexEditor { } - // this.moduleInstances['core'].prepare(); - Promise.resolve() - .then(this.moduleInstances['core'].prepare.bind(this.moduleInstances['core'])); - // .then(this.moduleInstances['ui'].prepare) - // .then(this.moduleInstances['tools'.prepare]) - // .catch(function (error) { - // - // console.log('Error occured', error); - // - // }); + } + + /** + * @param module - module instance + * @returns {*} + */ + prepare(module) { + + function prepareDecorator(module) { + + return module.prepare(); + + } + + return Promise.resolve() + .then(prepareDecorator(this.moduleInstances['core'])) + .then(prepareDecorator(this.moduleInstances['ui'])); + // .then(this.moduleInstances['tools'.prepare]) + // .catch(function (error) { + // + // console.log('Error occured', error); + // + // }); + } diff --git a/package.json b/package.json index e75ce2ce..8627987d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codex.editor", - "version": "1.7.8", + "version": "2.0.0", "description": "Codex Editor. Native JS, based on API and Open Source", "main": "index.js", "scripts": { diff --git a/src/modules/core.js b/src/modules/core.js index eefefa61..bfb4826d 100644 --- a/src/modules/core.js +++ b/src/modules/core.js @@ -22,6 +22,12 @@ module.exports = class Core { } + /** + * @public + * + * Editor preparing method + * @return Promise + */ prepare() { let self = this; @@ -81,64 +87,150 @@ module.exports = class Core { } + /** + * Native Ajax + * @param {String} settings.url - request URL + * @param {function} settings.beforeSend - returned value will be passed as context to the Success, Error and Progress callbacks + * @param {function} settings.success + * @param {function} settings.progress + */ + ajax(settings) { + + if (!settings || !settings.url) { + + return; + + } + + var XMLHTTP = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'), + encodedString, + isFormData, + prop; + + + settings.async = true; + settings.type = settings.type || 'GET'; + settings.data = settings.data || ''; + settings['content-type'] = settings['content-type'] || 'application/json; charset=utf-8'; + + if (settings.type == 'GET' && settings.data) { + + settings.url = /\?/.test(settings.url) ? settings.url + '&' + settings.data : settings.url + '?' + settings.data; + + } else { + + encodedString = ''; + for(prop in settings.data) { + + encodedString += (prop + '=' + encodeURIComponent(settings.data[prop]) + '&'); + + } + + } + + if (settings.withCredentials) { + + XMLHTTP.withCredentials = true; + + } + + /** + * Value returned in beforeSend funtion will be passed as context to the other response callbacks + * If beforeSend returns false, AJAX will be blocked + */ + let responseContext, + beforeSendResult; + + if (typeof settings.beforeSend === 'function') { + + beforeSendResult = settings.beforeSend.call(); + + if (beforeSendResult === false) { + + return; + + } + + } + + XMLHTTP.open( settings.type, settings.url, settings.async ); + + /** + * If we send FormData, we need no content-type header + */ + isFormData = isFormData_(settings.data); + + if (!isFormData) { + + if (settings.type !== 'POST') { + + XMLHTTP.setRequestHeader('Content-type', settings['content-type']); + + } else { + + XMLHTTP.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + + } + + } + + XMLHTTP.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + + responseContext = beforeSendResult || XMLHTTP; + + if (typeof settings.progress === 'function') { + + XMLHTTP.upload.onprogress = settings.progress.bind(responseContext); + + } + + XMLHTTP.onreadystatechange = function () { + + if (XMLHTTP.readyState === 4) { + + if (XMLHTTP.status === 200) { + + if (typeof settings.success === 'function') { + + settings.success.call(responseContext, XMLHTTP.responseText); + + } + + } else { + + if (typeof settings.error === 'function') { + + settings.error.call(responseContext, XMLHTTP.responseText, XMLHTTP.status); + + } + + } + + } + + }; + + if (isFormData) { + + // Sending FormData + XMLHTTP.send(settings.data); + + } else { + + // POST requests + XMLHTTP.send(encodedString); + + } + + return XMLHTTP; + + } + }; // module.exports = (function (core) { // // let editor = codex.editor; // -// /** -// * @public -// * -// * Editor preparing method -// * @return Promise -// */ -// core.prepare = function (userSettings) { -// -// return new Promise(function (resolve, reject) { -// -// if ( userSettings ) { -// -// editor.settings.tools = userSettings.tools || editor.settings.tools; -// -// } -// -// if (userSettings.data) { -// -// editor.state.blocks = userSettings.data; -// -// } -// -// if (userSettings.initialBlockPlugin) { -// -// editor.settings.initialBlockPlugin = userSettings.initialBlockPlugin; -// -// } -// -// if (userSettings.sanitizer) { -// -// editor.settings.sanitizer = userSettings.sanitizer; -// -// } -// -// editor.hideToolbar = userSettings.hideToolbar; -// -// editor.settings.placeholder = userSettings.placeholder || ''; -// -// editor.nodes.holder = document.getElementById(userSettings.holderId || editor.settings.holderId); -// -// if (typeof editor.nodes.holder === undefined || editor.nodes.holder === null) { -// -// reject(Error("Holder wasn't found by ID: #" + userSettings.holderId)); -// -// } else { -// -// resolve(); -// -// } -// -// }); -// -// }; // // /** // * @protected @@ -192,145 +284,6 @@ module.exports = class Core { // }; // // /** -// * Native Ajax -// * @param {String} settings.url - request URL -// * @param {function} settings.beforeSend - returned value will be passed as context to the Success, Error and Progress callbacks -// * @param {function} settings.success -// * @param {function} settings.progress -// */ -// core.ajax = function (settings) { -// -// if (!settings || !settings.url) { -// -// return; -// -// } -// -// var XMLHTTP = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'), -// encodedString, -// isFormData, -// prop; -// -// -// settings.async = true; -// settings.type = settings.type || 'GET'; -// settings.data = settings.data || ''; -// settings['content-type'] = settings['content-type'] || 'application/json; charset=utf-8'; -// -// if (settings.type == 'GET' && settings.data) { -// -// settings.url = /\?/.test(settings.url) ? settings.url + '&' + settings.data : settings.url + '?' + settings.data; -// -// } else { -// -// encodedString = ''; -// for(prop in settings.data) { -// -// encodedString += (prop + '=' + encodeURIComponent(settings.data[prop]) + '&'); -// -// } -// -// } -// -// if (settings.withCredentials) { -// -// XMLHTTP.withCredentials = true; -// -// } -// -// /** -// * Value returned in beforeSend funtion will be passed as context to the other response callbacks -// * If beforeSend returns false, AJAX will be blocked -// */ -// let responseContext, -// beforeSendResult; -// -// if (typeof settings.beforeSend === 'function') { -// -// beforeSendResult = settings.beforeSend.call(); -// -// if (beforeSendResult === false) { -// -// return; -// -// } -// -// } -// -// XMLHTTP.open( settings.type, settings.url, settings.async ); -// -// /** -// * If we send FormData, we need no content-type header -// */ -// isFormData = isFormData_(settings.data); -// -// if (!isFormData) { -// -// if (settings.type !== 'POST') { -// -// XMLHTTP.setRequestHeader('Content-type', settings['content-type']); -// -// } else { -// -// XMLHTTP.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); -// -// } -// -// } -// -// XMLHTTP.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); -// -// responseContext = beforeSendResult || XMLHTTP; -// -// if (typeof settings.progress === 'function') { -// -// XMLHTTP.upload.onprogress = settings.progress.bind(responseContext); -// -// } -// -// XMLHTTP.onreadystatechange = function () { -// -// if (XMLHTTP.readyState === 4) { -// -// if (XMLHTTP.status === 200) { -// -// if (typeof settings.success === 'function') { -// -// settings.success.call(responseContext, XMLHTTP.responseText); -// -// } -// -// } else { -// -// if (typeof settings.error === 'function') { -// -// settings.error.call(responseContext, XMLHTTP.responseText, XMLHTTP.status); -// -// } -// -// } -// -// } -// -// }; -// -// if (isFormData) { -// -// // Sending FormData -// XMLHTTP.send(settings.data); -// -// } else { -// -// // POST requests -// XMLHTTP.send(encodedString); -// -// } -// -// return XMLHTTP; -// -// }; -// -// /** // * Appends script to head of document // * @return Promise // */ diff --git a/src/modules/dom.js b/src/modules/dom.js new file mode 100644 index 00000000..417e65cf --- /dev/null +++ b/src/modules/dom.js @@ -0,0 +1,63 @@ +module.exports = class Dom { + + /** + * Draws element with class and properties + * + * @param {String} el - Element name + * @param {Array} classList - array of CSS classes + * @param {Object} properties - list of objects/properties + * + * @returns {Element} + */ + make(el, classList, properties) { + + let element = document.createElement(el); + + classList.forEach(function (className) { + + element.classList.add(className); + + }); + + for(property in properties) { + + element.property = properties[property]; + + } + + return element; + + } + + /** + * Selector Decorator + * + * Returns first match + * + * @param {Element} el - element we searching inside. Default - DOM Document + * @param {String} selector - searching string + * + * @returns {Element} + */ + find(el = document, selector) { + + 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} + */ + findAll(el = document, selector) { + + return el.querySelectorAll(selector); + + } + +}; \ No newline at end of file diff --git a/src/modules/draw.js b/src/modules/draw.js index 9c0d87cd..e849507c 100644 --- a/src/modules/draw.js +++ b/src/modules/draw.js @@ -7,32 +7,6 @@ module.exports = (function (draw) { - /** - * Base editor wrapper - */ - draw.wrapper = function () { - - var wrapper = document.createElement('div'); - - wrapper.className += 'codex-editor'; - - return wrapper; - - }; - - /** - * Content-editable holder - */ - draw.redactor = function () { - - var redactor = document.createElement('div'); - - redactor.className += 'ce-redactor'; - - return redactor; - - }; - draw.ceBlock = function () { var block = document.createElement('DIV'); diff --git a/src/modules/ui.js b/src/modules/ui.js index f8b65452..2d933f95 100644 --- a/src/modules/ui.js +++ b/src/modules/ui.js @@ -1,15 +1,97 @@ +/** + * Module UI + * + * @type {UI} + */ +let className = { + + /** + * @const {string} BLOCK_CLASSNAME - redactor blocks name + */ + BLOCK_CLASSNAME : 'ce-block', + + /** + * @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_HIGHLIGHTED - adds background + */ + BLOCK_HIGHLIGHTED : 'ce-block--focused', + + /** + * @const {String} - for all default settings + */ + SETTINGS_ITEM : 'ce-settings__item' +}; + +let CSS_ = { + editorWrapper : 'codex-editor', + editorZone : 'ce-redactor' +}; + module.exports = class UI { constructor(Editor) { + this.Editor = Editor; + + this.modules = this.Editor.modules; + } + /** + * @protected + * + * Making main interface + */ prepare() { - return new Promise(function(resolve, reject) { + return new Promise(function (resolve, reject) { + + let 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"); + }); } @@ -29,82 +111,9 @@ module.exports = class UI { // /** // * Basic editor classnames // */ -// ui.className = { -// -// /** -// * @const {string} BLOCK_CLASSNAME - redactor blocks name -// */ -// BLOCK_CLASSNAME : 'ce-block', -// -// /** -// * @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_HIGHLIGHTED - adds background -// */ -// BLOCK_HIGHLIGHTED : 'ce-block--focused', -// -// /** -// * @const {String} - for all default settings -// */ -// SETTINGS_ITEM : 'ce-settings__item' -// -// }; -// -// /** -// * @protected -// * -// * Making main interface -// */ // ui.prepare = function () { // -// return new Promise(function (resolve) { -// -// let wrapper = editor.draw.wrapper(), -// redactor = editor.draw.redactor(), -// 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"); -// -// }); + // // }; // diff --git a/webpack.config.js b/webpack.config.js index 8cbfd979..805431d1 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -70,7 +70,7 @@ module.exports = { // }), /** Block biuld if errors found */ - new webpack.NoErrorsPlugin(), + // new webpack.NoErrorsPlugin(), ],