diff --git a/build/codex-editor.js b/build/codex-editor.js
index cfe2d268..b1fb7197 100644
--- a/build/codex-editor.js
+++ b/build/codex-editor.js
@@ -43,14 +43,8 @@ var CodexEditor =
/************************************************************************/
/******/ ([
/* 0 */
-/***/ (function(module, exports, __webpack_require__) {
+/***/ function(module, exports, __webpack_require__) {
- 'use strict';
-
- var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
/**
* Codex Editor
*
@@ -70,10 +64,20 @@ var CodexEditor =
* ...
*/
+ 'use strict';
+
/**
- * All Editor components
+ * Require Editor modules places in components/modules dir
*/
- var modules = [__webpack_require__(1), __webpack_require__(2), __webpack_require__(3)];
+
+ 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"); } }
+
+ var modules = (["eventDispatcher.js","tools.js","ui.js"]).map(function (module) {
+
+ return __webpack_require__(1)("./" + module);
+ });
/**
* @class
@@ -104,17 +108,13 @@ var CodexEditor =
}]);
function CodexEditor(config) {
-
- 'use strict';
-
- /**
- * Configuration object
- */
-
var _this = this;
_classCallCheck(this, CodexEditor);
+ /**
+ * Configuration object
+ */
this.config = {};
/**
@@ -177,9 +177,15 @@ var CodexEditor =
modules.forEach(function (Module) {
- _this2.moduleInstances[Module.name] = new Module({
- config: _this2.configuration
- });
+ try {
+
+ _this2.moduleInstances[Module.name] = new Module({
+ config: _this2.configuration
+ });
+ } catch (e) {
+
+ console.log('Module %o skipped because %o', Module, e);
+ }
});
}
@@ -241,7 +247,7 @@ var CodexEditor =
return module.prepare();
};
- return Promise.resolve().then(prepareDecorator(this.moduleInstances['core'])).then(prepareDecorator(this.moduleInstances['ui'])).catch(function (error) {
+ return Promise.resolve().then(prepareDecorator(this.moduleInstances['ui'])).catch(function (error) {
console.log('Error occured', error);
});
@@ -417,555 +423,4750 @@ var CodexEditor =
//
// })({});
-/***/ }),
+/***/ },
/* 1 */
-/***/ (function(module, exports) {
+/***/ function(module, exports, __webpack_require__) {
- 'use strict';
-
- var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
- 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);
- }
- }, {
- key: 'state',
-
-
- /**
- * @param Editor
- * @param Editor.modules {@link Tools#list}
- * @param Editor.config {@link CodexEditor#configuration}
- * @param Editor
- */
- set: function set(Editor) {
-
- this.Editor = Editor;
- }
- }], [{
- key: 'name',
-
-
- /**
- * Module key name
- * @returns {string}
- */
- get: function get() {
-
- return 'dom';
- }
- }]);
-
- return Dom;
- }();
+ var map = {
+ "./_anchors": 2,
+ "./_anchors.js": 2,
+ "./_callbacks": 3,
+ "./_callbacks.js": 3,
+ "./_caret": 4,
+ "./_caret.js": 4,
+ "./_content": 5,
+ "./_content.js": 5,
+ "./_destroyer": 6,
+ "./_destroyer.js": 6,
+ "./_listeners": 7,
+ "./_listeners.js": 7,
+ "./_notifications": 8,
+ "./_notifications.js": 8,
+ "./_parser": 9,
+ "./_parser.js": 9,
+ "./_paste": 10,
+ "./_paste.js": 10,
+ "./_renderer": 11,
+ "./_renderer.js": 11,
+ "./_sanitizer": 12,
+ "./_sanitizer.js": 12,
+ "./_saver": 14,
+ "./_saver.js": 14,
+ "./_transport": 15,
+ "./_transport.js": 15,
+ "./eventDispatcher": 16,
+ "./eventDispatcher.js": 16,
+ "./toolbar/inline": 17,
+ "./toolbar/inline.js": 17,
+ "./toolbar/settings": 18,
+ "./toolbar/settings.js": 18,
+ "./toolbar/toolbar": 19,
+ "./toolbar/toolbar.js": 19,
+ "./toolbar/toolbox": 20,
+ "./toolbar/toolbox.js": 20,
+ "./tools": 21,
+ "./tools.js": 21,
+ "./ui": 22,
+ "./ui.js": 22
+ };
+ function webpackContext(req) {
+ return __webpack_require__(webpackContextResolve(req));
+ };
+ function webpackContextResolve(req) {
+ return map[req] || (function() { throw new Error("Cannot find module '" + req + "'.") }());
+ };
+ webpackContext.keys = function webpackContextKeys() {
+ return Object.keys(map);
+ };
+ webpackContext.resolve = webpackContextResolve;
+ module.exports = webpackContext;
+ webpackContext.id = 1;
-/***/ }),
+
+/***/ },
/* 2 */
-/***/ (function(module, exports) {
+/***/ 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"); } }
-
/**
- * Codex Editor Core
+ * Codex Editor Anchors module
*
* @author Codex Team
- * @version 1.1.3
+ * @version 1.0
*/
- module.exports = function () {
- _createClass(Core, null, [{
- key: 'name',
+ module.exports = function (anchors) {
- /**
- * Module key name
- * @returns {string}
- */
- get: function get() {
+ var editor = codex.editor;
- return 'core';
+ anchors.input = null;
+ anchors.currentNode = null;
+
+ anchors.settingsOpened = function (currentBlock) {
+
+ anchors.currentNode = currentBlock;
+ anchors.input.value = anchors.currentNode.dataset.anchor || '';
+ };
+
+ anchors.anchorChanged = function (e) {
+
+ var newAnchor = e.target.value = anchors.rusToTranslit(e.target.value);
+
+ anchors.currentNode.dataset.anchor = newAnchor;
+
+ if (newAnchor.trim() !== '') {
+
+ anchors.currentNode.classList.add(editor.ui.className.BLOCK_WITH_ANCHOR);
+ } else {
+
+ anchors.currentNode.classList.remove(editor.ui.className.BLOCK_WITH_ANCHOR);
}
- }, {
- key: 'scriptPrefix',
+ };
+ anchors.keyDownOnAnchorInput = function (e) {
- /** Editor script prefixes */
- get: function get() {
+ if (e.keyCode == editor.core.keys.ENTER) {
- return 'cdx-script-';
+ e.preventDefault();
+ e.stopPropagation();
+
+ e.target.blur();
+ editor.toolbar.settings.close();
+ }
+ };
+
+ anchors.keyUpOnAnchorInput = function (e) {
+
+ if (e.keyCode >= editor.core.keys.LEFT && e.keyCode <= editor.core.keys.DOWN) {
+
+ e.stopPropagation();
+ }
+ };
+
+ anchors.rusToTranslit = function (string) {
+
+ var ru = ['А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ь', 'Ы', 'Ь', 'Э', 'Ю', 'Я'],
+ en = ['A', 'B', 'V', 'G', 'D', 'E', 'E', 'Zh', 'Z', 'I', 'Y', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F', 'H', 'C', 'Ch', 'Sh', 'Sch', '', 'Y', '', 'E', 'Yu', 'Ya'];
+
+ for (var i = 0; i < ru.length; i++) {
+
+ string = string.split(ru[i]).join(en[i]);
+ string = string.split(ru[i].toLowerCase()).join(en[i].toLowerCase());
}
- /**
- *
- * @param Editor
- * @param Editor.modules {@link Tools#list}
- * @param Editor.config {@link CodexEditor#configuration}
- */
+ string = string.replace(/[^0-9a-zA-Z_]+/g, '-');
- }]);
+ return string;
+ };
- function Core(config) {
- _classCallCheck(this, Core);
+ return anchors;
+ }({});
+
+/***/ },
+/* 3 */
+/***/ function(module, exports) {
+
+ 'use strict';
- // this.Editor.modules.toolbar;
+ /**
+ * @module Codex Editor Callbacks module
+ * @description Module works with editor added Elements
+ *
+ * @author Codex Team
+ * @version 1.4.0
+ */
- this.Editor = null;
+ module.exports = function (callbacks) {
- // console.log(this.Editor);
-
-
- // this.toolbar = modules.toolbar;
-
- // this.sanitizer = null;
- // this.state = {};
- }
+ var editor = codex.editor;
/**
- * @param Editor
- * @param Editor.modules {@link Tools#list}
- * @param Editor.config {@link CodexEditor#configuration}
- * @param Editor
+ * used by UI module
+ * @description Routes all keydowns on document
+ * @param {Object} event
*/
+ callbacks.globalKeydown = function (event) {
+ switch (event.keyCode) {
+ case editor.core.keys.ENTER:
+ enterKeyPressed_(event);break;
+ }
+ };
- _createClass(Core, [{
- key: 'prepare',
+ /**
+ * used by UI module
+ * @description Routes all keydowns on redactors area
+ * @param {Object} event
+ */
+ callbacks.redactorKeyDown = function (event) {
+ switch (event.keyCode) {
+ case editor.core.keys.TAB:
+ tabKeyPressedOnRedactorsZone_(event);break;
+ case editor.core.keys.ENTER:
+ enterKeyPressedOnRedactorsZone_(event);break;
+ case editor.core.keys.ESC:
+ escapeKeyPressedOnRedactorsZone_(event);break;
+ default:
+ defaultKeyPressedOnRedactorsZone_(event);break;
+ }
+ };
+
+ /**
+ * used by UI module
+ * @description Routes all keyup events
+ * @param {Object} event
+ */
+ callbacks.globalKeyup = function (event) {
+
+ switch (event.keyCode) {
+ case editor.core.keys.UP:
+ case editor.core.keys.LEFT:
+ case editor.core.keys.RIGHT:
+ case editor.core.keys.DOWN:
+ arrowKeyPressed_(event);break;
+ }
+ };
+
+ /**
+ * @param {Object} event
+ * @private
+ *
+ * Handles behaviour when tab pressed
+ * @description if Content is empty show toolbox (if it is closed) or leaf tools
+ * uses Toolbars toolbox module to handle the situation
+ */
+ var tabKeyPressedOnRedactorsZone_ = function tabKeyPressedOnRedactorsZone_(event) {
/**
- * @public
- *
- * Editor preparing method
- * @return Promise
+ * Wait for solution. Would like to know the behaviour
+ * @todo Add spaces
*/
- value: function prepare() {
+ event.preventDefault();
- // let self = this;
-
- console.log('Core prepare fired');
-
- /**
- * Обращение к другому модулю
- */
- console.log(this.Editor.ui.wrapper);
+ if (!editor.core.isBlockEmpty(editor.content.currentNode)) {
return;
+ }
+
+ if (!editor.toolbar.opened) {
+
+ editor.toolbar.open();
+ }
+
+ if (editor.toolbar.opened && !editor.toolbar.toolbox.opened) {
+
+ editor.toolbar.toolbox.open();
+ } else {
+
+ editor.toolbar.toolbox.leaf();
+ }
+ };
+
+ /**
+ * Handles global EnterKey Press
+ * @see enterPressedOnBlock_
+ * @param {Object} event
+ */
+ var enterKeyPressed_ = function enterKeyPressed_() {
+
+ if (editor.content.editorAreaHightlighted) {
/**
- return new Promise(function (resolve, reject) {
- if (typeof self.Editor.config.holderId === undefined ) {
- reject(Error("Holder wasn't found by ID: #" + userSettings.holderId));
- } else {
- resolve();
- }
- resolve();
- });
- */
+ * it means that we lose input index, saved index before is not correct
+ * therefore we need to set caret when we insert new block
+ */
+ editor.caret.inputIndex = -1;
+
+ enterPressedOnBlock_();
+ }
+ };
+
+ /**
+ * Callback for enter key pressing in first-level block area
+ *
+ * @param {Event} event
+ * @private
+ *
+ * @description Inserts new block with initial type from settings
+ */
+ var enterPressedOnBlock_ = function enterPressedOnBlock_() {
+
+ var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;
+
+ editor.content.insertBlock({
+ type: NEW_BLOCK_TYPE,
+ block: editor.tools[NEW_BLOCK_TYPE].render()
+ }, true);
+
+ editor.toolbar.move();
+ editor.toolbar.open();
+ };
+
+ /**
+ * ENTER key handler
+ *
+ * @param {Object} event
+ * @private
+ *
+ * @description Makes new block with initial type from settings
+ */
+ var enterKeyPressedOnRedactorsZone_ = function enterKeyPressedOnRedactorsZone_(event) {
+
+ if (event.target.contentEditable == 'true') {
+
+ /** Update input index */
+ editor.caret.saveCurrentInputIndex();
+ }
+
+ var currentInputIndex = editor.caret.getCurrentInputIndex() || 0,
+ workingNode = editor.content.currentNode,
+ tool = workingNode.dataset.tool,
+ isEnterPressedOnToolbar = editor.toolbar.opened && editor.toolbar.current && event.target == editor.state.inputs[currentInputIndex];
+
+ /** The list of tools which needs the default browser behaviour */
+ var enableLineBreaks = editor.tools[tool].enableLineBreaks;
+
+ /** This type of block creates when enter is pressed */
+ var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;
+
+ /**
+ * When toolbar is opened, select tool instead of making new paragraph
+ */
+ if (isEnterPressedOnToolbar) {
+
+ event.preventDefault();
+
+ editor.toolbar.toolbox.toolClicked(event);
+
+ editor.toolbar.close();
+
+ /**
+ * Stop other listeners callback executions
+ */
+ event.stopPropagation();
+ event.stopImmediatePropagation();
+
+ return;
}
/**
- * Core custom logger
- *
- * @param msg
- * @param type
- * @param args
+ * Allow paragraph lineBreaks with shift enter
+ * Or if shiftkey pressed and enter and enabledLineBreaks, the let new block creation
*/
+ if (event.shiftKey || enableLineBreaks) {
- }, {
- key: 'log',
- value: function log(msg, type, args) {
+ event.stopPropagation();
+ event.stopImmediatePropagation();
+ return;
+ }
- type = type || 'log';
+ var currentSelection = window.getSelection(),
+ currentSelectedNode = currentSelection.anchorNode,
+ caretAtTheEndOfText = editor.caret.position.atTheEnd(),
+ isTextNodeHasParentBetweenContenteditable = false;
- if (!args) {
+ /**
+ * Allow making new
in same block by SHIFT+ENTER and forbids to prevent default browser behaviour
+ */
+ if (event.shiftKey && !enableLineBreaks) {
- args = msg || 'undefined';
- msg = '[codex-editor]: %o';
+ editor.callback.enterPressedOnBlock(editor.content.currentBlock, event);
+ event.preventDefault();
+ return;
+ }
+
+ /**
+ * Workaround situation when caret at the Text node that has some wrapper Elements
+ * Split block cant handle this.
+ * We need to save default behavior
+ */
+ isTextNodeHasParentBetweenContenteditable = currentSelectedNode && currentSelectedNode.parentNode.contentEditable != 'true';
+
+ /**
+ * Split blocks when input has several nodes and caret placed in textNode
+ */
+ if (currentSelectedNode.nodeType == editor.core.nodeTypes.TEXT && !isTextNodeHasParentBetweenContenteditable && !caretAtTheEndOfText) {
+
+ event.preventDefault();
+
+ editor.core.log('Splitting Text node...');
+
+ editor.content.splitBlock(currentInputIndex);
+
+ /** Show plus button when next input after split is empty*/
+ if (!editor.state.inputs[currentInputIndex + 1].textContent.trim()) {
+
+ editor.toolbar.showPlusButton();
+ }
+ } else {
+
+ var islastNode = editor.content.isLastNode(currentSelectedNode);
+
+ if (islastNode && caretAtTheEndOfText) {
+
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopImmediatePropagation();
+
+ editor.core.log('ENTER clicked in last textNode. Create new BLOCK');
+
+ editor.content.insertBlock({
+ type: NEW_BLOCK_TYPE,
+ block: editor.tools[NEW_BLOCK_TYPE].render()
+ }, true);
+
+ editor.toolbar.move();
+ editor.toolbar.open();
+
+ /** Show plus button with empty block */
+ editor.toolbar.showPlusButton();
+ }
+ }
+
+ /** get all inputs after new appending block */
+ editor.ui.saveInputs();
+ };
+
+ /**
+ * Escape behaviour
+ * @param event
+ * @private
+ *
+ * @description Closes toolbox and toolbar. Prevents default behaviour
+ */
+ var escapeKeyPressedOnRedactorsZone_ = function escapeKeyPressedOnRedactorsZone_(event) {
+
+ /** Close all toolbar */
+ editor.toolbar.close();
+
+ /** Close toolbox */
+ editor.toolbar.toolbox.close();
+
+ event.preventDefault();
+ };
+
+ /**
+ * @param {Event} event
+ * @private
+ *
+ * closes and moves toolbar
+ */
+ var arrowKeyPressed_ = function arrowKeyPressed_(event) {
+
+ editor.content.workingNodeChanged();
+
+ /* Closing toolbar */
+ editor.toolbar.close();
+ editor.toolbar.move();
+ };
+
+ /**
+ * @private
+ * @param {Event} event
+ *
+ * @description Closes all opened bars from toolbar.
+ * If block is mark, clears highlightning
+ */
+ var defaultKeyPressedOnRedactorsZone_ = function defaultKeyPressedOnRedactorsZone_() {
+
+ editor.toolbar.close();
+
+ if (!editor.toolbar.inline.actionsOpened) {
+
+ editor.toolbar.inline.close();
+ editor.content.clearMark();
+ }
+ };
+
+ /**
+ * Handler when clicked on redactors area
+ *
+ * @protected
+ * @param event
+ *
+ * @description Detects clicked area. If it is first-level block area, marks as detected and
+ * on next enter press will be inserted new block
+ * Otherwise, save carets position (input index) and put caret to the editable zone.
+ *
+ * @see detectWhenClickedOnFirstLevelBlockArea_
+ *
+ */
+ callbacks.redactorClicked = function (event) {
+
+ detectWhenClickedOnFirstLevelBlockArea_();
+
+ editor.content.workingNodeChanged(event.target);
+ editor.ui.saveInputs();
+
+ var selectedText = editor.toolbar.inline.getSelectionText(),
+ firstLevelBlock;
+
+ /** If selection range took off, then we hide inline toolbar */
+ if (selectedText.length === 0) {
+
+ editor.toolbar.inline.close();
+ }
+
+ /** Update current input index in memory when caret focused into existed input */
+ if (event.target.contentEditable == 'true') {
+
+ editor.caret.saveCurrentInputIndex();
+ }
+
+ if (editor.content.currentNode === null) {
+
+ /**
+ * If inputs in redactor does not exits, then we put input index 0 not -1
+ */
+ var indexOfLastInput = editor.state.inputs.length > 0 ? editor.state.inputs.length - 1 : 0;
+
+ /** If we have any inputs */
+ if (editor.state.inputs.length) {
+
+ /** getting firstlevel parent of input */
+ firstLevelBlock = editor.content.getFirstLevelBlock(editor.state.inputs[indexOfLastInput]);
+ }
+
+ /** If input is empty, then we set caret to the last input */
+ if (editor.state.inputs.length && editor.state.inputs[indexOfLastInput].textContent === '' && firstLevelBlock.dataset.tool == editor.settings.initialBlockPlugin) {
+
+ editor.caret.setToBlock(indexOfLastInput);
} else {
- msg = '[codex-editor]: ' + msg;
+ /** Create new input when caret clicked in redactors area */
+ var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;
+
+ editor.content.insertBlock({
+ type: NEW_BLOCK_TYPE,
+ block: editor.tools[NEW_BLOCK_TYPE].render()
+ });
+
+ /** If there is no inputs except inserted */
+ if (editor.state.inputs.length === 1) {
+
+ editor.caret.setToBlock(indexOfLastInput);
+ } else {
+
+ /** Set caret to this appended input */
+ editor.caret.setToNextBlock(indexOfLastInput);
+ }
+ }
+ } else {
+
+ /** Close all panels */
+ editor.toolbar.settings.close();
+ editor.toolbar.toolbox.close();
+ }
+
+ /**
+ * Move toolbar and open
+ */
+ editor.toolbar.move();
+ editor.toolbar.open();
+
+ var inputIsEmpty = !editor.content.currentNode.textContent.trim(),
+ currentNodeType = editor.content.currentNode.dataset.tool,
+ isInitialType = currentNodeType == editor.settings.initialBlockPlugin;
+
+ /** Hide plus buttons */
+ editor.toolbar.hidePlusButton();
+
+ if (!inputIsEmpty) {
+
+ /** Mark current block */
+ editor.content.markBlock();
+ }
+
+ if (isInitialType && inputIsEmpty) {
+
+ /** Show plus button */
+ editor.toolbar.showPlusButton();
+ }
+ };
+
+ /**
+ * This method allows to define, is caret in contenteditable element or not.
+ *
+ * @private
+ *
+ * @description Otherwise, if we get TEXT node from range container, that will means we have input index.
+ * In this case we use default browsers behaviour (if plugin allows that) or overwritten action.
+ * Therefore, to be sure that we've clicked first-level block area, we should have currentNode, which always
+ * specifies to the first-level block. Other cases we just ignore.
+ */
+ var detectWhenClickedOnFirstLevelBlockArea_ = function detectWhenClickedOnFirstLevelBlockArea_() {
+
+ var selection = window.getSelection(),
+ anchorNode = selection.anchorNode,
+ flag = false;
+
+ if (selection.rangeCount === 0) {
+
+ editor.content.editorAreaHightlighted = true;
+ } else {
+
+ if (!editor.core.isDomNode(anchorNode)) {
+
+ anchorNode = anchorNode.parentNode;
}
- try {
+ /** Already founded, without loop */
+ if (anchorNode.contentEditable == 'true') {
- if ('console' in window && window.console[type]) {
+ flag = true;
+ }
- if (args) window.console[type](msg, args);else window.console[type](msg);
+ while (anchorNode.contentEditable != 'true') {
+
+ anchorNode = anchorNode.parentNode;
+
+ if (anchorNode.contentEditable == 'true') {
+
+ flag = true;
}
- } catch (e) {
- // do nothing
+
+ if (anchorNode == document.body) {
+
+ break;
+ }
+ }
+
+ /** If editable element founded, flag is "TRUE", Therefore we return "FALSE" */
+ editor.content.editorAreaHightlighted = !flag;
+ }
+ };
+
+ /**
+ * Toolbar button click handler
+ *
+ * @param {Object} event - cursor to the button
+ * @protected
+ *
+ * @description gets current tool and calls render method
+ */
+ callbacks.toolbarButtonClicked = function (event) {
+
+ var button = this;
+
+ editor.toolbar.current = button.dataset.type;
+
+ editor.toolbar.toolbox.toolClicked(event);
+ editor.toolbar.close();
+ };
+
+ /**
+ * Show or Hide toolbox when plus button is clicked
+ */
+ callbacks.plusButtonClicked = function () {
+
+ if (!editor.nodes.toolbox.classList.contains('opened')) {
+
+ editor.toolbar.toolbox.open();
+ } else {
+
+ editor.toolbar.toolbox.close();
+ }
+ };
+
+ /**
+ * Block handlers for KeyDown events
+ *
+ * @protected
+ * @param {Object} event
+ *
+ * Handles keydowns on block
+ * @see blockRightOrDownArrowPressed_
+ * @see backspacePressed_
+ * @see blockLeftOrUpArrowPressed_
+ */
+ callbacks.blockKeydown = function (event) {
+
+ var block = event.target; // event.target is input
+
+ switch (event.keyCode) {
+
+ case editor.core.keys.DOWN:
+ case editor.core.keys.RIGHT:
+ blockRightOrDownArrowPressed_(event);
+ break;
+
+ case editor.core.keys.BACKSPACE:
+ backspacePressed_(block, event);
+ break;
+
+ case editor.core.keys.UP:
+ case editor.core.keys.LEFT:
+ blockLeftOrUpArrowPressed_(event);
+ break;
+
+ }
+ };
+
+ /**
+ * RIGHT or DOWN keydowns on block
+ *
+ * @param {Object} event
+ * @private
+ *
+ * @description watches the selection and gets closest editable element.
+ * Uses method getDeepestTextNodeFromPosition to get the last node of next block
+ * Sets caret if it is contenteditable
+ */
+ var blockRightOrDownArrowPressed_ = function blockRightOrDownArrowPressed_(event) {
+
+ var selection = window.getSelection(),
+ inputs = editor.state.inputs,
+ focusedNode = selection.anchorNode,
+ focusedNodeHolder;
+
+ /** Check for caret existance */
+ if (!focusedNode) {
+
+ return false;
+ }
+
+ /** Looking for closest (parent) contentEditable element of focused node */
+ while (focusedNode.contentEditable != 'true') {
+
+ focusedNodeHolder = focusedNode.parentNode;
+ focusedNode = focusedNodeHolder;
+ }
+
+ /** Input index in DOM level */
+ var editableElementIndex = 0;
+
+ while (focusedNode != inputs[editableElementIndex]) {
+
+ editableElementIndex++;
+ }
+
+ /**
+ * Founded contentEditable element doesn't have childs
+ * Or maybe New created block
+ */
+ if (!focusedNode.textContent) {
+
+ editor.caret.setToNextBlock(editableElementIndex);
+ return;
+ }
+
+ /**
+ * Do nothing when caret doesn not reaches the end of last child
+ */
+ var caretInLastChild = false,
+ caretAtTheEndOfText = false;
+
+ var lastChild, deepestTextnode;
+
+ lastChild = focusedNode.childNodes[focusedNode.childNodes.length - 1];
+
+ if (editor.core.isDomNode(lastChild)) {
+
+ deepestTextnode = editor.content.getDeepestTextNodeFromPosition(lastChild, lastChild.childNodes.length);
+ } else {
+
+ deepestTextnode = lastChild;
+ }
+
+ caretInLastChild = selection.anchorNode == deepestTextnode;
+ caretAtTheEndOfText = deepestTextnode.length == selection.anchorOffset;
+
+ if (!caretInLastChild || !caretAtTheEndOfText) {
+
+ editor.core.log('arrow [down|right] : caret does not reached the end');
+ return false;
+ }
+
+ editor.caret.setToNextBlock(editableElementIndex);
+ };
+
+ /**
+ * LEFT or UP keydowns on block
+ *
+ * @param {Object} event
+ * @private
+ *
+ * watches the selection and gets closest editable element.
+ * Uses method getDeepestTextNodeFromPosition to get the last node of previous block
+ * Sets caret if it is contenteditable
+ *
+ */
+ var blockLeftOrUpArrowPressed_ = function blockLeftOrUpArrowPressed_(event) {
+
+ var selection = window.getSelection(),
+ inputs = editor.state.inputs,
+ focusedNode = selection.anchorNode,
+ focusedNodeHolder;
+
+ /** Check for caret existance */
+ if (!focusedNode) {
+
+ return false;
+ }
+
+ /**
+ * LEFT or UP not at the beginning
+ */
+ if (selection.anchorOffset !== 0) {
+
+ return false;
+ }
+
+ /** Looking for parent contentEditable block */
+ while (focusedNode.contentEditable != 'true') {
+
+ focusedNodeHolder = focusedNode.parentNode;
+ focusedNode = focusedNodeHolder;
+ }
+
+ /** Input index in DOM level */
+ var editableElementIndex = 0;
+
+ while (focusedNode != inputs[editableElementIndex]) {
+
+ editableElementIndex++;
+ }
+
+ /**
+ * Do nothing if caret is not at the beginning of first child
+ */
+ var caretInFirstChild = false,
+ caretAtTheBeginning = false;
+
+ var firstChild, deepestTextnode;
+
+ /**
+ * Founded contentEditable element doesn't have childs
+ * Or maybe New created block
+ */
+ if (!focusedNode.textContent) {
+
+ editor.caret.setToPreviousBlock(editableElementIndex);
+ return;
+ }
+
+ firstChild = focusedNode.childNodes[0];
+
+ if (editor.core.isDomNode(firstChild)) {
+
+ deepestTextnode = editor.content.getDeepestTextNodeFromPosition(firstChild, 0);
+ } else {
+
+ deepestTextnode = firstChild;
+ }
+
+ caretInFirstChild = selection.anchorNode == deepestTextnode;
+ caretAtTheBeginning = selection.anchorOffset === 0;
+
+ if (caretInFirstChild && caretAtTheBeginning) {
+
+ editor.caret.setToPreviousBlock(editableElementIndex);
+ }
+ };
+
+ /**
+ * Handles backspace keydown
+ *
+ * @param {Element} block
+ * @param {Object} event
+ * @private
+ *
+ * @description if block is empty, delete the block and set caret to the previous block
+ * If block is not empty, try to merge two blocks - current and previous
+ * But it we try'n to remove first block, then we should set caret to the next block, not previous.
+ * If we removed the last block, create new one
+ */
+ var backspacePressed_ = function backspacePressed_(block, event) {
+
+ var currentInputIndex = editor.caret.getCurrentInputIndex(),
+ range,
+ selectionLength,
+ firstLevelBlocksCount;
+
+ if (editor.core.isNativeInput(event.target)) {
+
+ /** If input value is empty - remove block */
+ if (event.target.value.trim() == '') {
+
+ block.remove();
+ } else {
+
+ return;
+ }
+ }
+
+ if (block.textContent.trim()) {
+
+ range = editor.content.getRange();
+ selectionLength = range.endOffset - range.startOffset;
+
+ if (editor.caret.position.atStart() && !selectionLength && editor.state.inputs[currentInputIndex - 1]) {
+
+ editor.content.mergeBlocks(currentInputIndex);
+ } else {
+
+ return;
+ }
+ }
+
+ if (!selectionLength) {
+
+ block.remove();
+ }
+
+ firstLevelBlocksCount = editor.nodes.redactor.childNodes.length;
+
+ /**
+ * If all blocks are removed
+ */
+ if (firstLevelBlocksCount === 0) {
+
+ /** update currentNode variable */
+ editor.content.currentNode = null;
+
+ /** Inserting new empty initial block */
+ editor.ui.addInitialBlock();
+
+ /** Updating inputs state after deleting last block */
+ editor.ui.saveInputs();
+
+ /** Set to current appended block */
+ window.setTimeout(function () {
+
+ editor.caret.setToPreviousBlock(1);
+ }, 10);
+ } else {
+
+ if (editor.caret.inputIndex !== 0) {
+
+ /** Target block is not first */
+ editor.caret.setToPreviousBlock(editor.caret.inputIndex);
+ } else {
+
+ /** If we try to delete first block */
+ editor.caret.setToNextBlock(editor.caret.inputIndex);
+ }
+ }
+
+ editor.toolbar.move();
+
+ if (!editor.toolbar.opened) {
+
+ editor.toolbar.open();
+ }
+
+ /** Updating inputs state */
+ editor.ui.saveInputs();
+
+ /** Prevent default browser behaviour */
+ event.preventDefault();
+ };
+
+ /**
+ * used by UI module
+ * Clicks on block settings button
+ *
+ * @param {Object} event
+ * @protected
+ * @description Opens toolbar settings
+ */
+ callbacks.showSettingsButtonClicked = function (event) {
+
+ /**
+ * Get type of current block
+ * It uses to append settings from tool.settings property.
+ * ...
+ * Type is stored in data-type attribute on block
+ */
+ var currentToolType = editor.content.currentNode.dataset.tool;
+
+ editor.toolbar.settings.toggle(currentToolType);
+
+ /** Close toolbox when settings button is active */
+ editor.toolbar.toolbox.close();
+ editor.toolbar.settings.hideRemoveActions();
+ };
+
+ return callbacks;
+ }({});
+
+/***/ },
+/* 4 */
+/***/ function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * Codex Editor Caret Module
+ *
+ * @author Codex Team
+ * @version 1.0
+ */
+
+ module.exports = function (caret) {
+
+ var editor = codex.editor;
+
+ /**
+ * @var {int} InputIndex - editable element in DOM
+ */
+ caret.inputIndex = null;
+
+ /**
+ * @var {int} offset - caret position in a text node.
+ */
+ caret.offset = null;
+
+ /**
+ * @var {int} focusedNodeIndex - we get index of child node from first-level block
+ */
+ caret.focusedNodeIndex = null;
+
+ /**
+ * Creates Document Range and sets caret to the element.
+ * @protected
+ * @uses caret.save — if you need to save caret position
+ * @param {Element} el - Changed Node.
+ */
+ caret.set = function (el, index, offset) {
+
+ offset = offset || caret.offset || 0;
+ index = index || caret.focusedNodeIndex || 0;
+
+ var childs = el.childNodes,
+ nodeToSet;
+
+ if (childs.length === 0) {
+
+ nodeToSet = el;
+ } else {
+
+ nodeToSet = childs[index];
+ }
+
+ /** If Element is INPUT */
+ if (el.contentEditable != 'true') {
+
+ el.focus();
+ return;
+ }
+
+ if (editor.core.isDomNode(nodeToSet)) {
+
+ nodeToSet = editor.content.getDeepestTextNodeFromPosition(nodeToSet, nodeToSet.childNodes.length);
+ }
+
+ var range = document.createRange(),
+ selection = window.getSelection();
+
+ window.setTimeout(function () {
+
+ range.setStart(nodeToSet, offset);
+ range.setEnd(nodeToSet, offset);
+
+ selection.removeAllRanges();
+ selection.addRange(range);
+
+ editor.caret.saveCurrentInputIndex();
+ }, 20);
+ };
+
+ /**
+ * @protected
+ * Updates index of input and saves it in caret object
+ */
+ caret.saveCurrentInputIndex = function () {
+
+ /** Index of Input that we paste sanitized content */
+ var selection = window.getSelection(),
+ inputs = editor.state.inputs,
+ focusedNode = selection.anchorNode,
+ focusedNodeHolder;
+
+ if (!focusedNode) {
+
+ return;
+ }
+
+ /** Looking for parent contentEditable block */
+ while (focusedNode.contentEditable != 'true') {
+
+ focusedNodeHolder = focusedNode.parentNode;
+ focusedNode = focusedNodeHolder;
+ }
+
+ /** Input index in DOM level */
+ var editableElementIndex = 0;
+
+ while (focusedNode != inputs[editableElementIndex]) {
+
+ editableElementIndex++;
+ }
+
+ caret.inputIndex = editableElementIndex;
+ };
+
+ /**
+ * Returns current input index (caret object)
+ */
+ caret.getCurrentInputIndex = function () {
+
+ return caret.inputIndex;
+ };
+
+ /**
+ * @param {int} index - index of first-level block after that we set caret into next input
+ */
+ caret.setToNextBlock = function (index) {
+
+ var inputs = editor.state.inputs,
+ nextInput = inputs[index + 1];
+
+ if (!nextInput) {
+
+ editor.core.log('We are reached the end');
+ return;
+ }
+
+ /**
+ * When new Block created or deleted content of input
+ * We should add some text node to set caret
+ */
+ if (!nextInput.childNodes.length) {
+
+ var emptyTextElement = document.createTextNode('');
+
+ nextInput.appendChild(emptyTextElement);
+ }
+
+ editor.caret.inputIndex = index + 1;
+ editor.caret.set(nextInput, 0, 0);
+ editor.content.workingNodeChanged(nextInput);
+ };
+
+ /**
+ * @param {int} index - index of target input.
+ * Sets caret to input with this index
+ */
+ caret.setToBlock = function (index) {
+
+ var inputs = editor.state.inputs,
+ targetInput = inputs[index];
+
+ if (!targetInput) {
+
+ return;
+ }
+
+ /**
+ * When new Block created or deleted content of input
+ * We should add some text node to set caret
+ */
+ if (!targetInput.childNodes.length) {
+
+ var emptyTextElement = document.createTextNode('');
+
+ targetInput.appendChild(emptyTextElement);
+ }
+
+ editor.caret.inputIndex = index;
+ editor.caret.set(targetInput, 0, 0);
+ editor.content.workingNodeChanged(targetInput);
+ };
+
+ /**
+ * @param {int} index - index of input
+ */
+ caret.setToPreviousBlock = function (index) {
+
+ index = index || 0;
+
+ var inputs = editor.state.inputs,
+ previousInput = inputs[index - 1],
+ lastChildNode,
+ lengthOfLastChildNode,
+ emptyTextElement;
+
+ if (!previousInput) {
+
+ editor.core.log('We are reached first node');
+ return;
+ }
+
+ lastChildNode = editor.content.getDeepestTextNodeFromPosition(previousInput, previousInput.childNodes.length);
+ lengthOfLastChildNode = lastChildNode.length;
+
+ /**
+ * When new Block created or deleted content of input
+ * We should add some text node to set caret
+ */
+ if (!previousInput.childNodes.length) {
+
+ emptyTextElement = document.createTextNode('');
+ previousInput.appendChild(emptyTextElement);
+ }
+ editor.caret.inputIndex = index - 1;
+ editor.caret.set(previousInput, previousInput.childNodes.length - 1, lengthOfLastChildNode);
+ editor.content.workingNodeChanged(inputs[index - 1]);
+ };
+
+ caret.position = {
+
+ atStart: function atStart() {
+
+ var selection = window.getSelection(),
+ anchorOffset = selection.anchorOffset,
+ anchorNode = selection.anchorNode,
+ firstLevelBlock = editor.content.getFirstLevelBlock(anchorNode),
+ pluginsRender = firstLevelBlock.childNodes[0];
+
+ if (!editor.core.isDomNode(anchorNode)) {
+
+ anchorNode = anchorNode.parentNode;
+ }
+
+ var isFirstNode = anchorNode === pluginsRender.childNodes[0],
+ isOffsetZero = anchorOffset === 0;
+
+ return isFirstNode && isOffsetZero;
+ },
+
+ atTheEnd: function atTheEnd() {
+
+ var selection = window.getSelection(),
+ anchorOffset = selection.anchorOffset,
+ anchorNode = selection.anchorNode;
+
+ /** Caret is at the end of input */
+ return !anchorNode || !anchorNode.length || anchorOffset === anchorNode.length;
+ }
+ };
+
+ /**
+ * Inserts node at the caret location
+ * @param {HTMLElement|DocumentFragment} node
+ */
+ caret.insertNode = function (node) {
+
+ var selection,
+ range,
+ lastNode = node;
+
+ if (node.nodeType == editor.core.nodeTypes.DOCUMENT_FRAGMENT) {
+
+ lastNode = node.lastChild;
+ }
+
+ selection = window.getSelection();
+
+ range = selection.getRangeAt(0);
+ range.deleteContents();
+
+ range.insertNode(node);
+
+ range.setStartAfter(lastNode);
+ range.collapse(true);
+
+ selection.removeAllRanges();
+ selection.addRange(range);
+ };
+
+ return caret;
+ }({});
+
+/***/ },
+/* 5 */
+/***/ function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * Codex Editor Content Module
+ * Works with DOM
+ *
+ * @module Codex Editor content module
+ *
+ * @author Codex Team
+ * @version 1.3.13
+ *
+ * @description Module works with Elements that have been appended to the main DOM
+ */
+
+ module.exports = function (content) {
+
+ var editor = codex.editor;
+
+ /**
+ * Links to current active block
+ * @type {null | Element}
+ */
+ content.currentNode = null;
+
+ /**
+ * clicked in redactor area
+ * @type {null | Boolean}
+ */
+ content.editorAreaHightlighted = null;
+
+ /**
+ * @deprecated
+ * Synchronizes redactor with original textarea
+ */
+ content.sync = function () {
+
+ editor.core.log('syncing...');
+
+ /**
+ * Save redactor content to editor.state
+ */
+ editor.state.html = editor.nodes.redactor.innerHTML;
+ };
+
+ /**
+ * Appends background to the block
+ *
+ * @description add CSS class to highlight visually first-level block area
+ */
+ content.markBlock = function () {
+
+ editor.content.currentNode.classList.add(editor.ui.className.BLOCK_HIGHLIGHTED);
+ };
+
+ /**
+ * Clear background
+ *
+ * @description clears styles that highlights block
+ */
+ content.clearMark = function () {
+
+ if (editor.content.currentNode) {
+
+ editor.content.currentNode.classList.remove(editor.ui.className.BLOCK_HIGHLIGHTED);
+ }
+ };
+
+ /**
+ * Finds first-level block
+ *
+ * @param {Element} node - selected or clicked in redactors area node
+ * @protected
+ *
+ * @description looks for first-level block.
+ * gets parent while node is not first-level
+ */
+ content.getFirstLevelBlock = function (node) {
+
+ if (!editor.core.isDomNode(node)) {
+
+ node = node.parentNode;
+ }
+
+ if (node === editor.nodes.redactor || node === document.body) {
+
+ return null;
+ } else {
+
+ while (!node.classList.contains(editor.ui.className.BLOCK_CLASSNAME)) {
+
+ node = node.parentNode;
+ }
+
+ return node;
+ }
+ };
+
+ /**
+ * Trigger this event when working node changed
+ * @param {Element} targetNode - first-level of this node will be current
+ * @protected
+ *
+ * @description If targetNode is first-level then we set it as current else we look for parents to find first-level
+ */
+ content.workingNodeChanged = function (targetNode) {
+
+ /** Clear background from previous marked block before we change */
+ editor.content.clearMark();
+
+ if (!targetNode) {
+
+ return;
+ }
+
+ content.currentNode = content.getFirstLevelBlock(targetNode);
+ };
+
+ /**
+ * Replaces one redactor block with another
+ * @protected
+ * @param {Element} targetBlock - block to replace. Mostly currentNode.
+ * @param {Element} newBlock
+ * @param {string} newBlockType - type of new block; we need to store it to data-attribute
+ *
+ * [!] Function does not saves old block content.
+ * You can get it manually and pass with newBlock.innerHTML
+ */
+ content.replaceBlock = function (targetBlock, newBlock) {
+
+ if (!targetBlock || !newBlock) {
+
+ editor.core.log('replaceBlock: missed params');
+ return;
+ }
+
+ /** If target-block is not a frist-level block, then we iterate parents to find it */
+ while (!targetBlock.classList.contains(editor.ui.className.BLOCK_CLASSNAME)) {
+
+ targetBlock = targetBlock.parentNode;
+ }
+
+ /** Replacing */
+ editor.nodes.redactor.replaceChild(newBlock, targetBlock);
+
+ /**
+ * Set new node as current
+ */
+ editor.content.workingNodeChanged(newBlock);
+
+ /**
+ * Add block handlers
+ */
+ editor.ui.addBlockHandlers(newBlock);
+
+ /**
+ * Save changes
+ */
+ editor.ui.saveInputs();
+ };
+
+ /**
+ * @protected
+ *
+ * Inserts new block to redactor
+ * Wrapps block into a DIV with BLOCK_CLASSNAME class
+ *
+ * @param blockData {object}
+ * @param blockData.block {Element} element with block content
+ * @param blockData.type {string} block plugin
+ * @param needPlaceCaret {bool} pass true to set caret in new block
+ *
+ */
+ content.insertBlock = function (blockData, needPlaceCaret) {
+
+ var workingBlock = editor.content.currentNode,
+ newBlockContent = blockData.block,
+ blockType = blockData.type,
+ isStretched = blockData.stretched;
+
+ var newBlock = composeNewBlock_(newBlockContent, blockType, isStretched);
+
+ if (workingBlock) {
+
+ editor.core.insertAfter(workingBlock, newBlock);
+ } else {
+
+ /**
+ * If redactor is empty, append as first child
+ */
+ editor.nodes.redactor.appendChild(newBlock);
+ }
+
+ /**
+ * Block handler
+ */
+ editor.ui.addBlockHandlers(newBlock);
+
+ /**
+ * Set new node as current
+ */
+ editor.content.workingNodeChanged(newBlock);
+
+ /**
+ * Save changes
+ */
+ editor.ui.saveInputs();
+
+ if (needPlaceCaret) {
+
+ /**
+ * If we don't know input index then we set default value -1
+ */
+ var currentInputIndex = editor.caret.getCurrentInputIndex() || -1;
+
+ if (currentInputIndex == -1) {
+
+ var editableElement = newBlock.querySelector('[contenteditable]'),
+ emptyText = document.createTextNode('');
+
+ editableElement.appendChild(emptyText);
+ editor.caret.set(editableElement, 0, 0);
+
+ editor.toolbar.move();
+ editor.toolbar.showPlusButton();
+ } else {
+
+ if (currentInputIndex === editor.state.inputs.length - 1) return;
+
+ /** Timeout for browsers execution */
+ window.setTimeout(function () {
+
+ /** Setting to the new input */
+ editor.caret.setToNextBlock(currentInputIndex);
+ editor.toolbar.move();
+ editor.toolbar.open();
+ }, 10);
}
}
/**
- * 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
+ * Block is inserted, wait for new click that defined focusing on editors area
+ * @type {boolean}
*/
+ content.editorAreaHightlighted = false;
+ };
- }, {
- key: 'ajax',
- value: function ajax(settings) {
+ /**
+ * Replaces blocks with saving content
+ * @protected
+ * @param {Element} noteToReplace
+ * @param {Element} newNode
+ * @param {Element} blockType
+ */
+ content.switchBlock = function (blockToReplace, newBlock, tool) {
- if (!settings || !settings.url) {
+ tool = tool || editor.content.currentNode.dataset.tool;
+ var newBlockComposed = composeNewBlock_(newBlock, tool);
+
+ /** Replacing */
+ editor.content.replaceBlock(blockToReplace, newBlockComposed);
+
+ /** Save new Inputs when block is changed */
+ editor.ui.saveInputs();
+ };
+
+ /**
+ * Iterates between child noted and looking for #text node on deepest level
+ * @protected
+ *
+ * @param {Element} block - node where find
+ * @param {int} postiton - starting postion
+ * Example: childNodex.length to find from the end
+ * or 0 to find from the start
+ * @return {Text} block
+ * @uses DFS
+ */
+ content.getDeepestTextNodeFromPosition = function (block, position) {
+
+ /**
+ * Clear Block from empty and useless spaces with trim.
+ * Such nodes we should remove
+ */
+ var blockChilds = block.childNodes,
+ index,
+ node,
+ text;
+
+ for (index = 0; index < blockChilds.length; index++) {
+
+ node = blockChilds[index];
+
+ if (node.nodeType == editor.core.nodeTypes.TEXT) {
+
+ text = node.textContent.trim();
+
+ /** Text is empty. We should remove this child from node before we start DFS
+ * decrease the quantity of childs.
+ */
+ if (text === '') {
+
+ block.removeChild(node);
+ position--;
+ }
+ }
+ }
+
+ if (block.childNodes.length === 0) {
+
+ return document.createTextNode('');
+ }
+
+ /** Setting default position when we deleted all empty nodes */
+ if (position < 0) position = 1;
+
+ var lookingFromStart = false;
+
+ /** For looking from START */
+ if (position === 0) {
+
+ lookingFromStart = true;
+ position = 1;
+ }
+
+ while (position) {
+
+ /** initial verticle of node. */
+ if (lookingFromStart) {
+
+ block = block.childNodes[0];
+ } else {
+
+ block = block.childNodes[position - 1];
+ }
+
+ if (block.nodeType == editor.core.nodeTypes.TAG) {
+
+ position = block.childNodes.length;
+ } else if (block.nodeType == editor.core.nodeTypes.TEXT) {
+
+ position = 0;
+ }
+ }
+
+ return block;
+ };
+
+ /**
+ * @private
+ * @param {Element} block - current plugins render
+ * @param {String} tool - plugins name
+ * @param {Boolean} isStretched - make stretched block or not
+ *
+ * @description adds necessary information to wrap new created block by first-level holder
+ */
+ var composeNewBlock_ = function composeNewBlock_(block, tool, isStretched) {
+
+ var newBlock = editor.draw.node('DIV', editor.ui.className.BLOCK_CLASSNAME, {}),
+ blockContent = editor.draw.node('DIV', editor.ui.className.BLOCK_CONTENT, {});
+
+ blockContent.appendChild(block);
+ newBlock.appendChild(blockContent);
+
+ if (isStretched) {
+
+ blockContent.classList.add(editor.ui.className.BLOCK_STRETCHED);
+ }
+
+ newBlock.dataset.tool = tool;
+ return newBlock;
+ };
+
+ /**
+ * Returns Range object of current selection
+ * @protected
+ */
+ content.getRange = function () {
+
+ var selection = window.getSelection().getRangeAt(0);
+
+ return selection;
+ };
+
+ /**
+ * Divides block in two blocks (after and before caret)
+ *
+ * @protected
+ * @param {int} inputIndex - target input index
+ *
+ * @description splits current input content to the separate blocks
+ * When enter is pressed among the words, that text will be splited.
+ */
+ content.splitBlock = function (inputIndex) {
+
+ var selection = window.getSelection(),
+ anchorNode = selection.anchorNode,
+ anchorNodeText = anchorNode.textContent,
+ caretOffset = selection.anchorOffset,
+ textBeforeCaret,
+ textNodeBeforeCaret,
+ textAfterCaret,
+ textNodeAfterCaret;
+
+ var currentBlock = editor.content.currentNode.querySelector('[contentEditable]');
+
+ textBeforeCaret = anchorNodeText.substring(0, caretOffset);
+ textAfterCaret = anchorNodeText.substring(caretOffset);
+
+ textNodeBeforeCaret = document.createTextNode(textBeforeCaret);
+
+ if (textAfterCaret) {
+
+ textNodeAfterCaret = document.createTextNode(textAfterCaret);
+ }
+
+ var previousChilds = [],
+ nextChilds = [],
+ reachedCurrent = false;
+
+ if (textNodeAfterCaret) {
+
+ nextChilds.push(textNodeAfterCaret);
+ }
+
+ for (var i = 0, child; !!(child = currentBlock.childNodes[i]); i++) {
+
+ if (child != anchorNode) {
+
+ if (!reachedCurrent) {
+
+ previousChilds.push(child);
+ } else {
+
+ nextChilds.push(child);
+ }
+ } else {
+
+ reachedCurrent = true;
+ }
+ }
+
+ /** Clear current input */
+ editor.state.inputs[inputIndex].innerHTML = '';
+
+ /**
+ * Append all childs founded before anchorNode
+ */
+ var previousChildsLength = previousChilds.length;
+
+ for (i = 0; i < previousChildsLength; i++) {
+
+ editor.state.inputs[inputIndex].appendChild(previousChilds[i]);
+ }
+
+ editor.state.inputs[inputIndex].appendChild(textNodeBeforeCaret);
+
+ /**
+ * Append text node which is after caret
+ */
+ var nextChildsLength = nextChilds.length,
+ newNode = document.createElement('div');
+
+ for (i = 0; i < nextChildsLength; i++) {
+
+ newNode.appendChild(nextChilds[i]);
+ }
+
+ newNode = newNode.innerHTML;
+
+ /** This type of block creates when enter is pressed */
+ var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;
+
+ /**
+ * Make new paragraph with text after caret
+ */
+ editor.content.insertBlock({
+ type: NEW_BLOCK_TYPE,
+ block: editor.tools[NEW_BLOCK_TYPE].render({
+ text: newNode
+ })
+ }, true);
+ };
+
+ /**
+ * Merges two blocks — current and target
+ * If target index is not exist, then previous will be as target
+ *
+ * @protected
+ * @param {int} currentInputIndex
+ * @param {int} targetInputIndex
+ *
+ * @description gets two inputs indexes and merges into one
+ */
+ content.mergeBlocks = function (currentInputIndex, targetInputIndex) {
+
+ /** If current input index is zero, then prevent method execution */
+ if (currentInputIndex === 0) {
+
+ return;
+ }
+
+ var targetInput,
+ currentInputContent = editor.state.inputs[currentInputIndex].innerHTML;
+
+ if (!targetInputIndex) {
+
+ targetInput = editor.state.inputs[currentInputIndex - 1];
+ } else {
+
+ targetInput = editor.state.inputs[targetInputIndex];
+ }
+
+ targetInput.innerHTML += currentInputContent;
+ };
+
+ /**
+ * Iterates all right siblings and parents, which has right siblings
+ * while it does not reached the first-level block
+ *
+ * @param {Element} node
+ * @return {boolean}
+ */
+ content.isLastNode = function (node) {
+
+ // console.log('погнали перебор родителей');
+
+ var allChecked = false;
+
+ while (!allChecked) {
+
+ // console.log('Смотрим на %o', node);
+ // console.log('Проверим, пустые ли соседи справа');
+
+ if (!allSiblingsEmpty_(node)) {
+
+ // console.log('Есть непустые соседи. Узел не последний. Выходим.');
+ return false;
+ }
+
+ node = node.parentNode;
+
+ /**
+ * Проверяем родителей до тех пор, пока не найдем блок первого уровня
+ */
+ if (node.classList.contains(editor.ui.className.BLOCK_CONTENT)) {
+
+ allChecked = true;
+ }
+ }
+
+ return true;
+ };
+
+ /**
+ * Checks if all element right siblings is empty
+ * @param node
+ */
+ var allSiblingsEmpty_ = function allSiblingsEmpty_(node) {
+
+ /**
+ * Нужно убедиться, что после пустого соседа ничего нет
+ */
+ var sibling = node.nextSibling;
+
+ while (sibling) {
+
+ if (sibling.textContent.length) {
+
+ return false;
+ }
+
+ sibling = sibling.nextSibling;
+ }
+
+ return true;
+ };
+
+ /**
+ * @public
+ *
+ * @param {string} htmlData - html content as string
+ * @param {string} plainData - plain text
+ * @return {string} - html content as string
+ */
+ content.wrapTextWithParagraphs = function (htmlData, plainData) {
+
+ if (!htmlData.trim()) {
+
+ return wrapPlainTextWithParagraphs(plainData);
+ }
+
+ var wrapper = document.createElement('DIV'),
+ newWrapper = document.createElement('DIV'),
+ i,
+ paragraph,
+ firstLevelBlocks = ['DIV', 'P'],
+ blockTyped,
+ node;
+
+ /**
+ * Make HTML Element to Wrap Text
+ * It allows us to work with input data as HTML content
+ */
+ wrapper.innerHTML = htmlData;
+ paragraph = document.createElement('P');
+
+ for (i = 0; i < wrapper.childNodes.length; i++) {
+
+ node = wrapper.childNodes[i];
+
+ blockTyped = firstLevelBlocks.indexOf(node.tagName) != -1;
+
+ /**
+ * If node is first-levet
+ * we add this node to our new wrapper
+ */
+ if (blockTyped) {
+
+ /**
+ * If we had splitted inline nodes to paragraph before
+ */
+ if (paragraph.childNodes.length) {
+
+ newWrapper.appendChild(paragraph.cloneNode(true));
+
+ /** empty paragraph */
+ paragraph = null;
+ paragraph = document.createElement('P');
+ }
+
+ newWrapper.appendChild(node.cloneNode(true));
+ } else {
+
+ /** Collect all inline nodes to one as paragraph */
+ paragraph.appendChild(node.cloneNode(true));
+
+ /** if node is last we should append this node to paragraph and paragraph to new wrapper */
+ if (i == wrapper.childNodes.length - 1) {
+
+ newWrapper.appendChild(paragraph.cloneNode(true));
+ }
+ }
+ }
+
+ return newWrapper.innerHTML;
+ };
+
+ /**
+ * Splits strings on new line and wraps paragraphs with
tag
+ * @param plainText
+ * @returns {string}
+ */
+ var wrapPlainTextWithParagraphs = function wrapPlainTextWithParagraphs(plainText) {
+
+ if (!plainText) return '';
+
+ return '
tags to split it logically
+ * @type {string}
+ */
+ wrappedData = editor.content.wrapTextWithParagraphs(cleanData, plainData);
+ paragraphs.innerHTML = wrappedData;
+
+ /**
+ * If there only one paragraph, just insert in at the caret location
+ */
+ if (paragraphs.childNodes.length == 1) {
+
+ emulateUserAgentBehaviour(paragraphs.firstChild);
+ return;
+ }
+
+ insertPastedParagraphs(paragraphs.childNodes);
+ };
+
+ /**
+ * Checks if we should handle paste event on block
+ * @param block
+ *
+ * @return {boolean}
+ */
+ var needsToHandlePasteEvent = function needsToHandlePasteEvent(block) {
+
+ /** If area is input or textarea then allow default behaviour */
+ if (editor.core.isNativeInput(block)) {
+
+ return false;
+ }
+
+ var editableParent = editor.content.getEditableParent(block);
+
+ /** Allow paste when event target placed in Editable element */
+ if (!editableParent) {
+
+ return false;
+ }
+
+ return true;
+ };
+
+ /**
+ * Inserts new initial plugin blocks with data in paragraphs
+ *
+ * @param {Array} paragraphs - array of paragraphs (
...); if
+ // they are, we want to unwrap the inner block element.
+ var isNotTopContainer = !! parentNode.parentNode;
+ var isNestedBlockElement =
+ isBlockElement(parentNode) &&
+ isBlockElement(node) &&
+ isNotTopContainer;
+
+ var nodeName = node.nodeName.toLowerCase();
+
+ var allowedAttrs = getAllowedAttrs(this.config, nodeName, node);
+
+ var isInvalid = isInline && containsBlockElement;
+
+ // Drop tag entirely according to the whitelist *and* if the markup
+ // is invalid.
+ if (isInvalid || shouldRejectNode(node, allowedAttrs)
+ || (!this.config.keepNestedBlockElements && isNestedBlockElement)) {
+ // Do not keep the inner text of SCRIPT/STYLE elements.
+ if (! (node.nodeName === 'SCRIPT' || node.nodeName === 'STYLE')) {
+ while (node.childNodes.length > 0) {
+ parentNode.insertBefore(node.childNodes[0], node);
+ }
+ }
+ parentNode.removeChild(node);
+
+ this._sanitize(parentNode);
+ break;
+ }
+
+ // Sanitize attributes
+ for (var a = 0; a < node.attributes.length; a += 1) {
+ var attr = node.attributes[a];
+
+ if (shouldRejectAttr(attr, allowedAttrs, node)) {
+ node.removeAttribute(attr.name);
+ // Shift the array to continue looping.
+ a = a - 1;
+ }
+ }
+
+ // Sanitize children
+ this._sanitize(node);
+
+ // Mark node as sanitized so it's ignored in future runs
+ node._sanitized = true;
+ } while ((node = treeWalker.nextSibling()));
+ };
+
+ function createTreeWalker(node) {
+ return document.createTreeWalker(node,
+ NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT,
+ null, false);
+ }
+
+ function getAllowedAttrs(config, nodeName, node){
+ if (typeof config.tags[nodeName] === 'function') {
+ return config.tags[nodeName](node);
+ } else {
+ return config.tags[nodeName];
+ }
+ }
+
+ function shouldRejectNode(node, allowedAttrs){
+ if (typeof allowedAttrs === 'undefined') {
+ return true;
+ } else if (typeof allowedAttrs === 'boolean') {
+ return !allowedAttrs;
+ }
+
+ return false;
+ }
+
+ function shouldRejectAttr(attr, allowedAttrs, node){
+ var attrName = attr.name.toLowerCase();
+
+ if (allowedAttrs === true){
+ return false;
+ } else if (typeof allowedAttrs[attrName] === 'function'){
+ return !allowedAttrs[attrName](attr.value, node);
+ } else if (typeof allowedAttrs[attrName] === 'undefined'){
+ return true;
+ } else if (allowedAttrs[attrName] === false) {
+ return true;
+ } else if (typeof allowedAttrs[attrName] === 'string') {
+ return (allowedAttrs[attrName] !== attr.value);
+ }
+
+ return false;
+ }
+
+ return HTMLJanitor;
+
+ }));
+
+
+/***/ },
+/* 14 */
+/***/ function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * Codex Editor Saver
+ *
+ * @author Codex Team
+ * @version 1.1.0
+ */
+
+ module.exports = function (saver) {
+
+ var editor = codex.editor;
+
+ /**
+ * @public
+ * Save blocks
+ */
+ saver.save = function () {
+
+ /** Save html content of redactor to memory */
+ editor.state.html = editor.nodes.redactor.innerHTML;
+
+ /** Clean jsonOutput state */
+ editor.state.jsonOutput = [];
+
+ return saveBlocks(editor.nodes.redactor.childNodes);
+ };
+
+ /**
+ * @private
+ * Save each block data
+ *
+ * @param blocks
+ * @returns {Promise.}
+ */
+ var saveBlocks = function saveBlocks(blocks) {
+
+ var data = [];
+
+ for (var index = 0; index < blocks.length; index++) {
+
+ data.push(getBlockData(blocks[index]));
+ }
+
+ return Promise.all(data).then(makeOutput).catch(editor.core.log);
+ };
+
+ /** Save and validate block data */
+ var getBlockData = function getBlockData(block) {
+
+ return saveBlockData(block).then(validateBlockData).catch(editor.core.log);
+ };
+
+ /**
+ * @private
+ * Call block`s plugin save method and return saved data
+ *
+ * @param block
+ * @returns {Object}
+ */
+ var saveBlockData = function saveBlockData(block) {
+
+ var pluginName = block.dataset.tool;
+
+ /** Check for plugin existence */
+ if (!editor.tools[pluginName]) {
+
+ editor.core.log('Plugin \xAB' + pluginName + '\xBB not found', 'error');
+ return { data: null, pluginName: null };
+ }
+
+ /** Check for plugin having save method */
+ if (typeof editor.tools[pluginName].save !== 'function') {
+
+ editor.core.log('Plugin \xAB' + pluginName + '\xBB must have save method', 'error');
+ return { data: null, pluginName: null };
+ }
+
+ /** Result saver */
+ var blockContent = block.childNodes[0],
+ pluginsContent = blockContent.childNodes[0],
+ position = pluginsContent.dataset.inputPosition;
+
+ /** If plugin wasn't available then return data from cache */
+ if (editor.tools[pluginName].available === false) {
+
+ return Promise.resolve({ data: codex.editor.state.blocks.items[position].data, pluginName: pluginName });
+ }
+
+ return Promise.resolve(pluginsContent).then(editor.tools[pluginName].save).then(function (data) {
+ return Object({ data: data, pluginName: pluginName });
+ });
+ };
+
+ /**
+ * Call plugin`s validate method. Return false if validation failed
+ *
+ * @param data
+ * @param pluginName
+ * @returns {Object|Boolean}
+ */
+ var validateBlockData = function validateBlockData(_ref) {
+ var data = _ref.data,
+ pluginName = _ref.pluginName;
+
+
+ if (!data || !pluginName) {
+
+ return false;
+ }
+
+ if (editor.tools[pluginName].validate) {
+
+ var result = editor.tools[pluginName].validate(data);
+
+ /**
+ * Do not allow invalid data
+ */
+ if (!result) {
+
+ return false;
+ }
+ }
+
+ return { data: data, pluginName: pluginName };
+ };
+
+ /**
+ * Compile article output
+ *
+ * @param savedData
+ * @returns {{time: number, version, items: (*|Array)}}
+ */
+ var makeOutput = function makeOutput(savedData) {
+
+ savedData = savedData.filter(function (blockData) {
+ return blockData;
+ });
+
+ var items = savedData.map(function (blockData) {
+ return Object({ type: blockData.pluginName, data: blockData.data });
+ });
+
+ editor.state.jsonOutput = items;
+
+ return {
+ id: editor.state.blocks.id || null,
+ time: +new Date(),
+ version: editor.version,
+ items: items
+ };
+ };
+
+ return saver;
+ }({});
+
+/***/ },
+/* 15 */
+/***/ function(module, exports) {
+
+ 'use strict';
+
+ /**
+ *
+ * Codex.Editor Transport Module
+ *
+ * @copyright 2017 Codex-Team
+ * @version 1.2.0
+ */
+
+ module.exports = function (transport) {
+
+ var editor = codex.editor;
+
+ /**
+ * @private {Object} current XmlHttpRequest instance
+ */
+ var currentRequest = null;
+
+ /**
+ * @type {null} | {DOMElement} input - keeps input element in memory
+ */
+ transport.input = null;
+
+ /**
+ * @property {Object} arguments - keep plugin settings and defined callbacks
+ */
+ transport.arguments = null;
+
+ /**
+ * Prepares input element where will be files
+ */
+ transport.prepare = function () {
+
+ var input = editor.draw.node('INPUT', '', { type: 'file' });
+
+ editor.listeners.add(input, 'change', editor.transport.fileSelected);
+ editor.transport.input = input;
+ };
+
+ /** Clear input when files is uploaded */
+ transport.clearInput = function () {
+
+ /** Remove old input */
+ transport.input = null;
+
+ /** Prepare new one */
+ transport.prepare();
+ };
+
+ /**
+ * Callback for file selection
+ * @param {Event} event
+ */
+ transport.fileSelected = function () {
+
+ var input = this,
+ i,
+ files = input.files,
+ formData = new FormData();
+
+ if (editor.transport.arguments.multiple === true) {
+
+ for (i = 0; i < files.length; i++) {
+
+ formData.append('files[]', files[i], files[i].name);
+ }
+ } else {
+
+ formData.append('files', files[0], files[0].name);
+ }
+
+ currentRequest = editor.core.ajax({
+ type: 'POST',
+ data: formData,
+ url: editor.transport.arguments.url,
+ beforeSend: editor.transport.arguments.beforeSend,
+ success: editor.transport.arguments.success,
+ error: editor.transport.arguments.error,
+ progress: editor.transport.arguments.progress
+ });
+
+ /** Clear input */
+ transport.clearInput();
+ };
+
+ /**
+ * Use plugin callbacks
+ * @protected
+ *
+ * @param {Object} args - can have :
+ * @param {String} args.url - fetch URL
+ * @param {Function} args.beforeSend - function calls before sending ajax
+ * @param {Function} args.success - success callback
+ * @param {Function} args.error - on error handler
+ * @param {Function} args.progress - xhr onprogress handler
+ * @param {Boolean} args.multiple - allow select several files
+ * @param {String} args.accept - adds accept attribute
+ */
+ transport.selectAndUpload = function (args) {
+
+ transport.arguments = args;
+
+ if (args.multiple === true) {
+
+ transport.input.setAttribute('multiple', 'multiple');
+ }
+
+ if (args.accept) {
+
+ transport.input.setAttribute('accept', args.accept);
+ }
+
+ transport.input.click();
+ };
+
+ transport.abort = function () {
+
+ currentRequest.abort();
+
+ currentRequest = null;
+ };
+
+ return transport;
+ }({});
+
+/***/ },
+/* 16 */
+/***/ 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 Events() {
+ _classCallCheck(this, Events);
+
+ this.subscribers = {};
+ }
+
+ _createClass(Events, [{
+ key: "on",
+ value: function on(eventName, callback) {
+
+ if (!(eventName in this.subscribers)) {
+
+ this.subscribers[eventName] = [];
}
- return XMLHTTP;
+ // group by events
+ this.subscribers[eventName].push(callback);
}
}, {
- key: 'state',
- set: function set(Editor) {
+ key: "emit",
+ value: function emit(eventName, data) {
- this.Editor = Editor;
+ this.subscribers[eventName].reduce(function (previousData, currentHandler) {
+
+ var newData = currentHandler(previousData);
+
+ return newData ? newData : previousData;
+ }, data);
}
}]);
- return Core;
+ return Events;
}();
- // module.exports = (function (core) {
+
+/***/ },
+/* 17 */
+/***/ function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * Inline toolbar
+ *
+ * Contains from tools:
+ * Bold, Italic, Underline and Anchor
+ *
+ * @author Codex Team
+ * @version 1.0
+ */
+
+ module.exports = function (inline) {
+
+ var editor = codex.editor;
+
+ inline.buttonsOpened = null;
+ inline.actionsOpened = null;
+ inline.wrappersOffset = null;
+
+ /**
+ * saving selection that need for execCommand for styling
+ *
+ */
+ inline.storedSelection = null;
+
+ /**
+ * @protected
+ *
+ * Open inline toobar
+ */
+ inline.show = function () {
+
+ var currentNode = editor.content.currentNode,
+ tool = currentNode.dataset.tool,
+ plugin;
+
+ /**
+ * tool allowed to open inline toolbar
+ */
+ plugin = editor.tools[tool];
+
+ if (!plugin.showInlineToolbar) return;
+
+ var selectedText = inline.getSelectionText(),
+ toolbar = editor.nodes.inlineToolbar.wrapper;
+
+ if (selectedText.length > 0) {
+
+ /** Move toolbar and open */
+ editor.toolbar.inline.move();
+
+ /** Open inline toolbar */
+ toolbar.classList.add('opened');
+
+ /** show buttons of inline toolbar */
+ editor.toolbar.inline.showButtons();
+ }
+ };
+
+ /**
+ * @protected
+ *
+ * Closes inline toolbar
+ */
+ inline.close = function () {
+
+ var toolbar = editor.nodes.inlineToolbar.wrapper;
+
+ toolbar.classList.remove('opened');
+ };
+
+ /**
+ * @private
+ *
+ * Moving toolbar
+ */
+ inline.move = function () {
+
+ if (!this.wrappersOffset) {
+
+ this.wrappersOffset = this.getWrappersOffset();
+ }
+
+ var coords = this.getSelectionCoords(),
+ defaultOffset = 0,
+ toolbar = editor.nodes.inlineToolbar.wrapper,
+ newCoordinateX,
+ newCoordinateY;
+
+ if (toolbar.offsetHeight === 0) {
+
+ defaultOffset = 40;
+ }
+
+ newCoordinateX = coords.x - this.wrappersOffset.left;
+ newCoordinateY = coords.y + window.scrollY - this.wrappersOffset.top - defaultOffset - toolbar.offsetHeight;
+
+ toolbar.style.transform = 'translate3D(' + Math.floor(newCoordinateX) + 'px, ' + Math.floor(newCoordinateY) + 'px, 0)';
+
+ /** Close everything */
+ editor.toolbar.inline.closeButtons();
+ editor.toolbar.inline.closeAction();
+ };
+
+ /**
+ * @private
+ *
+ * Tool Clicked
+ */
+
+ inline.toolClicked = function (event, type) {
+
+ /**
+ * For simple tools we use default browser function
+ * For more complicated tools, we should write our own behavior
+ */
+ switch (type) {
+ case 'createLink':
+ editor.toolbar.inline.createLinkAction(event, type);break;
+ default:
+ editor.toolbar.inline.defaultToolAction(type);break;
+ }
+
+ /**
+ * highlight buttons
+ * after making some action
+ */
+ editor.nodes.inlineToolbar.buttons.childNodes.forEach(editor.toolbar.inline.hightlight);
+ };
+
+ /**
+ * @private
+ *
+ * Saving wrappers offset in DOM
+ */
+ inline.getWrappersOffset = function () {
+
+ var wrapper = editor.nodes.wrapper,
+ offset = this.getOffset(wrapper);
+
+ this.wrappersOffset = offset;
+ return offset;
+ };
+
+ /**
+ * @private
+ *
+ * Calculates offset of DOM element
+ *
+ * @param el
+ * @returns {{top: number, left: number}}
+ */
+ inline.getOffset = function (el) {
+
+ var _x = 0;
+ var _y = 0;
+
+ while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
+
+ _x += el.offsetLeft + el.clientLeft;
+ _y += el.offsetTop + el.clientTop;
+ el = el.offsetParent;
+ }
+ return { top: _y, left: _x };
+ };
+
+ /**
+ * @private
+ *
+ * Calculates position of selected text
+ * @returns {{x: number, y: number}}
+ */
+ inline.getSelectionCoords = function () {
+
+ var sel = document.selection,
+ range;
+ var x = 0,
+ y = 0;
+
+ if (sel) {
+
+ if (sel.type != 'Control') {
+
+ range = sel.createRange();
+ range.collapse(true);
+ x = range.boundingLeft;
+ y = range.boundingTop;
+ }
+ } else if (window.getSelection) {
+
+ sel = window.getSelection();
+
+ if (sel.rangeCount) {
+
+ range = sel.getRangeAt(0).cloneRange();
+ if (range.getClientRects) {
+
+ range.collapse(true);
+ var rect = range.getClientRects()[0];
+
+ if (!rect) {
+
+ return;
+ }
+
+ x = rect.left;
+ y = rect.top;
+ }
+ }
+ }
+ return { x: x, y: y };
+ };
+
+ /**
+ * @private
+ *
+ * Returns selected text as String
+ * @returns {string}
+ */
+ inline.getSelectionText = function () {
+
+ var selectedText = '';
+
+ // all modern browsers and IE9+
+ if (window.getSelection) {
+
+ selectedText = window.getSelection().toString();
+ }
+
+ return selectedText;
+ };
+
+ /** Opens buttons block */
+ inline.showButtons = function () {
+
+ var buttons = editor.nodes.inlineToolbar.buttons;
+
+ buttons.classList.add('opened');
+
+ editor.toolbar.inline.buttonsOpened = true;
+
+ /** highlight buttons */
+ editor.nodes.inlineToolbar.buttons.childNodes.forEach(editor.toolbar.inline.hightlight);
+ };
+
+ /** Makes buttons disappear */
+ inline.closeButtons = function () {
+
+ var buttons = editor.nodes.inlineToolbar.buttons;
+
+ buttons.classList.remove('opened');
+
+ editor.toolbar.inline.buttonsOpened = false;
+ };
+
+ /** Open buttons defined action if exist */
+ inline.showActions = function () {
+
+ var action = editor.nodes.inlineToolbar.actions;
+
+ action.classList.add('opened');
+
+ editor.toolbar.inline.actionsOpened = true;
+ };
+
+ /** Close actions block */
+ inline.closeAction = function () {
+
+ var action = editor.nodes.inlineToolbar.actions;
+
+ action.innerHTML = '';
+ action.classList.remove('opened');
+ editor.toolbar.inline.actionsOpened = false;
+ };
+
+ /**
+ * Callback for keydowns in inline toolbar "Insert link..." input
+ */
+ var inlineToolbarAnchorInputKeydown_ = function inlineToolbarAnchorInputKeydown_(event) {
+
+ if (event.keyCode != editor.core.keys.ENTER) {
+
+ return;
+ }
+
+ var editable = editor.content.currentNode,
+ storedSelection = editor.toolbar.inline.storedSelection;
+
+ editor.toolbar.inline.restoreSelection(editable, storedSelection);
+ editor.toolbar.inline.setAnchor(this.value);
+
+ /**
+ * Preventing events that will be able to happen
+ */
+ event.preventDefault();
+ event.stopImmediatePropagation();
+
+ editor.toolbar.inline.clearRange();
+ };
+
+ /** Action for link creation or for setting anchor */
+ inline.createLinkAction = function (event) {
+
+ var isActive = this.isLinkActive();
+
+ var editable = editor.content.currentNode,
+ storedSelection = editor.toolbar.inline.saveSelection(editable);
+
+ /** Save globally selection */
+ editor.toolbar.inline.storedSelection = storedSelection;
+
+ if (isActive) {
+
+ /**
+ * Changing stored selection. if we want to remove anchor from word
+ * we should remove anchor from whole word, not only selected part.
+ * The solution is than we get the length of current link
+ * Change start position to - end of selection minus length of anchor
+ */
+ editor.toolbar.inline.restoreSelection(editable, storedSelection);
+
+ editor.toolbar.inline.defaultToolAction('unlink');
+ } else {
+
+ /** Create input and close buttons */
+ var action = editor.draw.inputForLink();
+
+ editor.nodes.inlineToolbar.actions.appendChild(action);
+
+ editor.toolbar.inline.closeButtons();
+ editor.toolbar.inline.showActions();
+
+ /**
+ * focus to input
+ * Solution: https://developer.mozilla.org/ru/docs/Web/API/HTMLElement/focus
+ * Prevents event after showing input and when we need to focus an input which is in unexisted form
+ */
+ action.focus();
+ event.preventDefault();
+
+ /** Callback to link action */
+ editor.listeners.add(action, 'keydown', inlineToolbarAnchorInputKeydown_, false);
+ }
+ };
+
+ inline.isLinkActive = function () {
+
+ var isActive = false;
+
+ editor.nodes.inlineToolbar.buttons.childNodes.forEach(function (tool) {
+
+ var dataType = tool.dataset.type;
+
+ if (dataType == 'link' && tool.classList.contains('hightlighted')) {
+
+ isActive = true;
+ }
+ });
+
+ return isActive;
+ };
+
+ /** default action behavior of tool */
+ inline.defaultToolAction = function (type) {
+
+ document.execCommand(type, false, null);
+ };
+
+ /**
+ * @private
+ *
+ * Sets URL
+ *
+ * @param {String} url - URL
+ */
+ inline.setAnchor = function (url) {
+
+ document.execCommand('createLink', false, url);
+
+ /** Close after URL inserting */
+ editor.toolbar.inline.closeAction();
+ };
+
+ /**
+ * @private
+ *
+ * Saves selection
+ */
+ inline.saveSelection = function (containerEl) {
+
+ var range = window.getSelection().getRangeAt(0),
+ preSelectionRange = range.cloneRange(),
+ start;
+
+ preSelectionRange.selectNodeContents(containerEl);
+ preSelectionRange.setEnd(range.startContainer, range.startOffset);
+
+ start = preSelectionRange.toString().length;
+
+ return {
+ start: start,
+ end: start + range.toString().length
+ };
+ };
+
+ /**
+ * @private
+ *
+ * Sets to previous selection (Range)
+ *
+ * @param {Element} containerEl - editable element where we restore range
+ * @param {Object} savedSel - range basic information to restore
+ */
+ inline.restoreSelection = function (containerEl, savedSel) {
+
+ var range = document.createRange(),
+ charIndex = 0;
+
+ range.setStart(containerEl, 0);
+ range.collapse(true);
+
+ var nodeStack = [containerEl],
+ node,
+ foundStart = false,
+ stop = false,
+ nextCharIndex;
+
+ while (!stop && (node = nodeStack.pop())) {
+
+ if (node.nodeType == 3) {
+
+ nextCharIndex = charIndex + node.length;
+
+ if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
+
+ range.setStart(node, savedSel.start - charIndex);
+ foundStart = true;
+ }
+ if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
+
+ range.setEnd(node, savedSel.end - charIndex);
+ stop = true;
+ }
+ charIndex = nextCharIndex;
+ } else {
+
+ var i = node.childNodes.length;
+
+ while (i--) {
+
+ nodeStack.push(node.childNodes[i]);
+ }
+ }
+ }
+
+ var sel = window.getSelection();
+
+ sel.removeAllRanges();
+ sel.addRange(range);
+ };
+
+ /**
+ * @private
+ *
+ * Removes all ranges from window selection
+ */
+ inline.clearRange = function () {
+
+ var selection = window.getSelection();
+
+ selection.removeAllRanges();
+ };
+
+ /**
+ * @private
+ *
+ * sets or removes hightlight
+ */
+ inline.hightlight = function (tool) {
+
+ var dataType = tool.dataset.type;
+
+ if (document.queryCommandState(dataType)) {
+
+ editor.toolbar.inline.setButtonHighlighted(tool);
+ } else {
+
+ editor.toolbar.inline.removeButtonsHighLight(tool);
+ }
+
+ /**
+ *
+ * hightlight for anchors
+ */
+ var selection = window.getSelection(),
+ tag = selection.anchorNode.parentNode;
+
+ if (tag.tagName == 'A' && dataType == 'link') {
+
+ editor.toolbar.inline.setButtonHighlighted(tool);
+ }
+ };
+
+ /**
+ * @private
+ *
+ * Mark button if text is already executed
+ */
+ inline.setButtonHighlighted = function (button) {
+
+ button.classList.add('hightlighted');
+
+ /** At link tool we also change icon */
+ if (button.dataset.type == 'link') {
+
+ var icon = button.childNodes[0];
+
+ icon.classList.remove('ce-icon-link');
+ icon.classList.add('ce-icon-unlink');
+ }
+ };
+
+ /**
+ * @private
+ *
+ * Removes hightlight
+ */
+ inline.removeButtonsHighLight = function (button) {
+
+ button.classList.remove('hightlighted');
+
+ /** At link tool we also change icon */
+ if (button.dataset.type == 'link') {
+
+ var icon = button.childNodes[0];
+
+ icon.classList.remove('ce-icon-unlink');
+ icon.classList.add('ce-icon-link');
+ }
+ };
+
+ return inline;
+ }({});
+
+/***/ },
+/* 18 */
+/***/ function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * Toolbar settings
+ *
+ * @version 1.0.5
+ */
+
+ module.exports = function (settings) {
+
+ var editor = codex.editor;
+
+ settings.opened = false;
+
+ settings.setting = null;
+ settings.actions = null;
+
+ /**
+ * Append and open settings
+ */
+ settings.open = function (toolType) {
+
+ /**
+ * Append settings content
+ * It's stored in tool.settings
+ */
+ if (!editor.tools[toolType] || !editor.tools[toolType].makeSettings) {
+
+ return;
+ }
+
+ /**
+ * Draw settings block
+ */
+ var settingsBlock = editor.tools[toolType].makeSettings();
+
+ editor.nodes.pluginSettings.appendChild(settingsBlock);
+
+ /** Open settings block */
+ editor.nodes.blockSettings.classList.add('opened');
+ this.opened = true;
+ };
+
+ /**
+ * Close and clear settings
+ */
+ settings.close = function () {
+
+ editor.nodes.blockSettings.classList.remove('opened');
+ editor.nodes.pluginSettings.innerHTML = '';
+
+ this.opened = false;
+ };
+
+ /**
+ * @param {string} toolType - plugin type
+ */
+ settings.toggle = function (toolType) {
+
+ if (!this.opened) {
+
+ this.open(toolType);
+ } else {
+
+ this.close();
+ }
+ };
+
+ /**
+ * Here we will draw buttons and add listeners to components
+ */
+ settings.makeRemoveBlockButton = function () {
+
+ var removeBlockWrapper = editor.draw.node('SPAN', 'ce-toolbar__remove-btn', {}),
+ settingButton = editor.draw.node('SPAN', 'ce-toolbar__remove-setting', { innerHTML: '' }),
+ actionWrapper = editor.draw.node('DIV', 'ce-toolbar__remove-confirmation', {}),
+ confirmAction = editor.draw.node('DIV', 'ce-toolbar__remove-confirm', { textContent: 'Удалить блок' }),
+ cancelAction = editor.draw.node('DIV', 'ce-toolbar__remove-cancel', { textContent: 'Отмена' });
+
+ editor.listeners.add(settingButton, 'click', editor.toolbar.settings.removeButtonClicked, false);
+
+ editor.listeners.add(confirmAction, 'click', editor.toolbar.settings.confirmRemovingRequest, false);
+
+ editor.listeners.add(cancelAction, 'click', editor.toolbar.settings.cancelRemovingRequest, false);
+
+ actionWrapper.appendChild(confirmAction);
+ actionWrapper.appendChild(cancelAction);
+
+ removeBlockWrapper.appendChild(settingButton);
+ removeBlockWrapper.appendChild(actionWrapper);
+
+ /** Save setting */
+ editor.toolbar.settings.setting = settingButton;
+ editor.toolbar.settings.actions = actionWrapper;
+
+ return removeBlockWrapper;
+ };
+
+ settings.removeButtonClicked = function () {
+
+ var action = editor.toolbar.settings.actions;
+
+ if (action.classList.contains('opened')) {
+
+ editor.toolbar.settings.hideRemoveActions();
+ } else {
+
+ editor.toolbar.settings.showRemoveActions();
+ }
+
+ editor.toolbar.toolbox.close();
+ editor.toolbar.settings.close();
+ };
+
+ settings.cancelRemovingRequest = function () {
+
+ editor.toolbar.settings.actions.classList.remove('opened');
+ };
+
+ settings.confirmRemovingRequest = function () {
+
+ var currentBlock = editor.content.currentNode,
+ firstLevelBlocksCount;
+
+ currentBlock.remove();
+
+ firstLevelBlocksCount = editor.nodes.redactor.childNodes.length;
+
+ /**
+ * If all blocks are removed
+ */
+ if (firstLevelBlocksCount === 0) {
+
+ /** update currentNode variable */
+ editor.content.currentNode = null;
+
+ /** Inserting new empty initial block */
+ editor.ui.addInitialBlock();
+ }
+
+ editor.ui.saveInputs();
+
+ editor.toolbar.close();
+ };
+
+ settings.showRemoveActions = function () {
+
+ editor.toolbar.settings.actions.classList.add('opened');
+ };
+
+ settings.hideRemoveActions = function () {
+
+ editor.toolbar.settings.actions.classList.remove('opened');
+ };
+
+ return settings;
+ }({});
+
+/***/ },
+/* 19 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ /**
+ * Codex Editor toolbar module
+ *
+ * Contains:
+ * - Inline toolbox
+ * - Toolbox within plus button
+ * - Settings section
+ *
+ * @author Codex Team
+ * @version 1.0
+ */
+
+ module.exports = function (toolbar) {
+
+ var editor = codex.editor;
+
+ toolbar.settings = __webpack_require__(18);
+ toolbar.inline = __webpack_require__(17);
+ toolbar.toolbox = __webpack_require__(20);
+
+ /**
+ * Margin between focused node and toolbar
+ */
+ toolbar.defaultToolbarHeight = 49;
+
+ toolbar.defaultOffset = 34;
+
+ toolbar.opened = false;
+
+ toolbar.current = null;
+
+ /**
+ * @protected
+ */
+ toolbar.open = function () {
+
+ if (editor.hideToolbar) {
+
+ return;
+ }
+
+ var toolType = editor.content.currentNode.dataset.tool;
+
+ if (!editor.tools[toolType] || !editor.tools[toolType].makeSettings) {
+
+ editor.nodes.showSettingsButton.classList.add('hide');
+ } else {
+
+ editor.nodes.showSettingsButton.classList.remove('hide');
+ }
+
+ editor.nodes.toolbar.classList.add('opened');
+ this.opened = true;
+ };
+
+ /**
+ * @protected
+ */
+ toolbar.close = function () {
+
+ editor.nodes.toolbar.classList.remove('opened');
+
+ toolbar.opened = false;
+ toolbar.current = null;
+
+ for (var button in editor.nodes.toolbarButtons) {
+
+ editor.nodes.toolbarButtons[button].classList.remove('selected');
+ }
+
+ /** Close toolbox when toolbar is not displayed */
+ editor.toolbar.toolbox.close();
+ editor.toolbar.settings.close();
+ };
+
+ toolbar.toggle = function () {
+
+ if (!this.opened) {
+
+ this.open();
+ } else {
+
+ this.close();
+ }
+ };
+
+ toolbar.hidePlusButton = function () {
+
+ editor.nodes.plusButton.classList.add('hide');
+ };
+
+ toolbar.showPlusButton = function () {
+
+ editor.nodes.plusButton.classList.remove('hide');
+ };
+
+ /**
+ * Moving toolbar to the specified node
+ */
+ toolbar.move = function () {
+
+ /** Close Toolbox when we move toolbar */
+ editor.toolbar.toolbox.close();
+
+ if (!editor.content.currentNode) {
+
+ return;
+ }
+
+ var newYCoordinate = editor.content.currentNode.offsetTop - editor.toolbar.defaultToolbarHeight / 2 + editor.toolbar.defaultOffset;
+
+ editor.nodes.toolbar.style.transform = 'translate3D(0, ' + Math.floor(newYCoordinate) + 'px, 0)';
+
+ /** Close trash actions */
+ editor.toolbar.settings.hideRemoveActions();
+ };
+
+ return toolbar;
+ }({});
+
+/***/ },
+/* 20 */
+/***/ function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * Codex Editor toolbox
+ *
+ * All tools be able to appended here
+ *
+ * @author Codex Team
+ * @version 1.0
+ */
+
+ module.exports = function (toolbox) {
+
+ var editor = codex.editor;
+
+ toolbox.opened = false;
+ toolbox.openedOnBlock = null;
+
+ /** Shows toolbox */
+ toolbox.open = function () {
+
+ /** Close setting if toolbox is opened */
+ if (editor.toolbar.settings.opened) {
+
+ editor.toolbar.settings.close();
+ }
+
+ /** Add 'toolbar-opened' class for current block **/
+ toolbox.openedOnBlock = editor.content.currentNode;
+ toolbox.openedOnBlock.classList.add('toolbar-opened');
+
+ /** display toolbox */
+ editor.nodes.toolbox.classList.add('opened');
+
+ /** Animate plus button */
+ editor.nodes.plusButton.classList.add('clicked');
+
+ /** toolbox state */
+ editor.toolbar.toolbox.opened = true;
+ };
+
+ /** Closes toolbox */
+ toolbox.close = function () {
+
+ /** Remove 'toolbar-opened' class from current block **/
+ if (toolbox.openedOnBlock) toolbox.openedOnBlock.classList.remove('toolbar-opened');
+ toolbox.openedOnBlock = null;
+
+ /** Makes toolbox disappear */
+ editor.nodes.toolbox.classList.remove('opened');
+
+ /** Rotate plus button */
+ editor.nodes.plusButton.classList.remove('clicked');
+
+ /** toolbox state */
+ editor.toolbar.toolbox.opened = false;
+
+ editor.toolbar.current = null;
+ };
+
+ toolbox.leaf = function () {
+
+ var currentTool = editor.toolbar.current,
+ tools = Object.keys(editor.tools),
+ barButtons = editor.nodes.toolbarButtons,
+ nextToolIndex = 0,
+ toolToSelect = void 0,
+ visibleTool = void 0,
+ tool = void 0;
+
+ if (!currentTool) {
+
+ /** Get first tool from object*/
+ for (tool in editor.tools) {
+
+ if (editor.tools[tool].displayInToolbox) {
+
+ break;
+ }
+
+ nextToolIndex++;
+ }
+ } else {
+
+ nextToolIndex = (tools.indexOf(currentTool) + 1) % tools.length;
+ visibleTool = tools[nextToolIndex];
+
+ while (!editor.tools[visibleTool].displayInToolbox) {
+
+ nextToolIndex = (nextToolIndex + 1) % tools.length;
+ visibleTool = tools[nextToolIndex];
+ }
+ }
+
+ toolToSelect = tools[nextToolIndex];
+
+ for (var button in barButtons) {
+
+ barButtons[button].classList.remove('selected');
+ }
+
+ barButtons[toolToSelect].classList.add('selected');
+ editor.toolbar.current = toolToSelect;
+ };
+
+ /**
+ * Transforming selected node type into selected toolbar element type
+ * @param {event} event
+ */
+ toolbox.toolClicked = function (event) {
+
+ /**
+ * UNREPLACEBLE_TOOLS this types of tools are forbidden to replace even they are empty
+ */
+ var UNREPLACEBLE_TOOLS = ['image', 'link', 'list', 'instagram', 'twitter', 'embed'],
+ tool = editor.tools[editor.toolbar.current],
+ workingNode = editor.content.currentNode,
+ currentInputIndex = editor.caret.inputIndex,
+ newBlockContent,
+ appendCallback,
+ blockData;
+
+ /** Make block from plugin */
+ newBlockContent = tool.render();
+
+ /** information about block */
+ blockData = {
+ block: newBlockContent,
+ type: tool.type,
+ stretched: false
+ };
+
+ if (workingNode && UNREPLACEBLE_TOOLS.indexOf(workingNode.dataset.tool) === -1 && workingNode.textContent.trim() === '') {
+
+ /** Replace current block */
+ editor.content.switchBlock(workingNode, newBlockContent, tool.type);
+ } else {
+
+ /** Insert new Block from plugin */
+ editor.content.insertBlock(blockData);
+
+ /** increase input index */
+ currentInputIndex++;
+ }
+
+ /** Fire tool append callback */
+ appendCallback = tool.appendCallback;
+
+ if (appendCallback && typeof appendCallback == 'function') {
+
+ appendCallback.call(event);
+ }
+
+ window.setTimeout(function () {
+
+ /** Set caret to current block */
+ editor.caret.setToBlock(currentInputIndex);
+ }, 10);
+
+ /**
+ * Changing current Node
+ */
+ editor.content.workingNodeChanged();
+
+ /**
+ * Move toolbar when node is changed
+ */
+ editor.toolbar.move();
+ };
+
+ return toolbox;
+ }({});
+
+/***/ },
+/* 21 */
+/***/ 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 Tools() {
+ _classCallCheck(this, Tools);
+ }
+
+ _createClass(Tools, [{
+ key: "prepare",
+ value: function prepare() {}
+ }]);
+
+ return Tools;
+ }();
+ // /**
+ // * Module working with plugins
+ // */
+ // module.exports = (function () {
//
// let editor = codex.editor;
//
- //
// /**
- // * @protected
- // *
- // * Helper for insert one element after another
+ // * Initialize plugins before using
+ // * Ex. Load scripts or call some internal methods
+ // * @return Promise
// */
- // core.insertAfter = function (target, element) {
+ // function prepare() {
//
- // target.parentNode.insertBefore(element, target.nextSibling);
+ // return new Promise(function (resolve_, reject_) {
//
- // };
+ // Promise.resolve()
//
- // /**
- // * @const
- // *
- // * Readable DOM-node types map
- // */
- // core.nodeTypes = {
- // TAG : 1,
- // TEXT : 3,
- // COMMENT : 8,
- // DOCUMENT_FRAGMENT: 11
- // };
+ // /**
+ // * Compose a sequence of plugins that requires preparation
+ // */
+ // .then(function () {
//
- // /**
- // * @const
- // * Readable keys map
- // */
- // 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 };
+ // let pluginsRequiresPreparation = [],
+ // allPlugins = editor.tools;
//
- // /**
- // * @protected
- // *
- // * Check object for DOM node
- // */
- // core.isDomNode = function (el) {
+ // for ( let pluginName in allPlugins ) {
//
- // return el && typeof el === 'object' && el.nodeType && el.nodeType == this.nodeTypes.TAG;
+ // let plugin = allPlugins[pluginName];
//
- // };
+ // if (plugin.prepare && typeof plugin.prepare != 'function' || !plugin.prepare) {
//
- // /**
- // * Checks passed object for emptiness
- // * @require ES5 - Object.keys
- // * @param {object}
- // */
- // core.isEmpty = function ( obj ) {
+ // continue;
//
- // return Object.keys(obj).length === 0;
+ // }
//
- // };
+ // pluginsRequiresPreparation.push(plugin);
//
- // /**
- // * Appends script to head of document
- // * @return Promise
- // */
- // core.importScript = function (scriptPath, instanceName) {
+ // }
//
- // return new Promise(function (resolve, reject) {
+ // /**
+ // * If no one passed plugins requires preparation, finish prepare() and go ahead
+ // */
+ // if (!pluginsRequiresPreparation.length) {
//
- // let script;
+ // resolve_();
//
- // /** Script is already loaded */
- // if ( !instanceName ) {
+ // }
//
- // reject('Instance name is missed');
+ // return pluginsRequiresPreparation;
//
- // } else if ( document.getElementById(editor.scriptPrefix + instanceName) ) {
+ // })
//
- // resolve(scriptPath);
+ // /** Wait plugins while they prepares */
+ // .then(waitAllPluginsPreparation_)
//
- // }
+ // .then(function () {
//
- // script = document.createElement('SCRIPT');
- // script.async = true;
- // script.defer = true;
- // script.id = editor.scriptPrefix + instanceName;
+ // editor.core.log('Plugins loaded', 'info');
+ // resolve_();
//
- // script.onload = function () {
+ // }).catch(function (error) {
//
- // resolve(scriptPath);
+ // reject_(error);
//
- // };
- //
- // script.onerror = function () {
- //
- // reject(scriptPath);
- //
- // };
- //
- // script.src = scriptPath;
- // document.head.appendChild(script);
+ // });
//
// });
//
- // };
+ // }
//
// /**
- // * Function for checking is it FormData object to send.
- // * @param {Object} object to check
- // * @return boolean
- // */
- // var isFormData_ = function (object) {
+ // * @param {array} plugins - list of tools that requires preparation
+ // * @return {Promise} resolved while all plugins will be ready or failed
+ // */
+ // function waitAllPluginsPreparation_(plugins) {
//
- // return object instanceof FormData;
+ // /**
+ // * @calls allPluginsProcessed__ when all plugins prepared or failed
+ // */
+ // return new Promise (function (allPluginsProcessed__) {
//
- // };
+ // /**
+ // * pluck each element from queue
+ // * First, send resolved Promise as previous value
+ // * Each plugins "prepare" method returns a Promise, that's why
+ // * reduce current element will not be able to continue while can't get
+ // * a resolved Promise
+ // *
+ // * If last plugin is "prepared" then go to the next stage of initialization
+ // */
+ // plugins.reduce(function (previousValue, plugin, iteration) {
//
- // /**
- // * Check block
- // * @param target
- // * @description Checks target is it native input
- // */
- // core.isNativeInput = function (target) {
+ // return previousValue.then(function () {
//
- // var nativeInputAreas = ['INPUT', 'TEXTAREA'];
+ // /**
+ // * Wait till plugins prepared
+ // * @calls pluginIsReady__ when plugin is ready or failed
+ // */
+ // return new Promise ( function (pluginIsReady__) {
//
- // return nativeInputAreas.indexOf(target.tagName) != -1;
+ // callPluginsPrepareMethod_( plugin )
//
- // };
+ // .then( pluginIsReady__ )
+ // .then( function () {
//
- // /**
- // * Check if block is empty
- // * We should check block textContent, child native inputs and some exceptions like IMG and IFRAME
- // *
- // * @param block
- // * @returns {boolean}
- // */
- // core.isBlockEmpty = function (block) {
+ // plugin.available = true;
//
- // const EXCEPTION_TAGS = ['IMG', 'IFRAME'];
+ // })
//
- // var nativeInputs = block.querySelectorAll('textarea, input'),
- // nativeInputsAreEmpty = true,
- // textContentIsEmpty = !block.textContent.trim();
+ // .catch(function (error) {
//
- // Array.prototype.forEach.call(nativeInputs, function (input) {
+ // editor.core.log(`Plugin «${plugin.type}» was not loaded. Preparation failed because %o`, 'warn', error);
+ // plugin.available = false;
+ // plugin.loadingMessage = error;
//
- // if (input.type == 'textarea' || input.type == 'text') {
+ // /** Go ahead even some plugin has problems */
+ // pluginIsReady__();
//
- // nativeInputsAreEmpty = nativeInputsAreEmpty && !input.value.trim();
+ // })
//
- // }
+ // .then(function () {
+ //
+ // /** If last plugin has problems then just ignore and continue */
+ // if (iteration == plugins.length - 1) {
+ //
+ // allPluginsProcessed__();
+ //
+ // }
+ //
+ // });
+ //
+ // });
+ //
+ // });
+ //
+ // }, Promise.resolve() );
//
// });
//
- // return textContentIsEmpty && nativeInputsAreEmpty && !EXCEPTION_TAGS.includes(block.tagName);
+ // }
+ //
+ // var callPluginsPrepareMethod_ = function (plugin) {
+ //
+ // return plugin.prepare( plugin.config || {} );
//
// };
//
+ // return {
+ // prepare: prepare
+ // };
//
- // return core;
- //
- // })({});
+ // }());
-/***/ }),
-/* 3 */
-/***/ (function(module, exports) {
+/***/ },
+/* 22 */
+/***/ function(module, exports) {
'use strict';
@@ -974,10 +5175,10 @@ var CodexEditor =
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
- * Module UI
- *
- * @type {UI}
- */
+ * Module UI
+ *
+ * @type {UI}
+ */
var className = {
/**
@@ -1011,6 +5212,19 @@ var CodexEditor =
editorZone: 'ce-redactor'
};
+ /**
+ * @class
+ *
+ * @classdesc Makes CodeX Editor UI:
+ *
+ *
+ *
+ *
+ *
+ *
+ * @property {EditorConfig} config - editor configuration {@link CodexEditor#configuration}
+ * @property {Object} Editor - available editor modules {@link CodexEditor#moduleInstances}
+ */
module.exports = function () {
_createClass(UI, null, [{
key: 'name',
@@ -1024,24 +5238,25 @@ var CodexEditor =
return 'ui';
}
+
+ /**
+ * @constructor
+ *
+ * @param {EditorConfig} config
+ */
+
}]);
- function UI(Editor) {
+ function UI(config) {
_classCallCheck(this, UI);
- this.wrapper = null;
-
- // this.Editor = Editor;
- //
- // this.modules = this.Editor.modules;
-
+ this.config = config;
+ this.Editor = null;
}
/**
- * @param Editor
- * @param Editor.modules {@link Tools#list}
- * @param Editor.config {@link CodexEditor#configuration}
- * @param Editor
+ * Editor modules setter
+ * @param {object} Editor - available editor modules
*/
@@ -1058,8 +5273,6 @@ var CodexEditor =
console.log('ui prepare fired');
- this.wrapper = document.createElement('div');
-
return;
return new Promise(function (resolve, reject) {
@@ -1468,6 +5681,6 @@ var CodexEditor =
//
// })({});
-/***/ })
+/***/ }
/******/ ]);
//# sourceMappingURL=codex-editor.js.map
\ No newline at end of file
diff --git a/build/codex-editor.js.map b/build/codex-editor.js.map
new file mode 100644
index 00000000..fa498d82
--- /dev/null
+++ b/build/codex-editor.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["webpack:///webpack/bootstrap f9fb2e3ee97ac7d4fd68","webpack:///./src/codex.js","webpack:///./src/components/modules ^\\.\\/.*$","webpack:///./src/components/modules/_anchors.js","webpack:///./src/components/modules/_callbacks.js","webpack:///./src/components/modules/_caret.js","webpack:///./src/components/modules/_content.js","webpack:///./src/components/modules/_destroyer.js","webpack:///./src/components/modules/_listeners.js","webpack:///./src/components/modules/_notifications.js","webpack:///./src/components/modules/_parser.js","webpack:///./src/components/modules/_paste.js","webpack:///./src/components/modules/_renderer.js","webpack:///./src/components/modules/_sanitizer.js","webpack:///./~/html-janitor/src/html-janitor.js","webpack:///./src/components/modules/_saver.js","webpack:///./src/components/modules/_transport.js","webpack:///./src/components/modules/eventDispatcher.js","webpack:///./src/components/modules/toolbar/inline.js","webpack:///./src/components/modules/toolbar/settings.js","webpack:///./src/components/modules/toolbar/toolbar.js","webpack:///./src/components/modules/toolbar/toolbox.js","webpack:///./src/components/modules/tools.js","webpack:///./src/components/modules/ui.js"],"names":["modules","editorModules","map","module","exports","config","moduleInstances","Promise","resolve","then","configuration","init","start","console","log","catch","error","constructModules","configureModules","forEach","Module","name","e","state","getModulesDiff","moduleName","prepareDecorator","prepare","holderId","placeholder","sanitizer","p","b","a","hideToolbar","anchors","editor","codex","input","currentNode","settingsOpened","currentBlock","value","dataset","anchor","anchorChanged","newAnchor","target","rusToTranslit","trim","classList","add","ui","className","BLOCK_WITH_ANCHOR","remove","keyDownOnAnchorInput","keyCode","core","keys","ENTER","preventDefault","stopPropagation","blur","toolbar","settings","close","keyUpOnAnchorInput","LEFT","DOWN","string","ru","en","i","length","split","join","toLowerCase","replace","callbacks","globalKeydown","event","enterKeyPressed_","redactorKeyDown","TAB","tabKeyPressedOnRedactorsZone_","enterKeyPressedOnRedactorsZone_","ESC","escapeKeyPressedOnRedactorsZone_","defaultKeyPressedOnRedactorsZone_","globalKeyup","UP","RIGHT","arrowKeyPressed_","isBlockEmpty","content","opened","open","toolbox","leaf","editorAreaHightlighted","caret","inputIndex","enterPressedOnBlock_","NEW_BLOCK_TYPE","initialBlockPlugin","insertBlock","type","block","tools","render","move","contentEditable","saveCurrentInputIndex","currentInputIndex","getCurrentInputIndex","workingNode","tool","isEnterPressedOnToolbar","current","inputs","enableLineBreaks","toolClicked","stopImmediatePropagation","shiftKey","currentSelection","window","getSelection","currentSelectedNode","anchorNode","caretAtTheEndOfText","position","atTheEnd","isTextNodeHasParentBetweenContenteditable","callback","enterPressedOnBlock","parentNode","nodeType","nodeTypes","TEXT","splitBlock","textContent","showPlusButton","islastNode","isLastNode","saveInputs","workingNodeChanged","inline","actionsOpened","clearMark","redactorClicked","detectWhenClickedOnFirstLevelBlockArea_","selectedText","getSelectionText","firstLevelBlock","indexOfLastInput","getFirstLevelBlock","setToBlock","setToNextBlock","inputIsEmpty","currentNodeType","isInitialType","hidePlusButton","markBlock","selection","flag","rangeCount","isDomNode","document","body","toolbarButtonClicked","button","plusButtonClicked","nodes","contains","blockKeydown","blockRightOrDownArrowPressed_","BACKSPACE","backspacePressed_","blockLeftOrUpArrowPressed_","focusedNode","focusedNodeHolder","editableElementIndex","caretInLastChild","lastChild","deepestTextnode","childNodes","getDeepestTextNodeFromPosition","anchorOffset","caretInFirstChild","caretAtTheBeginning","firstChild","setToPreviousBlock","range","selectionLength","firstLevelBlocksCount","isNativeInput","getRange","endOffset","startOffset","atStart","mergeBlocks","redactor","addInitialBlock","setTimeout","showSettingsButtonClicked","currentToolType","toggle","hideRemoveActions","offset","focusedNodeIndex","set","el","index","childs","nodeToSet","focus","createRange","setStart","setEnd","removeAllRanges","addRange","nextInput","emptyTextElement","createTextNode","appendChild","targetInput","previousInput","lastChildNode","lengthOfLastChildNode","pluginsRender","isFirstNode","isOffsetZero","insertNode","node","lastNode","DOCUMENT_FRAGMENT","getRangeAt","deleteContents","setStartAfter","collapse","sync","html","innerHTML","BLOCK_HIGHLIGHTED","BLOCK_CLASSNAME","targetNode","replaceBlock","targetBlock","newBlock","replaceChild","addBlockHandlers","blockData","needPlaceCaret","workingBlock","newBlockContent","blockType","isStretched","stretched","composeNewBlock_","insertAfter","editableElement","querySelector","emptyText","switchBlock","blockToReplace","newBlockComposed","blockChilds","text","removeChild","lookingFromStart","TAG","draw","blockContent","BLOCK_CONTENT","BLOCK_STRETCHED","anchorNodeText","caretOffset","textBeforeCaret","textNodeBeforeCaret","textAfterCaret","textNodeAfterCaret","substring","previousChilds","nextChilds","reachedCurrent","push","child","previousChildsLength","nextChildsLength","newNode","createElement","targetInputIndex","currentInputContent","allChecked","allSiblingsEmpty_","sibling","nextSibling","wrapTextWithParagraphs","htmlData","plainData","wrapPlainTextWithParagraphs","wrapper","newWrapper","paragraph","firstLevelBlocks","blockTyped","indexOf","tagName","cloneNode","plainText","getEditableParent","clear","all","blocks","items","load","articleData","currentContent","Object","assign","concat","renderer","makeBlocksFromData","destroyer","removeNodes","notifications","destroyPlugins","destroy","destroyScripts","scripts","getElementsByTagName","id","scriptPrefix","listeners","removeAll","plugins","allListeners","search","byElement","element","context","listenersOnElement","listener","byType","eventType","listenersWithType","byHandler","handler","listenersWithHandler","one","result","isCapture","addEventListener","data","alreadyAddedListener","removeEventListener","existingListeners","splice","get","queue","addToQueue","createHolder","holder","errorThrown","errorMsg","notification","message","constructorSettings","cancel","confirm","inputField","confirmHandler","cancelHandler","create","time","okBtn","cancelBtn","okMsg","cancelMsg","send","parser","insertPastedContent","tag","isFirstLevelBlock","paste","patterns","renderOnPastePatterns","Array","isArray","pattern","pasted","clipBoardData","clipboardData","getData","analize","plugin","execArray","regex","exec","match","pasteToNewBlock_","blockPasteCallback","needsToHandlePasteEvent","paragraphs","cleanData","wrappedData","clean","emulateUserAgentBehaviour","insertPastedParagraphs","editableParent","childElementCount","createDocumentFragment","isEmpty","appendBlocks","nodeSequence","appendNodeAtIndex","getNodeAsync","createBlockFromData","blocksList","toolData","pluginName","Error","available","unavailableBlock","loadingMessage","inputPosition","janitor","require","Config","CUSTOM","BASIC","tags","href","rel","init_","userCustomConfig","dirtyString","customConfig","janitorInstance","saver","save","jsonOutput","saveBlocks","getBlockData","makeOutput","saveBlockData","validateBlockData","pluginsContent","validate","savedData","filter","Date","version","transport","currentRequest","arguments","fileSelected","clearInput","files","formData","FormData","multiple","append","ajax","url","beforeSend","success","progress","selectAndUpload","args","setAttribute","accept","click","abort","subscribers","eventName","reduce","previousData","currentHandler","newData","buttonsOpened","wrappersOffset","storedSelection","show","showInlineToolbar","inlineToolbar","showButtons","getWrappersOffset","coords","getSelectionCoords","defaultOffset","newCoordinateX","newCoordinateY","offsetHeight","x","left","y","scrollY","top","style","transform","Math","floor","closeButtons","closeAction","createLinkAction","defaultToolAction","buttons","hightlight","getOffset","_x","_y","isNaN","offsetLeft","offsetTop","clientLeft","clientTop","offsetParent","sel","boundingLeft","boundingTop","cloneRange","getClientRects","rect","toString","showActions","action","actions","inlineToolbarAnchorInputKeydown_","editable","restoreSelection","setAnchor","clearRange","isActive","isLinkActive","saveSelection","inputForLink","dataType","execCommand","containerEl","preSelectionRange","selectNodeContents","startContainer","end","savedSel","charIndex","nodeStack","foundStart","stop","nextCharIndex","pop","queryCommandState","setButtonHighlighted","removeButtonsHighLight","icon","setting","toolType","makeSettings","settingsBlock","pluginSettings","blockSettings","makeRemoveBlockButton","removeBlockWrapper","settingButton","actionWrapper","confirmAction","cancelAction","removeButtonClicked","confirmRemovingRequest","cancelRemovingRequest","showRemoveActions","defaultToolbarHeight","showSettingsButton","toolbarButtons","plusButton","newYCoordinate","openedOnBlock","currentTool","barButtons","nextToolIndex","toolToSelect","visibleTool","displayInToolbox","UNREPLACEBLE_TOOLS","appendCallback","call","SETTINGS_ITEM","CSS_","editorWrapper","editorZone","Editor","reject","dom","make","makeToolBar_","addTools_","makeInlineToolbar_","addInlineToolbarTools_","makeNotificationHolder_","bindEvents_"],"mappings":"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;AAEH;AAxEL;;AAAA;AAAA;;AAuLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;;;;;ACzWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kCAAiC,uDAAuD;AACxF;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;ACrDA;;;;;;;AAOAF,QAAOC,OAAP,GAAiB,UAAU+B,OAAV,EAAmB;;AAEhC,SAAIC,SAASC,MAAMD,MAAnB;;AAEAD,aAAQG,KAAR,GAAsB,IAAtB;AACAH,aAAQI,WAAR,GAAsB,IAAtB;;AAEAJ,aAAQK,cAAR,GAAyB,UAAUC,YAAV,E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AACA;AACA,IAAG;AACH;AACA,IAAG;AACH;AACA;AACA,EAAC;;AAED;AACA,cAAa,OAAO;AACpB,cAAa,QAAQ;AACrB;AACA;;AAEA;AACA;;AAEA;AACA,yBAAwB,iCAAiC,EAAE;AAC3D,8BAA6B,uEAAuE,EAAE;;AAEtG;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,iBAAgB,QAAQ;;AAExB;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA,gEAA+D;AAC/D;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,sBAAqB,4BAA4B;AACjD;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,MAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA,MAAK;AACL;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA,MAAK;AACL;AACA;;AAEA;AACA;;AAEA;;AAEA,EAAC;;;;;;;;;ACxLD;;;;;;;AAOA3B,QAAOC,OAAP,GAAkB,UAAUob,KAAV,EAAiB;;AAE/B,SAAIpZ,SAASC,MAAMD,MAAnB;;AAEA;;;;AAIAoZ,WAAMC,IAAN,GAAa,YAAY;;AAErB;AACArZ,gBAAOb,KAAP,CAAa2N,IAAb,GAAoB9M,OAAOyI,KAAP,CAAa6B,QAAb,CAAsByC,SAA1C;;AAEA;AACA/M,gBAAOb,KAAP,CAAama,UAAb,GAA0B,EAA1B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;AAEH,UATD,MASO;;AAEH;AACAvE,oBAAO2D,OAAP,CAAeW,WAAf,CAA2BkJ,SAA3B;;AAEA;AACA1I;AAEH;;AAED;AACAud,0BAAiBpd,KAAKod,cAAtB;;AAEA,aAAIA,kBAAkB,OAAOA,cAAP,IAAyB,UAA/C,EAA2D;;AAEvDA,4BAAeC,IAAf,CAAoBzf,KAApB;AAEH;;AAED6C,gBAAO8E,UAAP,CAAkB,YAAY;;AAE1B;AACAxK,oBAAOiE,KAAP,CAAawD,UAAb,CAAwB3C,iBAAxB;AAEH,UALD,EAKG,EALH;;AAQA;;;AAGA9E,gBAAO2D,OAAP,CAAemD,kBAAf;;AAEA;;;AAGA9G,gBAAO4B,OAAP,CAAe+C,IAAf;AAEH,MArED;;AAuEA,YAAOb,OAAP;AAEH,EArLgB,CAqLd,EArLc,CAAjB,C;;;;;;;;;;;;ACTA/F,QAAOC,OAAP;AAEI,sBAAc;AAAA;AAGb;;AALL;AAAA;AAAA,mCAOc,CAET;AATL;;AAAA;AAAA;AAYA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;;;;;;;;;;;ACpKI;;;;;AAKJ,KAAIiD,YAAY;;AAEZ;;;AAGAgM,sBAAkB,UALN;;AAOZ;;;AAGA6B,oBAAgB,mBAVJ;;AAYZ;;;AAGAC,sBAAkB,qBAfN;;AAiBZ;;;AAGA/B,wBAAoB,mBApBR;;AAsBZ;;;AAGAuV,oBAAgB;AAzBJ,EAAhB;;AA4BA,KAAIC,OAAO;AACPC,oBAAgB,cADT;AAEPC,iBAAgB;AAFT,EAAX;;AAMA;;;;;;;;;;;;;AAaA3kB,QAAOC,OAAP;AAAA;AAAA;;;AAEI;;;;AAFJ,6BAMsB;;AAEd,oBAAO,IAAP;AAEH;;AAED;;;;;;AAZJ;;AAiBI,iBAAaC,MAAb,EAAsB;AAAA;;AAElB,cAAKA,MAAL,GAAcA,MAAd;AACA,cAAK0kB,MAAL,GAAc,IAAd;AAEH;;AAGD;;;;;;AAzBJ;AAAA;;;AAmCI;;;;;AAnCJ,mCAwCc;;AAENlkB,qBAAQC,GAAR,CAAY,kBAAZ;;AAEA;;AAEA,oBAAO,IAAIP,OAAJ,CAAY,UAAUC,OAAV,EAAmBwkB,MAAnB,EAA2B;;AAE1C,qBAAIlS,UAAW,KAAK9S,OAAL,CAAailB,GAAb,CAAiBC,IAAjB,CAAsB,KAAtB,EAA6B,CAAEN,KAAKC,aAAP,CAA7B,EAAqD,EAArD,CAAf;AAAA,qBACInY,WAAW,KAAK1M,OAAL,CAAailB,GAAb,CAAiBC,IAAjB,CAAsB,KAAtB,EAA6B,CAAEN,KAAKE,UAAP,CAA7B,EAAkD,EAAlD,CADf;AAAA,qBAEI9gB,UAAWmhB,cAFf;;AAIArS,yBAAQ7E,WAAR,CAAoBjK,OAApB;AACA8O,yBAAQ7E,WAAR,CAAoBvB,QAApB;;AAEA;AACAtK,wBAAOyI,KAAP,CAAaiI,OAAb,GAAwBA,OAAxB;AACA1Q,wBAAOyI,KAAP,CAAa6B,QAAb,GAAwBA,QAAxB;;AAEA;AACAtK,wBAAOyI,KAAP,CAAa8L,MAAb,CAAoB1I,WAApB,CAAgC6E,OAAhC;;AAEAtS;AAEH,cAlBM;;AAoBP;AApBO,cAqBNC,IArBM,CAqBD2kB,SArBC;;AAuBP;AAvBO,cAwBN3kB,IAxBM,CAwBD4kB,kBAxBC;;AA0BP;AA1BO,cA2BN5kB,IA3BM,CA2BD6kB,sBA3BC;;AA6BP;AA7BO,cA8BN7kB,IA9BM,CA8BD8kB,uBA9BC;;AAgCP;AAhCO,cAiCN9kB,IAjCM,CAiCD+kB,WAjCC,EAmCNzkB,KAnCM,CAmCC,YAAY;;AAEhBqB,wBAAOsB,IAAP,CAAY5C,GAAZ,CAAgB,6BAAhB;AAEH,cAvCM,CAAP;AAyCH;AAvFL;AAAA;AAAA,2BA6BcikB,MA7Bd,EA6BsB;;AAEd,kBAAKA,MAAL,GAAcA,MAAd;AAEH;AAjCL;;AAAA;AAAA;AA0FA;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 f9fb2e3ee97ac7d4fd68","/**\n * Codex Editor\n *\n *\n *\n *\n * @author CodeX Team\n */\n\n/**\n * @typedef {CodexEditor} CodexEditor - editor class\n */\n\n/**\n * @typedef {Object} EditorConfig\n * @property {String} holderId - Element to append Editor\n * ...\n */\n\n'use strict';\n\n/**\n * Require Editor modules places in components/modules dir\n */\nlet modules = editorModules.map( module => {\n\n return require('./components/modules/' + module );\n\n});\n\n/**\n * @class\n *\n * @classdesc CodeX Editor base class\n *\n * @property this.config - all settings\n * @property this.moduleInstances - constructed editor components\n *\n * @type {CodexEditor}\n */\nmodule.exports = class CodexEditor {\n\n /** Editor version */\n static get version() {\n\n return VERSION;\n\n }\n\n /**\n * @param {EditorConfig} config - user configuration\n *\n */\n constructor(config) {\n\n /**\n * Configuration object\n */\n this.config = {};\n\n /**\n * Editor Components\n */\n this.moduleInstances = {};\n\n Promise.resolve()\n .then(() => {\n\n this.configuration = config;\n\n })\n .then(() => this.init())\n .then(() => this.start())\n .then(() => {\n\n console.log('CodeX Editor is ready');\n\n })\n .catch(error => {\n\n console.log('CodeX Editor does not ready beecause of %o', error);\n\n });\n\n }\n\n /**\n * Setting for configuration\n * @param {object} config\n */\n set configuration(config = {}) {\n\n this.config.holderId = config.holderId;\n this.config.placeholder = config.placeholder || 'write your story...';\n this.config.sanitizer = config.sanitizer || {\n p: true,\n b: true,\n a: true\n };\n\n this.config.hideToolbar = config.hideToolbar ? config.hideToolbar : false;\n\n }\n\n /**\n * Returns private property\n * @returns {{}|*}\n */\n get configuration() {\n\n return this.config;\n\n }\n\n /**\n * Initializes modules:\n * - make and save instances\n * - configure\n */\n init() {\n\n /**\n * Make modules instances and save it to the @property this.moduleInstances\n */\n this.constructModules();\n\n /**\n * Modules configuration\n */\n this.configureModules();\n\n }\n\n /**\n * Make modules instances and save it to the @property this.moduleInstances\n */\n constructModules() {\n\n modules.forEach( Module => {\n\n try {\n\n this.moduleInstances[Module.name] = new Module({\n config : this.configuration\n });\n\n } catch ( e ) {\n\n console.log('Module %o skipped because %o', Module, e);\n\n }\n\n });\n\n }\n\n /**\n * Modules instances configuration:\n * - pass other modules to the 'state' property\n * - ...\n */\n configureModules() {\n\n for(let name in this.moduleInstances) {\n\n /**\n * Module does not need self-instance\n */\n this.moduleInstances[name].state = this.getModulesDiff( name );\n\n }\n\n }\n\n /**\n * Return modules without passed name\n */\n getModulesDiff( name ) {\n\n let modules = {};\n\n for(let moduleName in this.moduleInstances) {\n\n /**\n * Skip module with passed name\n */\n if (moduleName == name) {\n\n continue;\n\n }\n modules[moduleName] = this.moduleInstances[moduleName];\n\n }\n\n return modules;\n\n }\n\n\n\n /**\n * Start Editor!\n *\n * @return {Promise}\n */\n start() {\n\n let prepareDecorator = module => module.prepare();\n\n return Promise.resolve()\n .then(prepareDecorator(this.moduleInstances['ui']))\n .catch(function (error) {\n\n console.log('Error occured', error);\n\n });\n\n\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// ./src/codex.js","var map = {\n\t\"./_anchors\": 2,\n\t\"./_anchors.js\": 2,\n\t\"./_callbacks\": 3,\n\t\"./_callbacks.js\": 3,\n\t\"./_caret\": 4,\n\t\"./_caret.js\": 4,\n\t\"./_content\": 5,\n\t\"./_content.js\": 5,\n\t\"./_destroyer\": 6,\n\t\"./_destroyer.js\": 6,\n\t\"./_listeners\": 7,\n\t\"./_listeners.js\": 7,\n\t\"./_notifications\": 8,\n\t\"./_notifications.js\": 8,\n\t\"./_parser\": 9,\n\t\"./_parser.js\": 9,\n\t\"./_paste\": 10,\n\t\"./_paste.js\": 10,\n\t\"./_renderer\": 11,\n\t\"./_renderer.js\": 11,\n\t\"./_sanitizer\": 12,\n\t\"./_sanitizer.js\": 12,\n\t\"./_saver\": 14,\n\t\"./_saver.js\": 14,\n\t\"./_transport\": 15,\n\t\"./_transport.js\": 15,\n\t\"./eventDispatcher\": 16,\n\t\"./eventDispatcher.js\": 16,\n\t\"./toolbar/inline\": 17,\n\t\"./toolbar/inline.js\": 17,\n\t\"./toolbar/settings\": 18,\n\t\"./toolbar/settings.js\": 18,\n\t\"./toolbar/toolbar\": 19,\n\t\"./toolbar/toolbar.js\": 19,\n\t\"./toolbar/toolbox\": 20,\n\t\"./toolbar/toolbox.js\": 20,\n\t\"./tools\": 21,\n\t\"./tools.js\": 21,\n\t\"./ui\": 22,\n\t\"./ui.js\": 22\n};\nfunction webpackContext(req) {\n\treturn __webpack_require__(webpackContextResolve(req));\n};\nfunction webpackContextResolve(req) {\n\treturn map[req] || (function() { throw new Error(\"Cannot find module '\" + req + \"'.\") }());\n};\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = 1;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/components/modules ^\\.\\/.*$\n// module id = 1\n// module chunks = 0","/**\n * Codex Editor Anchors module\n *\n * @author Codex Team\n * @version 1.0\n */\n\nmodule.exports = function (anchors) {\n\n let editor = codex.editor;\n\n anchors.input = null;\n anchors.currentNode = null;\n\n anchors.settingsOpened = function (currentBlock) {\n\n anchors.currentNode = currentBlock;\n anchors.input.value = anchors.currentNode.dataset.anchor || '';\n\n };\n\n anchors.anchorChanged = function (e) {\n\n var newAnchor = e.target.value = anchors.rusToTranslit(e.target.value);\n\n anchors.currentNode.dataset.anchor = newAnchor;\n\n if (newAnchor.trim() !== '') {\n\n anchors.currentNode.classList.add(editor.ui.className.BLOCK_WITH_ANCHOR);\n\n } else {\n\n anchors.currentNode.classList.remove(editor.ui.className.BLOCK_WITH_ANCHOR);\n\n }\n\n };\n\n anchors.keyDownOnAnchorInput = function (e) {\n\n if (e.keyCode == editor.core.keys.ENTER) {\n\n e.preventDefault();\n e.stopPropagation();\n\n e.target.blur();\n editor.toolbar.settings.close();\n\n }\n\n };\n\n anchors.keyUpOnAnchorInput = function (e) {\n\n if (e.keyCode >= editor.core.keys.LEFT && e.keyCode <= editor.core.keys.DOWN) {\n\n e.stopPropagation();\n\n }\n\n };\n\n anchors.rusToTranslit = function (string) {\n\n var ru = [\n 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й',\n 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф',\n 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ь', 'Ы', 'Ь', 'Э', 'Ю', 'Я'\n ],\n en = [\n 'A', 'B', 'V', 'G', 'D', 'E', 'E', 'Zh', 'Z', 'I', 'Y',\n 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F',\n 'H', 'C', 'Ch', 'Sh', 'Sch', '', 'Y', '', 'E', 'Yu', 'Ya'\n ];\n\n for (var i = 0; i < ru.length; i++) {\n\n string = string.split(ru[i]).join(en[i]);\n string = string.split(ru[i].toLowerCase()).join(en[i].toLowerCase());\n\n }\n\n string = string.replace(/[^0-9a-zA-Z_]+/g, '-');\n\n return string;\n\n };\n\n return anchors;\n\n}({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_anchors.js","/**\n * @module Codex Editor Callbacks module\n * @description Module works with editor added Elements\n *\n * @author Codex Team\n * @version 1.4.0\n */\n\nmodule.exports = (function (callbacks) {\n\n let editor = codex.editor;\n\n /**\n * used by UI module\n * @description Routes all keydowns on document\n * @param {Object} event\n */\n callbacks.globalKeydown = function (event) {\n\n switch (event.keyCode) {\n case editor.core.keys.ENTER : enterKeyPressed_(event); break;\n }\n\n };\n\n /**\n * used by UI module\n * @description Routes all keydowns on redactors area\n * @param {Object} event\n */\n callbacks.redactorKeyDown = function (event) {\n\n switch (event.keyCode) {\n case editor.core.keys.TAB : tabKeyPressedOnRedactorsZone_(event); break;\n case editor.core.keys.ENTER : enterKeyPressedOnRedactorsZone_(event); break;\n case editor.core.keys.ESC : escapeKeyPressedOnRedactorsZone_(event); break;\n default : defaultKeyPressedOnRedactorsZone_(event); break;\n }\n\n };\n\n /**\n * used by UI module\n * @description Routes all keyup events\n * @param {Object} event\n */\n callbacks.globalKeyup = function (event) {\n\n switch (event.keyCode) {\n case editor.core.keys.UP :\n case editor.core.keys.LEFT :\n case editor.core.keys.RIGHT :\n case editor.core.keys.DOWN : arrowKeyPressed_(event); break;\n }\n\n };\n\n /**\n * @param {Object} event\n * @private\n *\n * Handles behaviour when tab pressed\n * @description if Content is empty show toolbox (if it is closed) or leaf tools\n * uses Toolbars toolbox module to handle the situation\n */\n var tabKeyPressedOnRedactorsZone_ = function (event) {\n\n /**\n * Wait for solution. Would like to know the behaviour\n * @todo Add spaces\n */\n event.preventDefault();\n\n\n if (!editor.core.isBlockEmpty(editor.content.currentNode)) {\n\n return;\n\n }\n\n if ( !editor.toolbar.opened ) {\n\n editor.toolbar.open();\n\n }\n\n if (editor.toolbar.opened && !editor.toolbar.toolbox.opened) {\n\n editor.toolbar.toolbox.open();\n\n } else {\n\n editor.toolbar.toolbox.leaf();\n\n }\n\n };\n\n /**\n * Handles global EnterKey Press\n * @see enterPressedOnBlock_\n * @param {Object} event\n */\n var enterKeyPressed_ = function () {\n\n if (editor.content.editorAreaHightlighted) {\n\n /**\n * it means that we lose input index, saved index before is not correct\n * therefore we need to set caret when we insert new block\n */\n editor.caret.inputIndex = -1;\n\n enterPressedOnBlock_();\n\n }\n\n };\n\n /**\n * Callback for enter key pressing in first-level block area\n *\n * @param {Event} event\n * @private\n *\n * @description Inserts new block with initial type from settings\n */\n var enterPressedOnBlock_ = function () {\n\n var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;\n\n editor.content.insertBlock({\n type : NEW_BLOCK_TYPE,\n block : editor.tools[NEW_BLOCK_TYPE].render()\n }, true );\n\n editor.toolbar.move();\n editor.toolbar.open();\n\n };\n\n\n /**\n * ENTER key handler\n *\n * @param {Object} event\n * @private\n *\n * @description Makes new block with initial type from settings\n */\n var enterKeyPressedOnRedactorsZone_ = function (event) {\n\n if (event.target.contentEditable == 'true') {\n\n /** Update input index */\n editor.caret.saveCurrentInputIndex();\n\n }\n\n var currentInputIndex = editor.caret.getCurrentInputIndex() || 0,\n workingNode = editor.content.currentNode,\n tool = workingNode.dataset.tool,\n isEnterPressedOnToolbar = editor.toolbar.opened &&\n editor.toolbar.current &&\n event.target == editor.state.inputs[currentInputIndex];\n\n /** The list of tools which needs the default browser behaviour */\n var enableLineBreaks = editor.tools[tool].enableLineBreaks;\n\n /** This type of block creates when enter is pressed */\n var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;\n\n /**\n * When toolbar is opened, select tool instead of making new paragraph\n */\n if ( isEnterPressedOnToolbar ) {\n\n event.preventDefault();\n\n editor.toolbar.toolbox.toolClicked(event);\n\n editor.toolbar.close();\n\n /**\n * Stop other listeners callback executions\n */\n event.stopPropagation();\n event.stopImmediatePropagation();\n\n return;\n\n }\n\n /**\n * Allow paragraph lineBreaks with shift enter\n * Or if shiftkey pressed and enter and enabledLineBreaks, the let new block creation\n */\n if ( event.shiftKey || enableLineBreaks ) {\n\n event.stopPropagation();\n event.stopImmediatePropagation();\n return;\n\n }\n\n var currentSelection = window.getSelection(),\n currentSelectedNode = currentSelection.anchorNode,\n caretAtTheEndOfText = editor.caret.position.atTheEnd(),\n isTextNodeHasParentBetweenContenteditable = false;\n\n /**\n * Allow making new in same block by SHIFT+ENTER and forbids to prevent default browser behaviour\n */\n if ( event.shiftKey && !enableLineBreaks ) {\n\n editor.callback.enterPressedOnBlock(editor.content.currentBlock, event);\n event.preventDefault();\n return;\n\n }\n\n /**\n * Workaround situation when caret at the Text node that has some wrapper Elements\n * Split block cant handle this.\n * We need to save default behavior\n */\n isTextNodeHasParentBetweenContenteditable = currentSelectedNode && currentSelectedNode.parentNode.contentEditable != 'true';\n\n /**\n * Split blocks when input has several nodes and caret placed in textNode\n */\n if (\n currentSelectedNode.nodeType == editor.core.nodeTypes.TEXT &&\n !isTextNodeHasParentBetweenContenteditable &&\n !caretAtTheEndOfText\n ) {\n\n event.preventDefault();\n\n editor.core.log('Splitting Text node...');\n\n editor.content.splitBlock(currentInputIndex);\n\n /** Show plus button when next input after split is empty*/\n if (!editor.state.inputs[currentInputIndex + 1].textContent.trim()) {\n\n editor.toolbar.showPlusButton();\n\n }\n\n } else {\n\n var islastNode = editor.content.isLastNode(currentSelectedNode);\n\n if ( islastNode && caretAtTheEndOfText ) {\n\n event.preventDefault();\n event.stopPropagation();\n event.stopImmediatePropagation();\n\n editor.core.log('ENTER clicked in last textNode. Create new BLOCK');\n\n editor.content.insertBlock({\n type: NEW_BLOCK_TYPE,\n block: editor.tools[NEW_BLOCK_TYPE].render()\n }, true);\n\n editor.toolbar.move();\n editor.toolbar.open();\n\n /** Show plus button with empty block */\n editor.toolbar.showPlusButton();\n\n }\n\n }\n\n /** get all inputs after new appending block */\n editor.ui.saveInputs();\n\n };\n\n /**\n * Escape behaviour\n * @param event\n * @private\n *\n * @description Closes toolbox and toolbar. Prevents default behaviour\n */\n var escapeKeyPressedOnRedactorsZone_ = function (event) {\n\n /** Close all toolbar */\n editor.toolbar.close();\n\n /** Close toolbox */\n editor.toolbar.toolbox.close();\n\n event.preventDefault();\n\n };\n\n /**\n * @param {Event} event\n * @private\n *\n * closes and moves toolbar\n */\n var arrowKeyPressed_ = function (event) {\n\n editor.content.workingNodeChanged();\n\n /* Closing toolbar */\n editor.toolbar.close();\n editor.toolbar.move();\n\n };\n\n /**\n * @private\n * @param {Event} event\n *\n * @description Closes all opened bars from toolbar.\n * If block is mark, clears highlightning\n */\n var defaultKeyPressedOnRedactorsZone_ = function () {\n\n editor.toolbar.close();\n\n if (!editor.toolbar.inline.actionsOpened) {\n\n editor.toolbar.inline.close();\n editor.content.clearMark();\n\n }\n\n };\n\n /**\n * Handler when clicked on redactors area\n *\n * @protected\n * @param event\n *\n * @description Detects clicked area. If it is first-level block area, marks as detected and\n * on next enter press will be inserted new block\n * Otherwise, save carets position (input index) and put caret to the editable zone.\n *\n * @see detectWhenClickedOnFirstLevelBlockArea_\n *\n */\n callbacks.redactorClicked = function (event) {\n\n detectWhenClickedOnFirstLevelBlockArea_();\n\n editor.content.workingNodeChanged(event.target);\n editor.ui.saveInputs();\n\n var selectedText = editor.toolbar.inline.getSelectionText(),\n firstLevelBlock;\n\n /** If selection range took off, then we hide inline toolbar */\n if (selectedText.length === 0) {\n\n editor.toolbar.inline.close();\n\n }\n\n /** Update current input index in memory when caret focused into existed input */\n if (event.target.contentEditable == 'true') {\n\n editor.caret.saveCurrentInputIndex();\n\n }\n\n if (editor.content.currentNode === null) {\n\n /**\n * If inputs in redactor does not exits, then we put input index 0 not -1\n */\n var indexOfLastInput = editor.state.inputs.length > 0 ? editor.state.inputs.length - 1 : 0;\n\n /** If we have any inputs */\n if (editor.state.inputs.length) {\n\n /** getting firstlevel parent of input */\n firstLevelBlock = editor.content.getFirstLevelBlock(editor.state.inputs[indexOfLastInput]);\n\n }\n\n /** If input is empty, then we set caret to the last input */\n if (editor.state.inputs.length && editor.state.inputs[indexOfLastInput].textContent === '' && firstLevelBlock.dataset.tool == editor.settings.initialBlockPlugin) {\n\n editor.caret.setToBlock(indexOfLastInput);\n\n } else {\n\n /** Create new input when caret clicked in redactors area */\n var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;\n\n editor.content.insertBlock({\n type : NEW_BLOCK_TYPE,\n block : editor.tools[NEW_BLOCK_TYPE].render()\n });\n\n /** If there is no inputs except inserted */\n if (editor.state.inputs.length === 1) {\n\n editor.caret.setToBlock(indexOfLastInput);\n\n } else {\n\n /** Set caret to this appended input */\n editor.caret.setToNextBlock(indexOfLastInput);\n\n }\n\n }\n\n } else {\n\n /** Close all panels */\n editor.toolbar.settings.close();\n editor.toolbar.toolbox.close();\n\n }\n\n /**\n * Move toolbar and open\n */\n editor.toolbar.move();\n editor.toolbar.open();\n\n var inputIsEmpty = !editor.content.currentNode.textContent.trim(),\n currentNodeType = editor.content.currentNode.dataset.tool,\n isInitialType = currentNodeType == editor.settings.initialBlockPlugin;\n\n\n /** Hide plus buttons */\n editor.toolbar.hidePlusButton();\n\n if (!inputIsEmpty) {\n\n /** Mark current block */\n editor.content.markBlock();\n\n }\n\n if ( isInitialType && inputIsEmpty ) {\n\n /** Show plus button */\n editor.toolbar.showPlusButton();\n\n }\n\n\n };\n\n /**\n * This method allows to define, is caret in contenteditable element or not.\n *\n * @private\n *\n * @description Otherwise, if we get TEXT node from range container, that will means we have input index.\n * In this case we use default browsers behaviour (if plugin allows that) or overwritten action.\n * Therefore, to be sure that we've clicked first-level block area, we should have currentNode, which always\n * specifies to the first-level block. Other cases we just ignore.\n */\n var detectWhenClickedOnFirstLevelBlockArea_ = function () {\n\n var selection = window.getSelection(),\n anchorNode = selection.anchorNode,\n flag = false;\n\n if (selection.rangeCount === 0) {\n\n editor.content.editorAreaHightlighted = true;\n\n } else {\n\n if (!editor.core.isDomNode(anchorNode)) {\n\n anchorNode = anchorNode.parentNode;\n\n }\n\n /** Already founded, without loop */\n if (anchorNode.contentEditable == 'true') {\n\n flag = true;\n\n }\n\n while (anchorNode.contentEditable != 'true') {\n\n anchorNode = anchorNode.parentNode;\n\n if (anchorNode.contentEditable == 'true') {\n\n flag = true;\n\n }\n\n if (anchorNode == document.body) {\n\n break;\n\n }\n\n }\n\n /** If editable element founded, flag is \"TRUE\", Therefore we return \"FALSE\" */\n editor.content.editorAreaHightlighted = !flag;\n\n }\n\n };\n\n /**\n * Toolbar button click handler\n *\n * @param {Object} event - cursor to the button\n * @protected\n *\n * @description gets current tool and calls render method\n */\n callbacks.toolbarButtonClicked = function (event) {\n\n var button = this;\n\n editor.toolbar.current = button.dataset.type;\n\n editor.toolbar.toolbox.toolClicked(event);\n editor.toolbar.close();\n\n };\n\n /**\n * Show or Hide toolbox when plus button is clicked\n */\n callbacks.plusButtonClicked = function () {\n\n if (!editor.nodes.toolbox.classList.contains('opened')) {\n\n editor.toolbar.toolbox.open();\n\n } else {\n\n editor.toolbar.toolbox.close();\n\n }\n\n };\n\n /**\n * Block handlers for KeyDown events\n *\n * @protected\n * @param {Object} event\n *\n * Handles keydowns on block\n * @see blockRightOrDownArrowPressed_\n * @see backspacePressed_\n * @see blockLeftOrUpArrowPressed_\n */\n callbacks.blockKeydown = function (event) {\n\n let block = event.target; // event.target is input\n\n switch (event.keyCode) {\n\n case editor.core.keys.DOWN:\n case editor.core.keys.RIGHT:\n blockRightOrDownArrowPressed_(event);\n break;\n\n case editor.core.keys.BACKSPACE:\n backspacePressed_(block, event);\n break;\n\n case editor.core.keys.UP:\n case editor.core.keys.LEFT:\n blockLeftOrUpArrowPressed_(event);\n break;\n\n }\n\n };\n\n /**\n * RIGHT or DOWN keydowns on block\n *\n * @param {Object} event\n * @private\n *\n * @description watches the selection and gets closest editable element.\n * Uses method getDeepestTextNodeFromPosition to get the last node of next block\n * Sets caret if it is contenteditable\n */\n var blockRightOrDownArrowPressed_ = function (event) {\n\n var selection = window.getSelection(),\n inputs = editor.state.inputs,\n focusedNode = selection.anchorNode,\n focusedNodeHolder;\n\n /** Check for caret existance */\n if (!focusedNode) {\n\n return false;\n\n }\n\n /** Looking for closest (parent) contentEditable element of focused node */\n while (focusedNode.contentEditable != 'true') {\n\n focusedNodeHolder = focusedNode.parentNode;\n focusedNode = focusedNodeHolder;\n\n }\n\n /** Input index in DOM level */\n var editableElementIndex = 0;\n\n while (focusedNode != inputs[editableElementIndex]) {\n\n editableElementIndex ++;\n\n }\n\n /**\n * Founded contentEditable element doesn't have childs\n * Or maybe New created block\n */\n if (!focusedNode.textContent) {\n\n editor.caret.setToNextBlock(editableElementIndex);\n return;\n\n }\n\n /**\n * Do nothing when caret doesn not reaches the end of last child\n */\n var caretInLastChild = false,\n caretAtTheEndOfText = false;\n\n var lastChild,\n deepestTextnode;\n\n lastChild = focusedNode.childNodes[focusedNode.childNodes.length - 1 ];\n\n if (editor.core.isDomNode(lastChild)) {\n\n deepestTextnode = editor.content.getDeepestTextNodeFromPosition(lastChild, lastChild.childNodes.length);\n\n } else {\n\n deepestTextnode = lastChild;\n\n }\n\n caretInLastChild = selection.anchorNode == deepestTextnode;\n caretAtTheEndOfText = deepestTextnode.length == selection.anchorOffset;\n\n if ( !caretInLastChild || !caretAtTheEndOfText ) {\n\n editor.core.log('arrow [down|right] : caret does not reached the end');\n return false;\n\n }\n\n editor.caret.setToNextBlock(editableElementIndex);\n\n };\n\n /**\n * LEFT or UP keydowns on block\n *\n * @param {Object} event\n * @private\n *\n * watches the selection and gets closest editable element.\n * Uses method getDeepestTextNodeFromPosition to get the last node of previous block\n * Sets caret if it is contenteditable\n *\n */\n var blockLeftOrUpArrowPressed_ = function (event) {\n\n var selection = window.getSelection(),\n inputs = editor.state.inputs,\n focusedNode = selection.anchorNode,\n focusedNodeHolder;\n\n /** Check for caret existance */\n if (!focusedNode) {\n\n return false;\n\n }\n\n /**\n * LEFT or UP not at the beginning\n */\n if ( selection.anchorOffset !== 0) {\n\n return false;\n\n }\n\n /** Looking for parent contentEditable block */\n while (focusedNode.contentEditable != 'true') {\n\n focusedNodeHolder = focusedNode.parentNode;\n focusedNode = focusedNodeHolder;\n\n }\n\n /** Input index in DOM level */\n var editableElementIndex = 0;\n\n while (focusedNode != inputs[editableElementIndex]) {\n\n editableElementIndex ++;\n\n }\n\n /**\n * Do nothing if caret is not at the beginning of first child\n */\n var caretInFirstChild = false,\n caretAtTheBeginning = false;\n\n var firstChild,\n deepestTextnode;\n\n /**\n * Founded contentEditable element doesn't have childs\n * Or maybe New created block\n */\n if (!focusedNode.textContent) {\n\n editor.caret.setToPreviousBlock(editableElementIndex);\n return;\n\n }\n\n firstChild = focusedNode.childNodes[0];\n\n if (editor.core.isDomNode(firstChild)) {\n\n deepestTextnode = editor.content.getDeepestTextNodeFromPosition(firstChild, 0);\n\n } else {\n\n deepestTextnode = firstChild;\n\n }\n\n caretInFirstChild = selection.anchorNode == deepestTextnode;\n caretAtTheBeginning = selection.anchorOffset === 0;\n\n if ( caretInFirstChild && caretAtTheBeginning ) {\n\n editor.caret.setToPreviousBlock(editableElementIndex);\n\n }\n\n };\n\n /**\n * Handles backspace keydown\n *\n * @param {Element} block\n * @param {Object} event\n * @private\n *\n * @description if block is empty, delete the block and set caret to the previous block\n * If block is not empty, try to merge two blocks - current and previous\n * But it we try'n to remove first block, then we should set caret to the next block, not previous.\n * If we removed the last block, create new one\n */\n var backspacePressed_ = function (block, event) {\n\n var currentInputIndex = editor.caret.getCurrentInputIndex(),\n range,\n selectionLength,\n firstLevelBlocksCount;\n\n if (editor.core.isNativeInput(event.target)) {\n\n /** If input value is empty - remove block */\n if (event.target.value.trim() == '') {\n\n block.remove();\n\n } else {\n\n return;\n\n }\n\n }\n\n if (block.textContent.trim()) {\n\n range = editor.content.getRange();\n selectionLength = range.endOffset - range.startOffset;\n\n if (editor.caret.position.atStart() && !selectionLength && editor.state.inputs[currentInputIndex - 1]) {\n\n editor.content.mergeBlocks(currentInputIndex);\n\n } else {\n\n return;\n\n }\n\n }\n\n if (!selectionLength) {\n\n block.remove();\n\n }\n\n\n firstLevelBlocksCount = editor.nodes.redactor.childNodes.length;\n\n /**\n * If all blocks are removed\n */\n if (firstLevelBlocksCount === 0) {\n\n /** update currentNode variable */\n editor.content.currentNode = null;\n\n /** Inserting new empty initial block */\n editor.ui.addInitialBlock();\n\n /** Updating inputs state after deleting last block */\n editor.ui.saveInputs();\n\n /** Set to current appended block */\n window.setTimeout(function () {\n\n editor.caret.setToPreviousBlock(1);\n\n }, 10);\n\n } else {\n\n if (editor.caret.inputIndex !== 0) {\n\n /** Target block is not first */\n editor.caret.setToPreviousBlock(editor.caret.inputIndex);\n\n } else {\n\n /** If we try to delete first block */\n editor.caret.setToNextBlock(editor.caret.inputIndex);\n\n }\n\n }\n\n editor.toolbar.move();\n\n if (!editor.toolbar.opened) {\n\n editor.toolbar.open();\n\n }\n\n /** Updating inputs state */\n editor.ui.saveInputs();\n\n /** Prevent default browser behaviour */\n event.preventDefault();\n\n };\n\n /**\n * used by UI module\n * Clicks on block settings button\n *\n * @param {Object} event\n * @protected\n * @description Opens toolbar settings\n */\n callbacks.showSettingsButtonClicked = function (event) {\n\n /**\n * Get type of current block\n * It uses to append settings from tool.settings property.\n * ...\n * Type is stored in data-type attribute on block\n */\n var currentToolType = editor.content.currentNode.dataset.tool;\n\n editor.toolbar.settings.toggle(currentToolType);\n\n /** Close toolbox when settings button is active */\n editor.toolbar.toolbox.close();\n editor.toolbar.settings.hideRemoveActions();\n\n };\n\n return callbacks;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_callbacks.js","/**\n * Codex Editor Caret Module\n *\n * @author Codex Team\n * @version 1.0\n */\n\nmodule.exports = (function (caret) {\n\n let editor = codex.editor;\n\n /**\n * @var {int} InputIndex - editable element in DOM\n */\n caret.inputIndex = null;\n\n /**\n * @var {int} offset - caret position in a text node.\n */\n caret.offset = null;\n\n /**\n * @var {int} focusedNodeIndex - we get index of child node from first-level block\n */\n caret.focusedNodeIndex = null;\n\n /**\n * Creates Document Range and sets caret to the element.\n * @protected\n * @uses caret.save — if you need to save caret position\n * @param {Element} el - Changed Node.\n */\n caret.set = function ( el, index, offset) {\n\n offset = offset || caret.offset || 0;\n index = index || caret.focusedNodeIndex || 0;\n\n var childs = el.childNodes,\n nodeToSet;\n\n if ( childs.length === 0 ) {\n\n nodeToSet = el;\n\n } else {\n\n nodeToSet = childs[index];\n\n }\n\n /** If Element is INPUT */\n if (el.contentEditable != 'true') {\n\n el.focus();\n return;\n\n }\n\n if (editor.core.isDomNode(nodeToSet)) {\n\n nodeToSet = editor.content.getDeepestTextNodeFromPosition(nodeToSet, nodeToSet.childNodes.length);\n\n }\n\n var range = document.createRange(),\n selection = window.getSelection();\n\n window.setTimeout(function () {\n\n range.setStart(nodeToSet, offset);\n range.setEnd(nodeToSet, offset);\n\n selection.removeAllRanges();\n selection.addRange(range);\n\n editor.caret.saveCurrentInputIndex();\n\n }, 20);\n\n };\n\n /**\n * @protected\n * Updates index of input and saves it in caret object\n */\n caret.saveCurrentInputIndex = function () {\n\n /** Index of Input that we paste sanitized content */\n var selection = window.getSelection(),\n inputs = editor.state.inputs,\n focusedNode = selection.anchorNode,\n focusedNodeHolder;\n\n if (!focusedNode) {\n\n return;\n\n }\n\n /** Looking for parent contentEditable block */\n while (focusedNode.contentEditable != 'true') {\n\n focusedNodeHolder = focusedNode.parentNode;\n focusedNode = focusedNodeHolder;\n\n }\n\n /** Input index in DOM level */\n var editableElementIndex = 0;\n\n while (focusedNode != inputs[editableElementIndex]) {\n\n editableElementIndex ++;\n\n }\n\n caret.inputIndex = editableElementIndex;\n\n };\n\n /**\n * Returns current input index (caret object)\n */\n caret.getCurrentInputIndex = function () {\n\n return caret.inputIndex;\n\n };\n\n /**\n * @param {int} index - index of first-level block after that we set caret into next input\n */\n caret.setToNextBlock = function (index) {\n\n var inputs = editor.state.inputs,\n nextInput = inputs[index + 1];\n\n if (!nextInput) {\n\n editor.core.log('We are reached the end');\n return;\n\n }\n\n /**\n * When new Block created or deleted content of input\n * We should add some text node to set caret\n */\n if (!nextInput.childNodes.length) {\n\n var emptyTextElement = document.createTextNode('');\n\n nextInput.appendChild(emptyTextElement);\n\n }\n\n editor.caret.inputIndex = index + 1;\n editor.caret.set(nextInput, 0, 0);\n editor.content.workingNodeChanged(nextInput);\n\n };\n\n /**\n * @param {int} index - index of target input.\n * Sets caret to input with this index\n */\n caret.setToBlock = function (index) {\n\n var inputs = editor.state.inputs,\n targetInput = inputs[index];\n\n if ( !targetInput ) {\n\n return;\n\n }\n\n /**\n * When new Block created or deleted content of input\n * We should add some text node to set caret\n */\n if (!targetInput.childNodes.length) {\n\n var emptyTextElement = document.createTextNode('');\n\n targetInput.appendChild(emptyTextElement);\n\n }\n\n editor.caret.inputIndex = index;\n editor.caret.set(targetInput, 0, 0);\n editor.content.workingNodeChanged(targetInput);\n\n };\n\n /**\n * @param {int} index - index of input\n */\n caret.setToPreviousBlock = function (index) {\n\n index = index || 0;\n\n var inputs = editor.state.inputs,\n previousInput = inputs[index - 1],\n lastChildNode,\n lengthOfLastChildNode,\n emptyTextElement;\n\n\n if (!previousInput) {\n\n editor.core.log('We are reached first node');\n return;\n\n }\n\n lastChildNode = editor.content.getDeepestTextNodeFromPosition(previousInput, previousInput.childNodes.length);\n lengthOfLastChildNode = lastChildNode.length;\n\n /**\n * When new Block created or deleted content of input\n * We should add some text node to set caret\n */\n if (!previousInput.childNodes.length) {\n\n emptyTextElement = document.createTextNode('');\n previousInput.appendChild(emptyTextElement);\n\n }\n editor.caret.inputIndex = index - 1;\n editor.caret.set(previousInput, previousInput.childNodes.length - 1, lengthOfLastChildNode);\n editor.content.workingNodeChanged(inputs[index - 1]);\n\n };\n\n caret.position = {\n\n atStart : function () {\n\n var selection = window.getSelection(),\n anchorOffset = selection.anchorOffset,\n anchorNode = selection.anchorNode,\n firstLevelBlock = editor.content.getFirstLevelBlock(anchorNode),\n pluginsRender = firstLevelBlock.childNodes[0];\n\n if (!editor.core.isDomNode(anchorNode)) {\n\n anchorNode = anchorNode.parentNode;\n\n }\n\n var isFirstNode = anchorNode === pluginsRender.childNodes[0],\n isOffsetZero = anchorOffset === 0;\n\n return isFirstNode && isOffsetZero;\n\n },\n\n atTheEnd : function () {\n\n var selection = window.getSelection(),\n anchorOffset = selection.anchorOffset,\n anchorNode = selection.anchorNode;\n\n /** Caret is at the end of input */\n return !anchorNode || !anchorNode.length || anchorOffset === anchorNode.length;\n\n }\n };\n\n\n /**\n * Inserts node at the caret location\n * @param {HTMLElement|DocumentFragment} node\n */\n caret.insertNode = function (node) {\n\n var selection, range,\n lastNode = node;\n\n if (node.nodeType == editor.core.nodeTypes.DOCUMENT_FRAGMENT) {\n\n lastNode = node.lastChild;\n\n }\n\n selection = window.getSelection();\n\n range = selection.getRangeAt(0);\n range.deleteContents();\n\n range.insertNode(node);\n\n range.setStartAfter(lastNode);\n range.collapse(true);\n\n selection.removeAllRanges();\n selection.addRange(range);\n\n\n };\n\n return caret;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_caret.js","/**\n * Codex Editor Content Module\n * Works with DOM\n *\n * @module Codex Editor content module\n *\n * @author Codex Team\n * @version 1.3.13\n *\n * @description Module works with Elements that have been appended to the main DOM\n */\n\nmodule.exports = (function (content) {\n\n let editor = codex.editor;\n\n /**\n * Links to current active block\n * @type {null | Element}\n */\n content.currentNode = null;\n\n /**\n * clicked in redactor area\n * @type {null | Boolean}\n */\n content.editorAreaHightlighted = null;\n\n /**\n * @deprecated\n * Synchronizes redactor with original textarea\n */\n content.sync = function () {\n\n editor.core.log('syncing...');\n\n /**\n * Save redactor content to editor.state\n */\n editor.state.html = editor.nodes.redactor.innerHTML;\n\n };\n\n /**\n * Appends background to the block\n *\n * @description add CSS class to highlight visually first-level block area\n */\n content.markBlock = function () {\n\n editor.content.currentNode.classList.add(editor.ui.className.BLOCK_HIGHLIGHTED);\n\n };\n\n /**\n * Clear background\n *\n * @description clears styles that highlights block\n */\n content.clearMark = function () {\n\n if (editor.content.currentNode) {\n\n editor.content.currentNode.classList.remove(editor.ui.className.BLOCK_HIGHLIGHTED);\n\n }\n\n };\n\n /**\n * Finds first-level block\n *\n * @param {Element} node - selected or clicked in redactors area node\n * @protected\n *\n * @description looks for first-level block.\n * gets parent while node is not first-level\n */\n content.getFirstLevelBlock = function (node) {\n\n if (!editor.core.isDomNode(node)) {\n\n node = node.parentNode;\n\n }\n\n if (node === editor.nodes.redactor || node === document.body) {\n\n return null;\n\n } else {\n\n while(!node.classList.contains(editor.ui.className.BLOCK_CLASSNAME)) {\n\n node = node.parentNode;\n\n }\n\n return node;\n\n }\n\n };\n\n /**\n * Trigger this event when working node changed\n * @param {Element} targetNode - first-level of this node will be current\n * @protected\n *\n * @description If targetNode is first-level then we set it as current else we look for parents to find first-level\n */\n content.workingNodeChanged = function (targetNode) {\n\n /** Clear background from previous marked block before we change */\n editor.content.clearMark();\n\n if (!targetNode) {\n\n return;\n\n }\n\n content.currentNode = content.getFirstLevelBlock(targetNode);\n\n };\n\n /**\n * Replaces one redactor block with another\n * @protected\n * @param {Element} targetBlock - block to replace. Mostly currentNode.\n * @param {Element} newBlock\n * @param {string} newBlockType - type of new block; we need to store it to data-attribute\n *\n * [!] Function does not saves old block content.\n * You can get it manually and pass with newBlock.innerHTML\n */\n content.replaceBlock = function (targetBlock, newBlock) {\n\n if (!targetBlock || !newBlock) {\n\n editor.core.log('replaceBlock: missed params');\n return;\n\n }\n\n /** If target-block is not a frist-level block, then we iterate parents to find it */\n while(!targetBlock.classList.contains(editor.ui.className.BLOCK_CLASSNAME)) {\n\n targetBlock = targetBlock.parentNode;\n\n }\n\n /** Replacing */\n editor.nodes.redactor.replaceChild(newBlock, targetBlock);\n\n /**\n * Set new node as current\n */\n editor.content.workingNodeChanged(newBlock);\n\n /**\n * Add block handlers\n */\n editor.ui.addBlockHandlers(newBlock);\n\n /**\n * Save changes\n */\n editor.ui.saveInputs();\n\n };\n\n /**\n * @protected\n *\n * Inserts new block to redactor\n * Wrapps block into a DIV with BLOCK_CLASSNAME class\n *\n * @param blockData {object}\n * @param blockData.block {Element} element with block content\n * @param blockData.type {string} block plugin\n * @param needPlaceCaret {bool} pass true to set caret in new block\n *\n */\n content.insertBlock = function ( blockData, needPlaceCaret ) {\n\n var workingBlock = editor.content.currentNode,\n newBlockContent = blockData.block,\n blockType = blockData.type,\n isStretched = blockData.stretched;\n\n var newBlock = composeNewBlock_(newBlockContent, blockType, isStretched);\n\n if (workingBlock) {\n\n editor.core.insertAfter(workingBlock, newBlock);\n\n } else {\n\n /**\n * If redactor is empty, append as first child\n */\n editor.nodes.redactor.appendChild(newBlock);\n\n }\n\n /**\n * Block handler\n */\n editor.ui.addBlockHandlers(newBlock);\n\n /**\n * Set new node as current\n */\n editor.content.workingNodeChanged(newBlock);\n\n /**\n * Save changes\n */\n editor.ui.saveInputs();\n\n\n if ( needPlaceCaret ) {\n\n /**\n * If we don't know input index then we set default value -1\n */\n var currentInputIndex = editor.caret.getCurrentInputIndex() || -1;\n\n\n if (currentInputIndex == -1) {\n\n\n var editableElement = newBlock.querySelector('[contenteditable]'),\n emptyText = document.createTextNode('');\n\n editableElement.appendChild(emptyText);\n editor.caret.set(editableElement, 0, 0);\n\n editor.toolbar.move();\n editor.toolbar.showPlusButton();\n\n\n } else {\n\n if (currentInputIndex === editor.state.inputs.length - 1)\n return;\n\n /** Timeout for browsers execution */\n window.setTimeout(function () {\n\n /** Setting to the new input */\n editor.caret.setToNextBlock(currentInputIndex);\n editor.toolbar.move();\n editor.toolbar.open();\n\n }, 10);\n\n }\n\n }\n\n /**\n * Block is inserted, wait for new click that defined focusing on editors area\n * @type {boolean}\n */\n content.editorAreaHightlighted = false;\n\n };\n\n /**\n * Replaces blocks with saving content\n * @protected\n * @param {Element} noteToReplace\n * @param {Element} newNode\n * @param {Element} blockType\n */\n content.switchBlock = function (blockToReplace, newBlock, tool) {\n\n tool = tool || editor.content.currentNode.dataset.tool;\n var newBlockComposed = composeNewBlock_(newBlock, tool);\n\n /** Replacing */\n editor.content.replaceBlock(blockToReplace, newBlockComposed);\n\n /** Save new Inputs when block is changed */\n editor.ui.saveInputs();\n\n };\n\n /**\n * Iterates between child noted and looking for #text node on deepest level\n * @protected\n *\n * @param {Element} block - node where find\n * @param {int} postiton - starting postion\n * Example: childNodex.length to find from the end\n * or 0 to find from the start\n * @return {Text} block\n * @uses DFS\n */\n content.getDeepestTextNodeFromPosition = function (block, position) {\n\n /**\n * Clear Block from empty and useless spaces with trim.\n * Such nodes we should remove\n */\n var blockChilds = block.childNodes,\n index,\n node,\n text;\n\n for(index = 0; index < blockChilds.length; index++) {\n\n node = blockChilds[index];\n\n if (node.nodeType == editor.core.nodeTypes.TEXT) {\n\n text = node.textContent.trim();\n\n /** Text is empty. We should remove this child from node before we start DFS\n * decrease the quantity of childs.\n */\n if (text === '') {\n\n block.removeChild(node);\n position--;\n\n }\n\n }\n\n }\n\n if (block.childNodes.length === 0) {\n\n return document.createTextNode('');\n\n }\n\n /** Setting default position when we deleted all empty nodes */\n if ( position < 0 )\n position = 1;\n\n var lookingFromStart = false;\n\n /** For looking from START */\n if (position === 0) {\n\n lookingFromStart = true;\n position = 1;\n\n }\n\n while ( position ) {\n\n /** initial verticle of node. */\n if ( lookingFromStart ) {\n\n block = block.childNodes[0];\n\n } else {\n\n block = block.childNodes[position - 1];\n\n }\n\n if ( block.nodeType == editor.core.nodeTypes.TAG ) {\n\n position = block.childNodes.length;\n\n } else if (block.nodeType == editor.core.nodeTypes.TEXT ) {\n\n position = 0;\n\n }\n\n }\n\n return block;\n\n };\n\n /**\n * @private\n * @param {Element} block - current plugins render\n * @param {String} tool - plugins name\n * @param {Boolean} isStretched - make stretched block or not\n *\n * @description adds necessary information to wrap new created block by first-level holder\n */\n var composeNewBlock_ = function (block, tool, isStretched) {\n\n var newBlock = editor.draw.node('DIV', editor.ui.className.BLOCK_CLASSNAME, {}),\n blockContent = editor.draw.node('DIV', editor.ui.className.BLOCK_CONTENT, {});\n\n blockContent.appendChild(block);\n newBlock.appendChild(blockContent);\n\n if (isStretched) {\n\n blockContent.classList.add(editor.ui.className.BLOCK_STRETCHED);\n\n }\n\n newBlock.dataset.tool = tool;\n return newBlock;\n\n };\n\n /**\n * Returns Range object of current selection\n * @protected\n */\n content.getRange = function () {\n\n var selection = window.getSelection().getRangeAt(0);\n\n return selection;\n\n };\n\n /**\n * Divides block in two blocks (after and before caret)\n *\n * @protected\n * @param {int} inputIndex - target input index\n *\n * @description splits current input content to the separate blocks\n * When enter is pressed among the words, that text will be splited.\n */\n content.splitBlock = function (inputIndex) {\n\n var selection = window.getSelection(),\n anchorNode = selection.anchorNode,\n anchorNodeText = anchorNode.textContent,\n caretOffset = selection.anchorOffset,\n textBeforeCaret,\n textNodeBeforeCaret,\n textAfterCaret,\n textNodeAfterCaret;\n\n var currentBlock = editor.content.currentNode.querySelector('[contentEditable]');\n\n\n textBeforeCaret = anchorNodeText.substring(0, caretOffset);\n textAfterCaret = anchorNodeText.substring(caretOffset);\n\n textNodeBeforeCaret = document.createTextNode(textBeforeCaret);\n\n if (textAfterCaret) {\n\n textNodeAfterCaret = document.createTextNode(textAfterCaret);\n\n }\n\n var previousChilds = [],\n nextChilds = [],\n reachedCurrent = false;\n\n if (textNodeAfterCaret) {\n\n nextChilds.push(textNodeAfterCaret);\n\n }\n\n for ( var i = 0, child; !!(child = currentBlock.childNodes[i]); i++) {\n\n if ( child != anchorNode ) {\n\n if ( !reachedCurrent ) {\n\n previousChilds.push(child);\n\n } else {\n\n nextChilds.push(child);\n\n }\n\n } else {\n\n reachedCurrent = true;\n\n }\n\n }\n\n /** Clear current input */\n editor.state.inputs[inputIndex].innerHTML = '';\n\n /**\n * Append all childs founded before anchorNode\n */\n var previousChildsLength = previousChilds.length;\n\n for(i = 0; i < previousChildsLength; i++) {\n\n editor.state.inputs[inputIndex].appendChild(previousChilds[i]);\n\n }\n\n editor.state.inputs[inputIndex].appendChild(textNodeBeforeCaret);\n\n /**\n * Append text node which is after caret\n */\n var nextChildsLength = nextChilds.length,\n newNode = document.createElement('div');\n\n for(i = 0; i < nextChildsLength; i++) {\n\n newNode.appendChild(nextChilds[i]);\n\n }\n\n newNode = newNode.innerHTML;\n\n /** This type of block creates when enter is pressed */\n var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;\n\n /**\n * Make new paragraph with text after caret\n */\n editor.content.insertBlock({\n type : NEW_BLOCK_TYPE,\n block : editor.tools[NEW_BLOCK_TYPE].render({\n text : newNode\n })\n }, true );\n\n };\n\n /**\n * Merges two blocks — current and target\n * If target index is not exist, then previous will be as target\n *\n * @protected\n * @param {int} currentInputIndex\n * @param {int} targetInputIndex\n *\n * @description gets two inputs indexes and merges into one\n */\n content.mergeBlocks = function (currentInputIndex, targetInputIndex) {\n\n /** If current input index is zero, then prevent method execution */\n if (currentInputIndex === 0) {\n\n return;\n\n }\n\n var targetInput,\n currentInputContent = editor.state.inputs[currentInputIndex].innerHTML;\n\n if (!targetInputIndex) {\n\n targetInput = editor.state.inputs[currentInputIndex - 1];\n\n } else {\n\n targetInput = editor.state.inputs[targetInputIndex];\n\n }\n\n targetInput.innerHTML += currentInputContent;\n\n };\n\n /**\n * Iterates all right siblings and parents, which has right siblings\n * while it does not reached the first-level block\n *\n * @param {Element} node\n * @return {boolean}\n */\n content.isLastNode = function (node) {\n\n // console.log('погнали перебор родителей');\n\n var allChecked = false;\n\n while ( !allChecked ) {\n\n // console.log('Смотрим на %o', node);\n // console.log('Проверим, пустые ли соседи справа');\n\n if ( !allSiblingsEmpty_(node) ) {\n\n // console.log('Есть непустые соседи. Узел не последний. Выходим.');\n return false;\n\n }\n\n node = node.parentNode;\n\n /**\n * Проверяем родителей до тех пор, пока не найдем блок первого уровня\n */\n if ( node.classList.contains(editor.ui.className.BLOCK_CONTENT) ) {\n\n allChecked = true;\n\n }\n\n }\n\n return true;\n\n };\n\n /**\n * Checks if all element right siblings is empty\n * @param node\n */\n var allSiblingsEmpty_ = function (node) {\n\n /**\n * Нужно убедиться, что после пустого соседа ничего нет\n */\n var sibling = node.nextSibling;\n\n while ( sibling ) {\n\n if (sibling.textContent.length) {\n\n return false;\n\n }\n\n sibling = sibling.nextSibling;\n\n }\n\n return true;\n\n };\n\n /**\n * @public\n *\n * @param {string} htmlData - html content as string\n * @param {string} plainData - plain text\n * @return {string} - html content as string\n */\n content.wrapTextWithParagraphs = function (htmlData, plainData) {\n\n if (!htmlData.trim()) {\n\n return wrapPlainTextWithParagraphs(plainData);\n\n }\n\n var wrapper = document.createElement('DIV'),\n newWrapper = document.createElement('DIV'),\n i,\n paragraph,\n firstLevelBlocks = ['DIV', 'P'],\n blockTyped,\n node;\n\n /**\n * Make HTML Element to Wrap Text\n * It allows us to work with input data as HTML content\n */\n wrapper.innerHTML = htmlData;\n paragraph = document.createElement('P');\n\n for (i = 0; i < wrapper.childNodes.length; i++) {\n\n node = wrapper.childNodes[i];\n\n blockTyped = firstLevelBlocks.indexOf(node.tagName) != -1;\n\n /**\n * If node is first-levet\n * we add this node to our new wrapper\n */\n if ( blockTyped ) {\n\n /**\n * If we had splitted inline nodes to paragraph before\n */\n if ( paragraph.childNodes.length ) {\n\n newWrapper.appendChild(paragraph.cloneNode(true));\n\n /** empty paragraph */\n paragraph = null;\n paragraph = document.createElement('P');\n\n }\n\n newWrapper.appendChild(node.cloneNode(true));\n\n } else {\n\n /** Collect all inline nodes to one as paragraph */\n paragraph.appendChild(node.cloneNode(true));\n\n /** if node is last we should append this node to paragraph and paragraph to new wrapper */\n if ( i == wrapper.childNodes.length - 1 ) {\n\n newWrapper.appendChild(paragraph.cloneNode(true));\n\n }\n\n }\n\n }\n\n return newWrapper.innerHTML;\n\n };\n\n /**\n * Splits strings on new line and wraps paragraphs with
tag\n * @param plainText\n * @returns {string}\n */\n var wrapPlainTextWithParagraphs = function (plainText) {\n\n if (!plainText) return '';\n\n return '
' + plainText.split('\\n\\n').join('
') + '
';\n\n };\n\n /**\n * Finds closest Contenteditable parent from Element\n * @param {Element} node element looking from\n * @return {Element} node contenteditable\n */\n content.getEditableParent = function (node) {\n\n while (node && node.contentEditable != 'true') {\n\n node = node.parentNode;\n\n }\n\n return node;\n\n };\n\n /**\n * Clear editors content\n *\n * @param {Boolean} all — if true, delete all article data (content, id, etc.)\n */\n content.clear = function (all) {\n\n editor.nodes.redactor.innerHTML = '';\n editor.content.sync();\n editor.ui.saveInputs();\n if (all) {\n\n editor.state.blocks = {};\n\n } else if (editor.state.blocks) {\n\n editor.state.blocks.items = [];\n\n }\n\n editor.content.currentNode = null;\n\n };\n\n /**\n *\n * Load new data to editor\n * If editor is not empty, just append articleData.items\n *\n * @param articleData.items\n */\n content.load = function (articleData) {\n\n var currentContent = Object.assign({}, editor.state.blocks);\n\n editor.content.clear();\n\n if (!Object.keys(currentContent).length) {\n\n editor.state.blocks = articleData;\n\n } else if (!currentContent.items) {\n\n currentContent.items = articleData.items;\n editor.state.blocks = currentContent;\n\n } else {\n\n currentContent.items = currentContent.items.concat(articleData.items);\n editor.state.blocks = currentContent;\n\n }\n\n editor.renderer.makeBlocksFromData();\n\n };\n\n return content;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_content.js","/**\n * Codex Editor Destroyer module\n *\n * @auhor Codex Team\n * @version 1.0\n */\n\nmodule.exports = function (destroyer) {\n\n let editor = codex.editor;\n\n destroyer.removeNodes = function () {\n\n editor.nodes.wrapper.remove();\n editor.nodes.notifications.remove();\n\n };\n\n destroyer.destroyPlugins = function () {\n\n for (var tool in editor.tools) {\n\n if (typeof editor.tools[tool].destroy === 'function') {\n\n editor.tools[tool].destroy();\n\n }\n\n }\n\n };\n\n destroyer.destroyScripts = function () {\n\n var scripts = document.getElementsByTagName('SCRIPT');\n\n for (var i = 0; i < scripts.length; i++) {\n\n if (scripts[i].id.indexOf(editor.scriptPrefix) + 1) {\n\n scripts[i].remove();\n i--;\n\n }\n\n }\n\n };\n\n\n /**\n * Delete editor data from webpage.\n * You should send settings argument with boolean flags:\n * @param settings.ui- remove redactor event listeners and DOM nodes\n * @param settings.scripts - remove redactor scripts from DOM\n * @param settings.plugins - remove plugin's objects\n * @param settings.core - remove editor core. You can remove core only if UI and scripts flags is true\n * }\n *\n */\n destroyer.destroy = function (settings) {\n\n if (!settings || typeof settings !== 'object') {\n\n return;\n\n }\n\n if (settings.ui) {\n\n destroyer.removeNodes();\n editor.listeners.removeAll();\n\n }\n\n if (settings.scripts) {\n\n destroyer.destroyScripts();\n\n }\n\n if (settings.plugins) {\n\n destroyer.destroyPlugins();\n\n }\n\n if (settings.ui && settings.scripts && settings.core) {\n\n delete codex.editor;\n\n }\n\n };\n\n return destroyer;\n\n}({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_destroyer.js","/**\n * Codex Editor Listeners module\n *\n * @author Codex Team\n * @version 1.0\n */\n\n/**\n * Module-decorator for event listeners assignment\n */\nmodule.exports = function (listeners) {\n\n var allListeners = [];\n\n /**\n * Search methods\n *\n * byElement, byType and byHandler returns array of suitable listeners\n * one and all takes element, eventType, and handler and returns first (all) suitable listener\n *\n */\n listeners.search = function () {\n\n var byElement = function (element, context) {\n\n var listenersOnElement = [];\n\n context = context || allListeners;\n\n for (var i = 0; i < context.length; i++) {\n\n var listener = context[i];\n\n if (listener.element === element) {\n\n listenersOnElement.push(listener);\n\n }\n\n }\n\n return listenersOnElement;\n\n };\n\n var byType = function (eventType, context) {\n\n var listenersWithType = [];\n\n context = context || allListeners;\n\n for (var i = 0; i < context.length; i++) {\n\n var listener = context[i];\n\n if (listener.type === eventType) {\n\n listenersWithType.push(listener);\n\n }\n\n }\n\n return listenersWithType;\n\n };\n\n var byHandler = function (handler, context) {\n\n var listenersWithHandler = [];\n\n context = context || allListeners;\n\n for (var i = 0; i < context.length; i++) {\n\n var listener = context[i];\n\n if (listener.handler === handler) {\n\n listenersWithHandler.push(listener);\n\n }\n\n }\n\n return listenersWithHandler;\n\n };\n\n var one = function (element, eventType, handler) {\n\n var result = allListeners;\n\n if (element)\n result = byElement(element, result);\n\n if (eventType)\n result = byType(eventType, result);\n\n if (handler)\n result = byHandler(handler, result);\n\n return result[0];\n\n };\n\n var all = function (element, eventType, handler) {\n\n var result = allListeners;\n\n if (element)\n result = byElement(element, result);\n\n if (eventType)\n result = byType(eventType, result);\n\n if (handler)\n result = byHandler(handler, result);\n\n return result;\n\n };\n\n return {\n byElement : byElement,\n byType : byType,\n byHandler : byHandler,\n one : one,\n all : all\n };\n\n }();\n\n listeners.add = function (element, eventType, handler, isCapture) {\n\n element.addEventListener(eventType, handler, isCapture);\n\n var data = {\n element: element,\n type: eventType,\n handler: handler\n };\n\n var alreadyAddedListener = listeners.search.one(element, eventType, handler);\n\n if (!alreadyAddedListener) {\n\n allListeners.push(data);\n\n }\n\n };\n\n listeners.remove = function (element, eventType, handler) {\n\n element.removeEventListener(eventType, handler);\n\n var existingListeners = listeners.search.all(element, eventType, handler);\n\n for (var i = 0; i < existingListeners.length; i++) {\n\n var index = allListeners.indexOf(existingListeners[i]);\n\n if (index > 0) {\n\n allListeners.splice(index, 1);\n\n }\n\n }\n\n };\n\n listeners.removeAll = function () {\n\n allListeners.map(function (current) {\n\n listeners.remove(current.element, current.type, current.handler);\n\n });\n\n };\n\n listeners.get = function (element, eventType, handler) {\n\n return listeners.search.all(element, eventType, handler);\n\n };\n\n return listeners;\n\n}({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_listeners.js","/**\n * Codex Editor Notification Module\n *\n * @author Codex Team\n * @version 1.0\n */\n\nmodule.exports = (function (notifications) {\n\n let editor = codex.editor;\n\n var queue = [];\n\n var addToQueue = function (settings) {\n\n queue.push(settings);\n\n var index = 0;\n\n while ( index < queue.length && queue.length > 5) {\n\n if (queue[index].type == 'confirm' || queue[index].type == 'prompt') {\n\n index++;\n continue;\n\n }\n\n queue[index].close();\n queue.splice(index, 1);\n\n }\n\n };\n\n notifications.createHolder = function () {\n\n var holder = editor.draw.node('DIV', 'cdx-notifications-block');\n\n editor.nodes.notifications = document.body.appendChild(holder);\n\n return holder;\n\n };\n\n\n /**\n * Error notificator. Shows block with message\n * @protected\n */\n notifications.errorThrown = function (errorMsg, event) {\n\n editor.notifications.notification({message: 'This action is not available currently', type: event.type});\n\n };\n\n /**\n *\n * Appends notification\n *\n * settings = {\n * type - notification type (reserved types: alert, confirm, prompt). Just add class 'cdx-notification-'+type\n * message - notification message\n * okMsg - confirm button text (default - 'Ok')\n * cancelBtn - cancel button text (default - 'Cancel'). Only for confirm and prompt types\n * confirm - function-handler for ok button click\n * cancel - function-handler for cancel button click. Only for confirm and prompt types\n * time - time (in seconds) after which notification will close (default - 10s)\n * }\n *\n * @param settings\n */\n notifications.notification = function (constructorSettings) {\n\n /** Private vars and methods */\n var notification = null,\n cancel = null,\n type = null,\n confirm = null,\n inputField = null;\n\n var confirmHandler = function () {\n\n close();\n\n if (typeof confirm !== 'function' ) {\n\n return;\n\n }\n\n if (type == 'prompt') {\n\n confirm(inputField.value);\n return;\n\n }\n\n confirm();\n\n };\n\n var cancelHandler = function () {\n\n close();\n\n if (typeof cancel !== 'function' ) {\n\n return;\n\n }\n\n cancel();\n\n };\n\n\n /** Public methods */\n function create(settings) {\n\n if (!(settings && settings.message)) {\n\n editor.core.log('Can\\'t create notification. Message is missed');\n return;\n\n }\n\n settings.type = settings.type || 'alert';\n settings.time = settings.time*1000 || 10000;\n\n var wrapper = editor.draw.node('DIV', 'cdx-notification'),\n message = editor.draw.node('DIV', 'cdx-notification__message'),\n input = editor.draw.node('INPUT', 'cdx-notification__input'),\n okBtn = editor.draw.node('SPAN', 'cdx-notification__ok-btn'),\n cancelBtn = editor.draw.node('SPAN', 'cdx-notification__cancel-btn');\n\n message.textContent = settings.message;\n okBtn.textContent = settings.okMsg || 'ОК';\n cancelBtn.textContent = settings.cancelMsg || 'Отмена';\n\n editor.listeners.add(okBtn, 'click', confirmHandler);\n editor.listeners.add(cancelBtn, 'click', cancelHandler);\n\n wrapper.appendChild(message);\n\n if (settings.type == 'prompt') {\n\n wrapper.appendChild(input);\n\n }\n\n wrapper.appendChild(okBtn);\n\n if (settings.type == 'prompt' || settings.type == 'confirm') {\n\n wrapper.appendChild(cancelBtn);\n\n }\n\n wrapper.classList.add('cdx-notification-' + settings.type);\n wrapper.dataset.type = settings.type;\n\n notification = wrapper;\n type = settings.type;\n confirm = settings.confirm;\n cancel = settings.cancel;\n inputField = input;\n\n if (settings.type != 'prompt' && settings.type != 'confirm') {\n\n window.setTimeout(close, settings.time);\n\n }\n\n };\n\n /**\n * Show notification block\n */\n function send() {\n\n editor.nodes.notifications.appendChild(notification);\n inputField.focus();\n\n editor.nodes.notifications.classList.add('cdx-notification__notification-appending');\n\n window.setTimeout(function () {\n\n editor.nodes.notifications.classList.remove('cdx-notification__notification-appending');\n\n }, 100);\n\n addToQueue({type: type, close: close});\n\n };\n\n /**\n * Remove notification block\n */\n function close() {\n\n notification.remove();\n\n };\n\n\n if (constructorSettings) {\n\n create(constructorSettings);\n send();\n\n }\n\n return {\n create: create,\n send: send,\n close: close\n };\n\n };\n\n notifications.clear = function () {\n\n editor.nodes.notifications.innerHTML = '';\n queue = [];\n\n };\n\n return notifications;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_notifications.js","/**\n * Codex Editor Parser Module\n *\n * @author Codex Team\n * @version 1.1\n */\n\nmodule.exports = (function (parser) {\n\n let editor = codex.editor;\n\n /** inserting text */\n parser.insertPastedContent = function (blockType, tag) {\n\n editor.content.insertBlock({\n type : blockType.type,\n block : blockType.render({\n text : tag.innerHTML\n })\n });\n\n };\n\n /**\n * Check DOM node for display style: separated block or child-view\n */\n parser.isFirstLevelBlock = function (node) {\n\n return node.nodeType == editor.core.nodeTypes.TAG &&\n node.classList.contains(editor.ui.className.BLOCK_CLASSNAME);\n\n };\n\n return parser;\n\n})({});\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_parser.js","/**\n * Codex Editor Paste module\n *\n * @author Codex Team\n * @version 1.1.1\n */\n\nmodule.exports = function (paste) {\n\n let editor = codex.editor;\n\n var patterns = [];\n\n paste.prepare = function () {\n\n var tools = editor.tools;\n\n for (var tool in tools) {\n\n if (!tools[tool].renderOnPastePatterns || !Array.isArray(tools[tool].renderOnPastePatterns)) {\n\n continue;\n\n }\n\n tools[tool].renderOnPastePatterns.map(function (pattern) {\n\n\n patterns.push(pattern);\n\n });\n\n }\n\n return Promise.resolve();\n\n };\n\n /**\n * Saves data\n * @param event\n */\n paste.pasted = function (event) {\n\n var clipBoardData = event.clipboardData || window.clipboardData,\n content = clipBoardData.getData('Text');\n\n var result = analize(content);\n\n if (result) {\n\n event.preventDefault();\n event.stopImmediatePropagation();\n\n }\n\n return result;\n\n };\n\n /**\n * Analizes pated string and calls necessary method\n */\n\n var analize = function (string) {\n\n var result = false,\n content = editor.content.currentNode,\n plugin = content.dataset.tool;\n\n patterns.map( function (pattern) {\n\n var execArray = pattern.regex.exec(string),\n match = execArray && execArray[0];\n\n if ( match && match === string.trim()) {\n\n /** current block is not empty */\n if ( content.textContent.trim() && plugin == editor.settings.initialBlockPlugin ) {\n\n pasteToNewBlock_();\n\n }\n\n pattern.callback(string, pattern);\n result = true;\n\n }\n\n });\n\n return result;\n\n };\n\n var pasteToNewBlock_ = function () {\n\n /** Create new initial block */\n editor.content.insertBlock({\n\n type : editor.settings.initialBlockPlugin,\n block : editor.tools[editor.settings.initialBlockPlugin].render({\n text : ''\n })\n\n }, false);\n\n };\n\n /**\n * This method prevents default behaviour.\n *\n * @param {Object} event\n * @protected\n *\n * @description We get from clipboard pasted data, sanitize, make a fragment that contains of this sanitized nodes.\n * Firstly, we need to memorize the caret position. We can do that by getting the range of selection.\n * After all, we insert clear fragment into caret placed position. Then, we should move the caret to the last node\n */\n paste.blockPasteCallback = function (event) {\n\n\n if (!needsToHandlePasteEvent(event.target)) {\n\n return;\n\n }\n\n /** Prevent default behaviour */\n event.preventDefault();\n\n /** get html pasted data - dirty data */\n var htmlData = event.clipboardData.getData('text/html'),\n plainData = event.clipboardData.getData('text/plain');\n\n /** Temporary DIV that is used to work with text's paragraphs as DOM-elements*/\n var paragraphs = editor.draw.node('DIV', '', {}),\n cleanData,\n wrappedData;\n\n /** Create fragment, that we paste to range after proccesing */\n cleanData = editor.sanitizer.clean(htmlData);\n\n /**\n * We wrap pasted text with tags to split it logically\n * @type {string}\n */\n wrappedData = editor.content.wrapTextWithParagraphs(cleanData, plainData);\n paragraphs.innerHTML = wrappedData;\n\n /**\n * If there only one paragraph, just insert in at the caret location\n */\n if (paragraphs.childNodes.length == 1) {\n\n emulateUserAgentBehaviour(paragraphs.firstChild);\n return;\n\n }\n\n insertPastedParagraphs(paragraphs.childNodes);\n\n };\n\n /**\n * Checks if we should handle paste event on block\n * @param block\n *\n * @return {boolean}\n */\n var needsToHandlePasteEvent = function (block) {\n\n /** If area is input or textarea then allow default behaviour */\n if ( editor.core.isNativeInput(block) ) {\n\n return false;\n\n }\n\n var editableParent = editor.content.getEditableParent(block);\n\n /** Allow paste when event target placed in Editable element */\n if (!editableParent) {\n\n return false;\n\n }\n\n return true;\n\n };\n\n /**\n * Inserts new initial plugin blocks with data in paragraphs\n *\n * @param {Array} paragraphs - array of paragraphs (
) whit content, that should be inserted\n */\n var insertPastedParagraphs = function (paragraphs) {\n\n var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin,\n currentNode = editor.content.currentNode;\n\n\n paragraphs.forEach(function (paragraph) {\n\n /** Don't allow empty paragraphs */\n if (editor.core.isBlockEmpty(paragraph)) {\n\n return;\n\n }\n\n editor.content.insertBlock({\n type : NEW_BLOCK_TYPE,\n block : editor.tools[NEW_BLOCK_TYPE].render({\n text : paragraph.innerHTML\n })\n });\n\n editor.caret.inputIndex++;\n\n });\n\n editor.caret.setToPreviousBlock(editor.caret.getCurrentInputIndex() + 1);\n\n\n /**\n * If there was no data in working node, remove it\n */\n if (editor.core.isBlockEmpty(currentNode)) {\n\n currentNode.remove();\n editor.ui.saveInputs();\n\n }\n\n\n };\n\n /**\n * Inserts node content at the caret position\n *\n * @param {Node} node - DOM node (could be DocumentFragment), that should be inserted at the caret location\n */\n var emulateUserAgentBehaviour = function (node) {\n\n var newNode;\n\n if (node.childElementCount) {\n\n newNode = document.createDocumentFragment();\n\n node.childNodes.forEach(function (current) {\n\n if (!editor.core.isDomNode(current) && current.data.trim() === '') {\n\n return;\n\n }\n\n newNode.appendChild(current.cloneNode(true));\n\n });\n\n } else {\n\n newNode = document.createTextNode(node.textContent);\n\n }\n\n editor.caret.insertNode(newNode);\n\n };\n\n\n return paste;\n\n}({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_paste.js","/**\n * Codex Editor Renderer Module\n *\n * @author Codex Team\n * @version 1.0\n */\n\nmodule.exports = (function (renderer) {\n\n let editor = codex.editor;\n\n /**\n * Asyncronously parses input JSON to redactor blocks\n */\n renderer.makeBlocksFromData = function () {\n\n /**\n * If redactor is empty, add first paragraph to start writing\n */\n if (editor.core.isEmpty(editor.state.blocks) || !editor.state.blocks.items.length) {\n\n editor.ui.addInitialBlock();\n return;\n\n }\n\n Promise.resolve()\n\n /** First, get JSON from state */\n .then(function () {\n\n return editor.state.blocks;\n\n })\n\n /** Then, start to iterate they */\n .then(editor.renderer.appendBlocks)\n\n /** Write log if something goes wrong */\n .catch(function (error) {\n\n editor.core.log('Error while parsing JSON: %o', 'error', error);\n\n });\n\n };\n\n /**\n * Parses JSON to blocks\n * @param {object} data\n * @return Primise -> nodeList\n */\n renderer.appendBlocks = function (data) {\n\n var blocks = data.items;\n\n /**\n * Sequence of one-by-one blocks appending\n * Uses to save blocks order after async-handler\n */\n var nodeSequence = Promise.resolve();\n\n for (var index = 0; index < blocks.length ; index++ ) {\n\n /** Add node to sequence at specified index */\n editor.renderer.appendNodeAtIndex(nodeSequence, blocks, index);\n\n }\n\n };\n\n /**\n * Append node at specified index\n */\n renderer.appendNodeAtIndex = function (nodeSequence, blocks, index) {\n\n /** We need to append node to sequence */\n nodeSequence\n\n /** first, get node async-aware */\n .then(function () {\n\n return editor.renderer.getNodeAsync(blocks, index);\n\n })\n\n /**\n * second, compose editor-block from JSON object\n */\n .then(editor.renderer.createBlockFromData)\n\n /**\n * now insert block to redactor\n */\n .then(function (blockData) {\n\n /**\n * blockData has 'block', 'type' and 'stretched' information\n */\n editor.content.insertBlock(blockData);\n\n /** Pass created block to next step */\n return blockData.block;\n\n })\n\n /** Log if something wrong with node */\n .catch(function (error) {\n\n editor.core.log('Node skipped while parsing because %o', 'error', error);\n\n });\n\n };\n\n /**\n * Asynchronously returns block data from blocksList by index\n * @return Promise to node\n */\n renderer.getNodeAsync = function (blocksList, index) {\n\n return Promise.resolve().then(function () {\n\n return {\n tool : blocksList[index],\n position : index\n };\n\n });\n\n };\n\n /**\n * Creates editor block by JSON-data\n *\n * @uses render method of each plugin\n *\n * @param {Object} toolData.tool\n * { header : {\n * text: '',\n * type: 'H3', ...\n * }\n * }\n * @param {Number} toolData.position - index in input-blocks array\n * @return {Object} with type and Element\n */\n renderer.createBlockFromData = function ( toolData ) {\n\n /** New parser */\n var block,\n tool = toolData.tool,\n pluginName = tool.type;\n\n /** Get first key of object that stores plugin name */\n // for (var pluginName in blockData) break;\n\n /** Check for plugin existance */\n if (!editor.tools[pluginName]) {\n\n throw Error(`Plugin «${pluginName}» not found`);\n\n }\n\n /** Check for plugin having render method */\n if (typeof editor.tools[pluginName].render != 'function') {\n\n throw Error(`Plugin «${pluginName}» must have «render» method`);\n\n }\n\n if ( editor.tools[pluginName].available === false ) {\n\n block = editor.draw.unavailableBlock();\n\n block.innerHTML = editor.tools[pluginName].loadingMessage;\n\n /**\n * Saver will extract data from initial block data by position in array\n */\n block.dataset.inputPosition = toolData.position;\n\n } else {\n\n /** New Parser */\n block = editor.tools[pluginName].render(tool.data);\n\n }\n\n /** is first-level block stretched */\n var stretched = editor.tools[pluginName].isStretched || false;\n\n /** Retrun type and block */\n return {\n type : pluginName,\n block : block,\n stretched : stretched\n };\n\n };\n\n return renderer;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_renderer.js","/**\n * Codex Sanitizer\n */\n\nmodule.exports = (function (sanitizer) {\n\n /** HTML Janitor library */\n let janitor = require('html-janitor');\n\n /** Codex Editor */\n let editor = codex.editor;\n\n sanitizer.prepare = function () {\n\n if (editor.settings.sanitizer && !editor.core.isEmpty(editor.settings.sanitizer)) {\n\n Config.CUSTOM = editor.settings.sanitizer;\n\n }\n\n };\n\n /**\n * Basic config\n */\n var Config = {\n\n /** User configuration */\n CUSTOM : null,\n\n BASIC : {\n\n tags: {\n p: {},\n a: {\n href: true,\n target: '_blank',\n rel: 'nofollow'\n }\n }\n }\n };\n\n sanitizer.Config = Config;\n\n /**\n *\n * @param userCustomConfig\n * @returns {*}\n * @private\n *\n * @description If developer uses editor's API, then he can customize sane restrictions.\n * Or, sane config can be defined globally in editors initialization. That config will be used everywhere\n * At least, if there is no config overrides, that API uses BASIC Default configation\n */\n let init_ = function (userCustomConfig) {\n\n let configuration = userCustomConfig || Config.CUSTOM || Config.BASIC;\n\n return new janitor(configuration);\n\n };\n\n /**\n * Cleans string from unwanted tags\n * @protected\n * @param {String} dirtyString - taint string\n * @param {Object} customConfig - allowed tags\n */\n sanitizer.clean = function (dirtyString, customConfig) {\n\n let janitorInstance = init_(customConfig);\n\n return janitorInstance.clean(dirtyString);\n\n };\n\n return sanitizer;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_sanitizer.js","(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n define('html-janitor', factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.HTMLJanitor = factory();\n }\n}(this, function () {\n\n /**\n * @param {Object} config.tags Dictionary of allowed tags.\n * @param {boolean} config.keepNestedBlockElements Default false.\n */\n function HTMLJanitor(config) {\n\n var tagDefinitions = config['tags'];\n var tags = Object.keys(tagDefinitions);\n\n var validConfigValues = tags\n .map(function(k) { return typeof tagDefinitions[k]; })\n .every(function(type) { return type === 'object' || type === 'boolean' || type === 'function'; });\n\n if(!validConfigValues) {\n throw new Error(\"The configuration was invalid\");\n }\n\n this.config = config;\n }\n\n // TODO: not exhaustive?\n var blockElementNames = ['P', 'LI', 'TD', 'TH', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'PRE'];\n function isBlockElement(node) {\n return blockElementNames.indexOf(node.nodeName) !== -1;\n }\n\n var inlineElementNames = ['A', 'B', 'STRONG', 'I', 'EM', 'SUB', 'SUP', 'U', 'STRIKE'];\n function isInlineElement(node) {\n return inlineElementNames.indexOf(node.nodeName) !== -1;\n }\n\n HTMLJanitor.prototype.clean = function (html) {\n var sandbox = document.createElement('div');\n sandbox.innerHTML = html;\n\n this._sanitize(sandbox);\n\n return sandbox.innerHTML;\n };\n\n HTMLJanitor.prototype._sanitize = function (parentNode) {\n var treeWalker = createTreeWalker(parentNode);\n var node = treeWalker.firstChild();\n if (!node) { return; }\n\n do {\n // Ignore nodes that have already been sanitized\n if (node._sanitized) {\n continue;\n }\n\n if (node.nodeType === Node.TEXT_NODE) {\n // If this text node is just whitespace and the previous or next element\n // sibling is a block element, remove it\n // N.B.: This heuristic could change. Very specific to a bug with\n // `contenteditable` in Firefox: http://jsbin.com/EyuKase/1/edit?js,output\n // FIXME: make this an option?\n if (node.data.trim() === ''\n && ((node.previousElementSibling && isBlockElement(node.previousElementSibling))\n || (node.nextElementSibling && isBlockElement(node.nextElementSibling)))) {\n parentNode.removeChild(node);\n this._sanitize(parentNode);\n break;\n } else {\n continue;\n }\n }\n\n // Remove all comments\n if (node.nodeType === Node.COMMENT_NODE) {\n parentNode.removeChild(node);\n this._sanitize(parentNode);\n break;\n }\n\n var isInline = isInlineElement(node);\n var containsBlockElement;\n if (isInline) {\n containsBlockElement = Array.prototype.some.call(node.childNodes, isBlockElement);\n }\n\n // Block elements should not be nested (e.g. ...); if\n // they are, we want to unwrap the inner block element.\n var isNotTopContainer = !! parentNode.parentNode;\n var isNestedBlockElement =\n isBlockElement(parentNode) &&\n isBlockElement(node) &&\n isNotTopContainer;\n\n var nodeName = node.nodeName.toLowerCase();\n\n var allowedAttrs = getAllowedAttrs(this.config, nodeName, node);\n\n var isInvalid = isInline && containsBlockElement;\n\n // Drop tag entirely according to the whitelist *and* if the markup\n // is invalid.\n if (isInvalid || shouldRejectNode(node, allowedAttrs)\n || (!this.config.keepNestedBlockElements && isNestedBlockElement)) {\n // Do not keep the inner text of SCRIPT/STYLE elements.\n if (! (node.nodeName === 'SCRIPT' || node.nodeName === 'STYLE')) {\n while (node.childNodes.length > 0) {\n parentNode.insertBefore(node.childNodes[0], node);\n }\n }\n parentNode.removeChild(node);\n\n this._sanitize(parentNode);\n break;\n }\n\n // Sanitize attributes\n for (var a = 0; a < node.attributes.length; a += 1) {\n var attr = node.attributes[a];\n\n if (shouldRejectAttr(attr, allowedAttrs, node)) {\n node.removeAttribute(attr.name);\n // Shift the array to continue looping.\n a = a - 1;\n }\n }\n\n // Sanitize children\n this._sanitize(node);\n\n // Mark node as sanitized so it's ignored in future runs\n node._sanitized = true;\n } while ((node = treeWalker.nextSibling()));\n };\n\n function createTreeWalker(node) {\n return document.createTreeWalker(node,\n NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT,\n null, false);\n }\n\n function getAllowedAttrs(config, nodeName, node){\n if (typeof config.tags[nodeName] === 'function') {\n return config.tags[nodeName](node);\n } else {\n return config.tags[nodeName];\n }\n }\n\n function shouldRejectNode(node, allowedAttrs){\n if (typeof allowedAttrs === 'undefined') {\n return true;\n } else if (typeof allowedAttrs === 'boolean') {\n return !allowedAttrs;\n }\n\n return false;\n }\n\n function shouldRejectAttr(attr, allowedAttrs, node){\n var attrName = attr.name.toLowerCase();\n\n if (allowedAttrs === true){\n return false;\n } else if (typeof allowedAttrs[attrName] === 'function'){\n return !allowedAttrs[attrName](attr.value, node);\n } else if (typeof allowedAttrs[attrName] === 'undefined'){\n return true;\n } else if (allowedAttrs[attrName] === false) {\n return true;\n } else if (typeof allowedAttrs[attrName] === 'string') {\n return (allowedAttrs[attrName] !== attr.value);\n }\n\n return false;\n }\n\n return HTMLJanitor;\n\n}));\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/html-janitor/src/html-janitor.js\n// module id = 13\n// module chunks = 0","/**\n * Codex Editor Saver\n *\n * @author Codex Team\n * @version 1.1.0\n */\n\nmodule.exports = (function (saver) {\n\n let editor = codex.editor;\n\n /**\n * @public\n * Save blocks\n */\n saver.save = function () {\n\n /** Save html content of redactor to memory */\n editor.state.html = editor.nodes.redactor.innerHTML;\n\n /** Clean jsonOutput state */\n editor.state.jsonOutput = [];\n\n return saveBlocks(editor.nodes.redactor.childNodes);\n\n };\n\n /**\n * @private\n * Save each block data\n *\n * @param blocks\n * @returns {Promise.}\n */\n let saveBlocks = function (blocks) {\n\n let data = [];\n\n for(let index = 0; index < blocks.length; index++) {\n\n data.push(getBlockData(blocks[index]));\n\n }\n\n return Promise.all(data)\n .then(makeOutput)\n .catch(editor.core.log);\n\n };\n\n /** Save and validate block data */\n let getBlockData = function (block) {\n\n return saveBlockData(block)\n .then(validateBlockData)\n .catch(editor.core.log);\n\n };\n\n /**\n * @private\n * Call block`s plugin save method and return saved data\n *\n * @param block\n * @returns {Object}\n */\n let saveBlockData = function (block) {\n\n let pluginName = block.dataset.tool;\n\n /** Check for plugin existence */\n if (!editor.tools[pluginName]) {\n\n editor.core.log(`Plugin «${pluginName}» not found`, 'error');\n return {data: null, pluginName: null};\n\n }\n\n /** Check for plugin having save method */\n if (typeof editor.tools[pluginName].save !== 'function') {\n\n editor.core.log(`Plugin «${pluginName}» must have save method`, 'error');\n return {data: null, pluginName: null};\n\n }\n\n /** Result saver */\n let blockContent = block.childNodes[0],\n pluginsContent = blockContent.childNodes[0],\n position = pluginsContent.dataset.inputPosition;\n\n /** If plugin wasn't available then return data from cache */\n if ( editor.tools[pluginName].available === false ) {\n\n return Promise.resolve({data: codex.editor.state.blocks.items[position].data, pluginName});\n\n }\n\n return Promise.resolve(pluginsContent)\n .then(editor.tools[pluginName].save)\n .then(data => Object({data, pluginName}));\n\n };\n\n /**\n * Call plugin`s validate method. Return false if validation failed\n *\n * @param data\n * @param pluginName\n * @returns {Object|Boolean}\n */\n let validateBlockData = function ({data, pluginName}) {\n\n if (!data || !pluginName) {\n\n return false;\n\n }\n\n if (editor.tools[pluginName].validate) {\n\n let result = editor.tools[pluginName].validate(data);\n\n /**\n * Do not allow invalid data\n */\n if (!result) {\n\n return false;\n\n }\n\n }\n\n return {data, pluginName};\n\n\n };\n\n /**\n * Compile article output\n *\n * @param savedData\n * @returns {{time: number, version, items: (*|Array)}}\n */\n let makeOutput = function (savedData) {\n\n savedData = savedData.filter(blockData => blockData);\n\n let items = savedData.map(blockData => Object({type: blockData.pluginName, data: blockData.data}));\n\n editor.state.jsonOutput = items;\n\n return {\n id: editor.state.blocks.id || null,\n time: +new Date(),\n version: editor.version,\n items\n };\n\n };\n\n return saver;\n\n})({});\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_saver.js","/**\n *\n * Codex.Editor Transport Module\n *\n * @copyright 2017 Codex-Team\n * @version 1.2.0\n */\n\nmodule.exports = (function (transport) {\n\n let editor = codex.editor;\n\n\n /**\n * @private {Object} current XmlHttpRequest instance\n */\n var currentRequest = null;\n\n\n /**\n * @type {null} | {DOMElement} input - keeps input element in memory\n */\n transport.input = null;\n\n /**\n * @property {Object} arguments - keep plugin settings and defined callbacks\n */\n transport.arguments = null;\n\n /**\n * Prepares input element where will be files\n */\n transport.prepare = function () {\n\n let input = editor.draw.node( 'INPUT', '', { type : 'file' } );\n\n editor.listeners.add(input, 'change', editor.transport.fileSelected);\n editor.transport.input = input;\n\n };\n\n /** Clear input when files is uploaded */\n transport.clearInput = function () {\n\n /** Remove old input */\n transport.input = null;\n\n /** Prepare new one */\n transport.prepare();\n\n };\n\n /**\n * Callback for file selection\n * @param {Event} event\n */\n transport.fileSelected = function () {\n\n var input = this,\n i,\n files = input.files,\n formData = new FormData();\n\n if (editor.transport.arguments.multiple === true) {\n\n for ( i = 0; i < files.length; i++) {\n\n formData.append('files[]', files[i], files[i].name);\n\n }\n\n } else {\n\n formData.append('files', files[0], files[0].name);\n\n }\n\n currentRequest = editor.core.ajax({\n type : 'POST',\n data : formData,\n url : editor.transport.arguments.url,\n beforeSend : editor.transport.arguments.beforeSend,\n success : editor.transport.arguments.success,\n error : editor.transport.arguments.error,\n progress : editor.transport.arguments.progress\n });\n\n /** Clear input */\n transport.clearInput();\n\n };\n\n /**\n * Use plugin callbacks\n * @protected\n *\n * @param {Object} args - can have :\n * @param {String} args.url - fetch URL\n * @param {Function} args.beforeSend - function calls before sending ajax\n * @param {Function} args.success - success callback\n * @param {Function} args.error - on error handler\n * @param {Function} args.progress - xhr onprogress handler\n * @param {Boolean} args.multiple - allow select several files\n * @param {String} args.accept - adds accept attribute\n */\n transport.selectAndUpload = function (args) {\n\n transport.arguments = args;\n\n if ( args.multiple === true) {\n\n transport.input.setAttribute('multiple', 'multiple');\n\n }\n\n if ( args.accept ) {\n\n transport.input.setAttribute('accept', args.accept);\n\n }\n\n transport.input.click();\n\n };\n\n transport.abort = function () {\n\n currentRequest.abort();\n\n currentRequest = null;\n\n };\n\n return transport;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_transport.js","\nmodule.exports = class 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\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/eventDispatcher.js","/**\n * Inline toolbar\n *\n * Contains from tools:\n * Bold, Italic, Underline and Anchor\n *\n * @author Codex Team\n * @version 1.0\n */\n\nmodule.exports = (function (inline) {\n\n let editor = codex.editor;\n\n inline.buttonsOpened = null;\n inline.actionsOpened = null;\n inline.wrappersOffset = null;\n\n /**\n * saving selection that need for execCommand for styling\n *\n */\n inline.storedSelection = null;\n\n /**\n * @protected\n *\n * Open inline toobar\n */\n inline.show = function () {\n\n var currentNode = editor.content.currentNode,\n tool = currentNode.dataset.tool,\n plugin;\n\n /**\n * tool allowed to open inline toolbar\n */\n plugin = editor.tools[tool];\n\n if (!plugin.showInlineToolbar)\n return;\n\n var selectedText = inline.getSelectionText(),\n toolbar = editor.nodes.inlineToolbar.wrapper;\n\n if (selectedText.length > 0) {\n\n /** Move toolbar and open */\n editor.toolbar.inline.move();\n\n /** Open inline toolbar */\n toolbar.classList.add('opened');\n\n /** show buttons of inline toolbar */\n editor.toolbar.inline.showButtons();\n\n }\n\n };\n\n /**\n * @protected\n *\n * Closes inline toolbar\n */\n inline.close = function () {\n\n var toolbar = editor.nodes.inlineToolbar.wrapper;\n\n toolbar.classList.remove('opened');\n\n };\n\n /**\n * @private\n *\n * Moving toolbar\n */\n inline.move = function () {\n\n if (!this.wrappersOffset) {\n\n this.wrappersOffset = this.getWrappersOffset();\n\n }\n\n var coords = this.getSelectionCoords(),\n defaultOffset = 0,\n toolbar = editor.nodes.inlineToolbar.wrapper,\n newCoordinateX,\n newCoordinateY;\n\n if (toolbar.offsetHeight === 0) {\n\n defaultOffset = 40;\n\n }\n\n newCoordinateX = coords.x - this.wrappersOffset.left;\n newCoordinateY = coords.y + window.scrollY - this.wrappersOffset.top - defaultOffset - toolbar.offsetHeight;\n\n toolbar.style.transform = `translate3D(${Math.floor(newCoordinateX)}px, ${Math.floor(newCoordinateY)}px, 0)`;\n\n /** Close everything */\n editor.toolbar.inline.closeButtons();\n editor.toolbar.inline.closeAction();\n\n };\n\n /**\n * @private\n *\n * Tool Clicked\n */\n\n inline.toolClicked = function (event, type) {\n\n /**\n * For simple tools we use default browser function\n * For more complicated tools, we should write our own behavior\n */\n switch (type) {\n case 'createLink' : editor.toolbar.inline.createLinkAction(event, type); break;\n default : editor.toolbar.inline.defaultToolAction(type); break;\n }\n\n /**\n * highlight buttons\n * after making some action\n */\n editor.nodes.inlineToolbar.buttons.childNodes.forEach(editor.toolbar.inline.hightlight);\n\n };\n\n /**\n * @private\n *\n * Saving wrappers offset in DOM\n */\n inline.getWrappersOffset = function () {\n\n var wrapper = editor.nodes.wrapper,\n offset = this.getOffset(wrapper);\n\n this.wrappersOffset = offset;\n return offset;\n\n };\n\n /**\n * @private\n *\n * Calculates offset of DOM element\n *\n * @param el\n * @returns {{top: number, left: number}}\n */\n inline.getOffset = function ( el ) {\n\n var _x = 0;\n var _y = 0;\n\n while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {\n\n _x += (el.offsetLeft + el.clientLeft);\n _y += (el.offsetTop + el.clientTop);\n el = el.offsetParent;\n\n }\n return { top: _y, left: _x };\n\n };\n\n /**\n * @private\n *\n * Calculates position of selected text\n * @returns {{x: number, y: number}}\n */\n inline.getSelectionCoords = function () {\n\n var sel = document.selection, range;\n var x = 0, y = 0;\n\n if (sel) {\n\n if (sel.type != 'Control') {\n\n range = sel.createRange();\n range.collapse(true);\n x = range.boundingLeft;\n y = range.boundingTop;\n\n }\n\n } else if (window.getSelection) {\n\n sel = window.getSelection();\n\n if (sel.rangeCount) {\n\n range = sel.getRangeAt(0).cloneRange();\n if (range.getClientRects) {\n\n range.collapse(true);\n var rect = range.getClientRects()[0];\n\n if (!rect) {\n\n return;\n\n }\n\n x = rect.left;\n y = rect.top;\n\n }\n\n }\n\n }\n return { x: x, y: y };\n\n };\n\n /**\n * @private\n *\n * Returns selected text as String\n * @returns {string}\n */\n inline.getSelectionText = function () {\n\n var selectedText = '';\n\n // all modern browsers and IE9+\n if (window.getSelection) {\n\n selectedText = window.getSelection().toString();\n\n }\n\n return selectedText;\n\n };\n\n /** Opens buttons block */\n inline.showButtons = function () {\n\n var buttons = editor.nodes.inlineToolbar.buttons;\n\n buttons.classList.add('opened');\n\n editor.toolbar.inline.buttonsOpened = true;\n\n /** highlight buttons */\n editor.nodes.inlineToolbar.buttons.childNodes.forEach(editor.toolbar.inline.hightlight);\n\n };\n\n /** Makes buttons disappear */\n inline.closeButtons = function () {\n\n var buttons = editor.nodes.inlineToolbar.buttons;\n\n buttons.classList.remove('opened');\n\n editor.toolbar.inline.buttonsOpened = false;\n\n };\n\n /** Open buttons defined action if exist */\n inline.showActions = function () {\n\n var action = editor.nodes.inlineToolbar.actions;\n\n action.classList.add('opened');\n\n editor.toolbar.inline.actionsOpened = true;\n\n };\n\n /** Close actions block */\n inline.closeAction = function () {\n\n var action = editor.nodes.inlineToolbar.actions;\n\n action.innerHTML = '';\n action.classList.remove('opened');\n editor.toolbar.inline.actionsOpened = false;\n\n };\n\n\n /**\n * Callback for keydowns in inline toolbar \"Insert link...\" input\n */\n let inlineToolbarAnchorInputKeydown_ = function (event) {\n\n if (event.keyCode != editor.core.keys.ENTER) {\n\n return;\n\n }\n\n let editable = editor.content.currentNode,\n storedSelection = editor.toolbar.inline.storedSelection;\n\n editor.toolbar.inline.restoreSelection(editable, storedSelection);\n editor.toolbar.inline.setAnchor(this.value);\n\n /**\n * Preventing events that will be able to happen\n */\n event.preventDefault();\n event.stopImmediatePropagation();\n\n editor.toolbar.inline.clearRange();\n\n };\n\n /** Action for link creation or for setting anchor */\n inline.createLinkAction = function (event) {\n\n var isActive = this.isLinkActive();\n\n var editable = editor.content.currentNode,\n storedSelection = editor.toolbar.inline.saveSelection(editable);\n\n /** Save globally selection */\n editor.toolbar.inline.storedSelection = storedSelection;\n\n if (isActive) {\n\n\n /**\n * Changing stored selection. if we want to remove anchor from word\n * we should remove anchor from whole word, not only selected part.\n * The solution is than we get the length of current link\n * Change start position to - end of selection minus length of anchor\n */\n editor.toolbar.inline.restoreSelection(editable, storedSelection);\n\n editor.toolbar.inline.defaultToolAction('unlink');\n\n } else {\n\n /** Create input and close buttons */\n var action = editor.draw.inputForLink();\n\n editor.nodes.inlineToolbar.actions.appendChild(action);\n\n editor.toolbar.inline.closeButtons();\n editor.toolbar.inline.showActions();\n\n /**\n * focus to input\n * Solution: https://developer.mozilla.org/ru/docs/Web/API/HTMLElement/focus\n * Prevents event after showing input and when we need to focus an input which is in unexisted form\n */\n action.focus();\n event.preventDefault();\n\n /** Callback to link action */\n editor.listeners.add(action, 'keydown', inlineToolbarAnchorInputKeydown_, false);\n\n }\n\n };\n\n inline.isLinkActive = function () {\n\n var isActive = false;\n\n editor.nodes.inlineToolbar.buttons.childNodes.forEach(function (tool) {\n\n var dataType = tool.dataset.type;\n\n if (dataType == 'link' && tool.classList.contains('hightlighted')) {\n\n isActive = true;\n\n }\n\n });\n\n return isActive;\n\n };\n\n /** default action behavior of tool */\n inline.defaultToolAction = function (type) {\n\n document.execCommand(type, false, null);\n\n };\n\n /**\n * @private\n *\n * Sets URL\n *\n * @param {String} url - URL\n */\n inline.setAnchor = function (url) {\n\n document.execCommand('createLink', false, url);\n\n /** Close after URL inserting */\n editor.toolbar.inline.closeAction();\n\n };\n\n /**\n * @private\n *\n * Saves selection\n */\n inline.saveSelection = function (containerEl) {\n\n var range = window.getSelection().getRangeAt(0),\n preSelectionRange = range.cloneRange(),\n start;\n\n preSelectionRange.selectNodeContents(containerEl);\n preSelectionRange.setEnd(range.startContainer, range.startOffset);\n\n start = preSelectionRange.toString().length;\n\n return {\n start: start,\n end: start + range.toString().length\n };\n\n };\n\n /**\n * @private\n *\n * Sets to previous selection (Range)\n *\n * @param {Element} containerEl - editable element where we restore range\n * @param {Object} savedSel - range basic information to restore\n */\n inline.restoreSelection = function (containerEl, savedSel) {\n\n var range = document.createRange(),\n charIndex = 0;\n\n range.setStart(containerEl, 0);\n range.collapse(true);\n\n var nodeStack = [ containerEl ],\n node,\n foundStart = false,\n stop = false,\n nextCharIndex;\n\n while (!stop && (node = nodeStack.pop())) {\n\n if (node.nodeType == 3) {\n\n nextCharIndex = charIndex + node.length;\n\n if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {\n\n range.setStart(node, savedSel.start - charIndex);\n foundStart = true;\n\n }\n if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {\n\n range.setEnd(node, savedSel.end - charIndex);\n stop = true;\n\n }\n charIndex = nextCharIndex;\n\n } else {\n\n var i = node.childNodes.length;\n\n while (i--) {\n\n nodeStack.push(node.childNodes[i]);\n\n }\n\n }\n\n }\n\n var sel = window.getSelection();\n\n sel.removeAllRanges();\n sel.addRange(range);\n\n };\n\n /**\n * @private\n *\n * Removes all ranges from window selection\n */\n inline.clearRange = function () {\n\n var selection = window.getSelection();\n\n selection.removeAllRanges();\n\n };\n\n /**\n * @private\n *\n * sets or removes hightlight\n */\n inline.hightlight = function (tool) {\n\n var dataType = tool.dataset.type;\n\n if (document.queryCommandState(dataType)) {\n\n editor.toolbar.inline.setButtonHighlighted(tool);\n\n } else {\n\n editor.toolbar.inline.removeButtonsHighLight(tool);\n\n }\n\n /**\n *\n * hightlight for anchors\n */\n var selection = window.getSelection(),\n tag = selection.anchorNode.parentNode;\n\n if (tag.tagName == 'A' && dataType == 'link') {\n\n editor.toolbar.inline.setButtonHighlighted(tool);\n\n }\n\n };\n\n /**\n * @private\n *\n * Mark button if text is already executed\n */\n inline.setButtonHighlighted = function (button) {\n\n button.classList.add('hightlighted');\n\n /** At link tool we also change icon */\n if (button.dataset.type == 'link') {\n\n var icon = button.childNodes[0];\n\n icon.classList.remove('ce-icon-link');\n icon.classList.add('ce-icon-unlink');\n\n }\n\n };\n\n /**\n * @private\n *\n * Removes hightlight\n */\n inline.removeButtonsHighLight = function (button) {\n\n button.classList.remove('hightlighted');\n\n /** At link tool we also change icon */\n if (button.dataset.type == 'link') {\n\n var icon = button.childNodes[0];\n\n icon.classList.remove('ce-icon-unlink');\n icon.classList.add('ce-icon-link');\n\n }\n\n };\n\n\n return inline;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/toolbar/inline.js","/**\n * Toolbar settings\n *\n * @version 1.0.5\n */\n\nmodule.exports = (function (settings) {\n\n let editor = codex.editor;\n\n settings.opened = false;\n\n settings.setting = null;\n settings.actions = null;\n\n /**\n * Append and open settings\n */\n settings.open = function (toolType) {\n\n /**\n * Append settings content\n * It's stored in tool.settings\n */\n if ( !editor.tools[toolType] || !editor.tools[toolType].makeSettings ) {\n\n return;\n\n }\n\n /**\n * Draw settings block\n */\n var settingsBlock = editor.tools[toolType].makeSettings();\n\n editor.nodes.pluginSettings.appendChild(settingsBlock);\n\n\n /** Open settings block */\n editor.nodes.blockSettings.classList.add('opened');\n this.opened = true;\n\n };\n\n /**\n * Close and clear settings\n */\n settings.close = function () {\n\n editor.nodes.blockSettings.classList.remove('opened');\n editor.nodes.pluginSettings.innerHTML = '';\n\n this.opened = false;\n\n };\n\n /**\n * @param {string} toolType - plugin type\n */\n settings.toggle = function ( toolType ) {\n\n if ( !this.opened ) {\n\n this.open(toolType);\n\n } else {\n\n this.close();\n\n }\n\n };\n\n /**\n * Here we will draw buttons and add listeners to components\n */\n settings.makeRemoveBlockButton = function () {\n\n var removeBlockWrapper = editor.draw.node('SPAN', 'ce-toolbar__remove-btn', {}),\n settingButton = editor.draw.node('SPAN', 'ce-toolbar__remove-setting', { innerHTML : '' }),\n actionWrapper = editor.draw.node('DIV', 'ce-toolbar__remove-confirmation', {}),\n confirmAction = editor.draw.node('DIV', 'ce-toolbar__remove-confirm', { textContent : 'Удалить блок' }),\n cancelAction = editor.draw.node('DIV', 'ce-toolbar__remove-cancel', { textContent : 'Отмена' });\n\n editor.listeners.add(settingButton, 'click', editor.toolbar.settings.removeButtonClicked, false);\n\n editor.listeners.add(confirmAction, 'click', editor.toolbar.settings.confirmRemovingRequest, false);\n\n editor.listeners.add(cancelAction, 'click', editor.toolbar.settings.cancelRemovingRequest, false);\n\n actionWrapper.appendChild(confirmAction);\n actionWrapper.appendChild(cancelAction);\n\n removeBlockWrapper.appendChild(settingButton);\n removeBlockWrapper.appendChild(actionWrapper);\n\n /** Save setting */\n editor.toolbar.settings.setting = settingButton;\n editor.toolbar.settings.actions = actionWrapper;\n\n return removeBlockWrapper;\n\n };\n\n settings.removeButtonClicked = function () {\n\n var action = editor.toolbar.settings.actions;\n\n if (action.classList.contains('opened')) {\n\n editor.toolbar.settings.hideRemoveActions();\n\n } else {\n\n editor.toolbar.settings.showRemoveActions();\n\n }\n\n editor.toolbar.toolbox.close();\n editor.toolbar.settings.close();\n\n };\n\n settings.cancelRemovingRequest = function () {\n\n editor.toolbar.settings.actions.classList.remove('opened');\n\n };\n\n settings.confirmRemovingRequest = function () {\n\n var currentBlock = editor.content.currentNode,\n firstLevelBlocksCount;\n\n currentBlock.remove();\n\n firstLevelBlocksCount = editor.nodes.redactor.childNodes.length;\n\n /**\n * If all blocks are removed\n */\n if (firstLevelBlocksCount === 0) {\n\n /** update currentNode variable */\n editor.content.currentNode = null;\n\n /** Inserting new empty initial block */\n editor.ui.addInitialBlock();\n\n }\n\n editor.ui.saveInputs();\n\n editor.toolbar.close();\n\n };\n\n settings.showRemoveActions = function () {\n\n editor.toolbar.settings.actions.classList.add('opened');\n\n };\n\n settings.hideRemoveActions = function () {\n\n editor.toolbar.settings.actions.classList.remove('opened');\n\n };\n\n return settings;\n\n})({});\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/toolbar/settings.js","/**\n * Codex Editor toolbar module\n *\n * Contains:\n * - Inline toolbox\n * - Toolbox within plus button\n * - Settings section\n *\n * @author Codex Team\n * @version 1.0\n */\n\nmodule.exports = (function (toolbar) {\n\n let editor = codex.editor;\n\n toolbar.settings = require('./settings');\n toolbar.inline = require('./inline');\n toolbar.toolbox = require('./toolbox');\n\n /**\n * Margin between focused node and toolbar\n */\n toolbar.defaultToolbarHeight = 49;\n\n toolbar.defaultOffset = 34;\n\n toolbar.opened = false;\n\n toolbar.current = null;\n\n /**\n * @protected\n */\n toolbar.open = function () {\n\n if (editor.hideToolbar) {\n\n return;\n\n }\n\n let toolType = editor.content.currentNode.dataset.tool;\n\n if (!editor.tools[toolType] || !editor.tools[toolType].makeSettings ) {\n\n editor.nodes.showSettingsButton.classList.add('hide');\n\n } else {\n\n editor.nodes.showSettingsButton.classList.remove('hide');\n\n }\n\n editor.nodes.toolbar.classList.add('opened');\n this.opened = true;\n\n };\n\n /**\n * @protected\n */\n toolbar.close = function () {\n\n editor.nodes.toolbar.classList.remove('opened');\n\n toolbar.opened = false;\n toolbar.current = null;\n\n for (var button in editor.nodes.toolbarButtons) {\n\n editor.nodes.toolbarButtons[button].classList.remove('selected');\n\n }\n\n /** Close toolbox when toolbar is not displayed */\n editor.toolbar.toolbox.close();\n editor.toolbar.settings.close();\n\n };\n\n toolbar.toggle = function () {\n\n if ( !this.opened ) {\n\n this.open();\n\n } else {\n\n this.close();\n\n }\n\n };\n\n toolbar.hidePlusButton = function () {\n\n editor.nodes.plusButton.classList.add('hide');\n\n };\n\n toolbar.showPlusButton = function () {\n\n editor.nodes.plusButton.classList.remove('hide');\n\n };\n\n /**\n * Moving toolbar to the specified node\n */\n toolbar.move = function () {\n\n /** Close Toolbox when we move toolbar */\n editor.toolbar.toolbox.close();\n\n if (!editor.content.currentNode) {\n\n return;\n\n }\n\n var newYCoordinate = editor.content.currentNode.offsetTop - (editor.toolbar.defaultToolbarHeight / 2) + editor.toolbar.defaultOffset;\n\n editor.nodes.toolbar.style.transform = `translate3D(0, ${Math.floor(newYCoordinate)}px, 0)`;\n\n /** Close trash actions */\n editor.toolbar.settings.hideRemoveActions();\n\n };\n\n return toolbar;\n\n})({});\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/toolbar/toolbar.js","/**\n * Codex Editor toolbox\n *\n * All tools be able to appended here\n *\n * @author Codex Team\n * @version 1.0\n */\n\nmodule.exports = (function (toolbox) {\n\n let editor = codex.editor;\n\n toolbox.opened = false;\n toolbox.openedOnBlock = null;\n\n /** Shows toolbox */\n toolbox.open = function () {\n\n /** Close setting if toolbox is opened */\n if (editor.toolbar.settings.opened) {\n\n editor.toolbar.settings.close();\n\n }\n\n /** Add 'toolbar-opened' class for current block **/\n toolbox.openedOnBlock = editor.content.currentNode;\n toolbox.openedOnBlock.classList.add('toolbar-opened');\n\n /** display toolbox */\n editor.nodes.toolbox.classList.add('opened');\n\n /** Animate plus button */\n editor.nodes.plusButton.classList.add('clicked');\n\n /** toolbox state */\n editor.toolbar.toolbox.opened = true;\n\n };\n\n /** Closes toolbox */\n toolbox.close = function () {\n\n /** Remove 'toolbar-opened' class from current block **/\n if (toolbox.openedOnBlock) toolbox.openedOnBlock.classList.remove('toolbar-opened');\n toolbox.openedOnBlock = null;\n\n /** Makes toolbox disappear */\n editor.nodes.toolbox.classList.remove('opened');\n\n /** Rotate plus button */\n editor.nodes.plusButton.classList.remove('clicked');\n\n /** toolbox state */\n editor.toolbar.toolbox.opened = false;\n\n editor.toolbar.current = null;\n\n };\n\n toolbox.leaf = function () {\n\n let currentTool = editor.toolbar.current,\n tools = Object.keys(editor.tools),\n barButtons = editor.nodes.toolbarButtons,\n nextToolIndex = 0,\n toolToSelect,\n visibleTool,\n tool;\n\n if ( !currentTool ) {\n\n /** Get first tool from object*/\n for(tool in editor.tools) {\n\n if (editor.tools[tool].displayInToolbox) {\n\n break;\n\n }\n\n nextToolIndex ++;\n\n }\n\n } else {\n\n nextToolIndex = (tools.indexOf(currentTool) + 1) % tools.length;\n visibleTool = tools[nextToolIndex];\n\n while (!editor.tools[visibleTool].displayInToolbox) {\n\n nextToolIndex = (nextToolIndex + 1) % tools.length;\n visibleTool = tools[nextToolIndex];\n\n }\n\n }\n\n toolToSelect = tools[nextToolIndex];\n\n for ( var button in barButtons ) {\n\n barButtons[button].classList.remove('selected');\n\n }\n\n barButtons[toolToSelect].classList.add('selected');\n editor.toolbar.current = toolToSelect;\n\n };\n\n /**\n * Transforming selected node type into selected toolbar element type\n * @param {event} event\n */\n toolbox.toolClicked = function (event) {\n\n /**\n * UNREPLACEBLE_TOOLS this types of tools are forbidden to replace even they are empty\n */\n var UNREPLACEBLE_TOOLS = ['image', 'link', 'list', 'instagram', 'twitter', 'embed'],\n tool = editor.tools[editor.toolbar.current],\n workingNode = editor.content.currentNode,\n currentInputIndex = editor.caret.inputIndex,\n newBlockContent,\n appendCallback,\n blockData;\n\n /** Make block from plugin */\n newBlockContent = tool.render();\n\n /** information about block */\n blockData = {\n block : newBlockContent,\n type : tool.type,\n stretched : false\n };\n\n if (\n workingNode &&\n UNREPLACEBLE_TOOLS.indexOf(workingNode.dataset.tool) === -1 &&\n workingNode.textContent.trim() === ''\n ) {\n\n /** Replace current block */\n editor.content.switchBlock(workingNode, newBlockContent, tool.type);\n\n } else {\n\n /** Insert new Block from plugin */\n editor.content.insertBlock(blockData);\n\n /** increase input index */\n currentInputIndex++;\n\n }\n\n /** Fire tool append callback */\n appendCallback = tool.appendCallback;\n\n if (appendCallback && typeof appendCallback == 'function') {\n\n appendCallback.call(event);\n\n }\n\n window.setTimeout(function () {\n\n /** Set caret to current block */\n editor.caret.setToBlock(currentInputIndex);\n\n }, 10);\n\n\n /**\n * Changing current Node\n */\n editor.content.workingNodeChanged();\n\n /**\n * Move toolbar when node is changed\n */\n editor.toolbar.move();\n\n };\n\n return toolbox;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/toolbar/toolbox.js","module.exports = class Tools {\n\n constructor() {\n\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/components/modules/tools.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\n\n/**\n * @class\n *\n * @classdesc Makes CodeX Editor UI:\n * \n * \n * \n * \n * \n *\n * @property {EditorConfig} config - editor configuration {@link CodexEditor#configuration}\n * @property {Object} Editor - available editor modules {@link CodexEditor#moduleInstances}\n */\nmodule.exports = class UI {\n\n /**\n * Module key name\n * @returns {string}\n */\n static get name() {\n\n return 'ui';\n\n }\n\n /**\n * @constructor\n *\n * @param {EditorConfig} config\n */\n constructor( config ) {\n\n this.config = config;\n this.Editor = null;\n\n }\n\n\n /**\n * Editor modules setter\n * @param {object} Editor - available editor modules\n */\n set state(Editor) {\n\n this.Editor = Editor;\n\n }\n\n /**\n * @protected\n *\n * Making main interface\n */\n prepare() {\n\n console.log('ui prepare fired');\n\n return;\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/components/modules/ui.js"],"sourceRoot":""}
\ No newline at end of file
diff --git a/codex-editor.js b/codex-editor.js
index 601ed0fa..5bcce768 100644
--- a/codex-editor.js
+++ b/codex-editor.js
@@ -45,12 +45,6 @@ var CodexEditor =
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
- 'use strict';
-
- var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
/**
* Codex Editor
*
@@ -70,10 +64,20 @@ var CodexEditor =
* ...
*/
+ 'use strict';
+
/**
- * All Editor components
+ * Require Editor modules places in components/modules dir
*/
- var modules = [__webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"./src/modules/dom\""); e.code = 'MODULE_NOT_FOUND'; throw e; }())), __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"./src/modules/core\""); e.code = 'MODULE_NOT_FOUND'; throw e; }())), __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"./src/modules/ui\""); e.code = 'MODULE_NOT_FOUND'; throw e; }())), __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"./src/modules/tools\""); e.code = 'MODULE_NOT_FOUND'; throw e; }()))];
+
+ 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"); } }
+
+ var modules = editorModules.map(function (module) {
+
+ return __webpack_require__(1)("./" + module);
+ });
/**
* @class
@@ -104,17 +108,13 @@ var CodexEditor =
}]);
function CodexEditor(config) {
-
- 'use strict';
-
- /**
- * Configuration object
- */
-
var _this = this;
_classCallCheck(this, CodexEditor);
+ /**
+ * Configuration object
+ */
this.config = {};
/**
@@ -177,9 +177,15 @@ var CodexEditor =
modules.forEach(function (Module) {
- _this2.moduleInstances[Module.name] = new Module({
- config: _this2.configuration
- });
+ try {
+
+ _this2.moduleInstances[Module.name] = new Module({
+ config: _this2.configuration
+ });
+ } catch (e) {
+
+ console.log('Module %o skipped because %o', Module, e);
+ }
});
}
@@ -241,7 +247,7 @@ var CodexEditor =
return module.prepare();
};
- return Promise.resolve().then(prepareDecorator(this.moduleInstances['core'])).then(prepareDecorator(this.moduleInstances['ui'])).then(prepareDecorator(this.moduleInstances['tools'])).catch(function (error) {
+ return Promise.resolve().then(prepareDecorator(this.moduleInstances['ui'])).then(prepareDecorator(this.moduleInstances['tools'])).catch(function (error) {
console.log('Error occured', error);
});
@@ -387,6 +393,5461 @@ var CodexEditor =
//
// })({});
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ var map = {
+ "./_anchors": 2,
+ "./_anchors.js": 2,
+ "./_callbacks": 3,
+ "./_callbacks.js": 3,
+ "./_caret": 4,
+ "./_caret.js": 4,
+ "./_content": 5,
+ "./_content.js": 5,
+ "./_destroyer": 6,
+ "./_destroyer.js": 6,
+ "./_listeners": 7,
+ "./_listeners.js": 7,
+ "./_notifications": 8,
+ "./_notifications.js": 8,
+ "./_parser": 9,
+ "./_parser.js": 9,
+ "./_paste": 10,
+ "./_paste.js": 10,
+ "./_renderer": 11,
+ "./_renderer.js": 11,
+ "./_sanitizer": 12,
+ "./_sanitizer.js": 12,
+ "./_saver": 14,
+ "./_saver.js": 14,
+ "./_transport": 15,
+ "./_transport.js": 15,
+ "./eventDispatcher": 16,
+ "./eventDispatcher.js": 16,
+ "./toolbar/inline": 17,
+ "./toolbar/inline.js": 17,
+ "./toolbar/settings": 18,
+ "./toolbar/settings.js": 18,
+ "./toolbar/toolbar": 19,
+ "./toolbar/toolbar.js": 19,
+ "./toolbar/toolbox": 20,
+ "./toolbar/toolbox.js": 20,
+ "./tools": 21,
+ "./tools.js": 21,
+ "./ui": 22,
+ "./ui.js": 22
+ };
+ function webpackContext(req) {
+ return __webpack_require__(webpackContextResolve(req));
+ };
+ function webpackContextResolve(req) {
+ return map[req] || (function() { throw new Error("Cannot find module '" + req + "'.") }());
+ };
+ webpackContext.keys = function webpackContextKeys() {
+ return Object.keys(map);
+ };
+ webpackContext.resolve = webpackContextResolve;
+ module.exports = webpackContext;
+ webpackContext.id = 1;
+
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * Codex Editor Anchors module
+ *
+ * @author Codex Team
+ * @version 1.0
+ */
+
+ module.exports = function (anchors) {
+
+ var editor = codex.editor;
+
+ anchors.input = null;
+ anchors.currentNode = null;
+
+ anchors.settingsOpened = function (currentBlock) {
+
+ anchors.currentNode = currentBlock;
+ anchors.input.value = anchors.currentNode.dataset.anchor || '';
+ };
+
+ anchors.anchorChanged = function (e) {
+
+ var newAnchor = e.target.value = anchors.rusToTranslit(e.target.value);
+
+ anchors.currentNode.dataset.anchor = newAnchor;
+
+ if (newAnchor.trim() !== '') {
+
+ anchors.currentNode.classList.add(editor.ui.className.BLOCK_WITH_ANCHOR);
+ } else {
+
+ anchors.currentNode.classList.remove(editor.ui.className.BLOCK_WITH_ANCHOR);
+ }
+ };
+
+ anchors.keyDownOnAnchorInput = function (e) {
+
+ if (e.keyCode == editor.core.keys.ENTER) {
+
+ e.preventDefault();
+ e.stopPropagation();
+
+ e.target.blur();
+ editor.toolbar.settings.close();
+ }
+ };
+
+ anchors.keyUpOnAnchorInput = function (e) {
+
+ if (e.keyCode >= editor.core.keys.LEFT && e.keyCode <= editor.core.keys.DOWN) {
+
+ e.stopPropagation();
+ }
+ };
+
+ anchors.rusToTranslit = function (string) {
+
+ var ru = ['А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ь', 'Ы', 'Ь', 'Э', 'Ю', 'Я'],
+ en = ['A', 'B', 'V', 'G', 'D', 'E', 'E', 'Zh', 'Z', 'I', 'Y', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F', 'H', 'C', 'Ch', 'Sh', 'Sch', '', 'Y', '', 'E', 'Yu', 'Ya'];
+
+ for (var i = 0; i < ru.length; i++) {
+
+ string = string.split(ru[i]).join(en[i]);
+ string = string.split(ru[i].toLowerCase()).join(en[i].toLowerCase());
+ }
+
+ string = string.replace(/[^0-9a-zA-Z_]+/g, '-');
+
+ return string;
+ };
+
+ return anchors;
+ }({});
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * @module Codex Editor Callbacks module
+ * @description Module works with editor added Elements
+ *
+ * @author Codex Team
+ * @version 1.4.0
+ */
+
+ module.exports = function (callbacks) {
+
+ var editor = codex.editor;
+
+ /**
+ * used by UI module
+ * @description Routes all keydowns on document
+ * @param {Object} event
+ */
+ callbacks.globalKeydown = function (event) {
+
+ switch (event.keyCode) {
+ case editor.core.keys.ENTER:
+ enterKeyPressed_(event);break;
+ }
+ };
+
+ /**
+ * used by UI module
+ * @description Routes all keydowns on redactors area
+ * @param {Object} event
+ */
+ callbacks.redactorKeyDown = function (event) {
+
+ switch (event.keyCode) {
+ case editor.core.keys.TAB:
+ tabKeyPressedOnRedactorsZone_(event);break;
+ case editor.core.keys.ENTER:
+ enterKeyPressedOnRedactorsZone_(event);break;
+ case editor.core.keys.ESC:
+ escapeKeyPressedOnRedactorsZone_(event);break;
+ default:
+ defaultKeyPressedOnRedactorsZone_(event);break;
+ }
+ };
+
+ /**
+ * used by UI module
+ * @description Routes all keyup events
+ * @param {Object} event
+ */
+ callbacks.globalKeyup = function (event) {
+
+ switch (event.keyCode) {
+ case editor.core.keys.UP:
+ case editor.core.keys.LEFT:
+ case editor.core.keys.RIGHT:
+ case editor.core.keys.DOWN:
+ arrowKeyPressed_(event);break;
+ }
+ };
+
+ /**
+ * @param {Object} event
+ * @private
+ *
+ * Handles behaviour when tab pressed
+ * @description if Content is empty show toolbox (if it is closed) or leaf tools
+ * uses Toolbars toolbox module to handle the situation
+ */
+ var tabKeyPressedOnRedactorsZone_ = function tabKeyPressedOnRedactorsZone_(event) {
+
+ /**
+ * Wait for solution. Would like to know the behaviour
+ * @todo Add spaces
+ */
+ event.preventDefault();
+
+ if (!editor.core.isBlockEmpty(editor.content.currentNode)) {
+
+ return;
+ }
+
+ if (!editor.toolbar.opened) {
+
+ editor.toolbar.open();
+ }
+
+ if (editor.toolbar.opened && !editor.toolbar.toolbox.opened) {
+
+ editor.toolbar.toolbox.open();
+ } else {
+
+ editor.toolbar.toolbox.leaf();
+ }
+ };
+
+ /**
+ * Handles global EnterKey Press
+ * @see enterPressedOnBlock_
+ * @param {Object} event
+ */
+ var enterKeyPressed_ = function enterKeyPressed_() {
+
+ if (editor.content.editorAreaHightlighted) {
+
+ /**
+ * it means that we lose input index, saved index before is not correct
+ * therefore we need to set caret when we insert new block
+ */
+ editor.caret.inputIndex = -1;
+
+ enterPressedOnBlock_();
+ }
+ };
+
+ /**
+ * Callback for enter key pressing in first-level block area
+ *
+ * @param {Event} event
+ * @private
+ *
+ * @description Inserts new block with initial type from settings
+ */
+ var enterPressedOnBlock_ = function enterPressedOnBlock_() {
+
+ var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;
+
+ editor.content.insertBlock({
+ type: NEW_BLOCK_TYPE,
+ block: editor.tools[NEW_BLOCK_TYPE].render()
+ }, true);
+
+ editor.toolbar.move();
+ editor.toolbar.open();
+ };
+
+ /**
+ * ENTER key handler
+ *
+ * @param {Object} event
+ * @private
+ *
+ * @description Makes new block with initial type from settings
+ */
+ var enterKeyPressedOnRedactorsZone_ = function enterKeyPressedOnRedactorsZone_(event) {
+
+ if (event.target.contentEditable == 'true') {
+
+ /** Update input index */
+ editor.caret.saveCurrentInputIndex();
+ }
+
+ var currentInputIndex = editor.caret.getCurrentInputIndex() || 0,
+ workingNode = editor.content.currentNode,
+ tool = workingNode.dataset.tool,
+ isEnterPressedOnToolbar = editor.toolbar.opened && editor.toolbar.current && event.target == editor.state.inputs[currentInputIndex];
+
+ /** The list of tools which needs the default browser behaviour */
+ var enableLineBreaks = editor.tools[tool].enableLineBreaks;
+
+ /** This type of block creates when enter is pressed */
+ var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;
+
+ /**
+ * When toolbar is opened, select tool instead of making new paragraph
+ */
+ if (isEnterPressedOnToolbar) {
+
+ event.preventDefault();
+
+ editor.toolbar.toolbox.toolClicked(event);
+
+ editor.toolbar.close();
+
+ /**
+ * Stop other listeners callback executions
+ */
+ event.stopPropagation();
+ event.stopImmediatePropagation();
+
+ return;
+ }
+
+ /**
+ * Allow paragraph lineBreaks with shift enter
+ * Or if shiftkey pressed and enter and enabledLineBreaks, the let new block creation
+ */
+ if (event.shiftKey || enableLineBreaks) {
+
+ event.stopPropagation();
+ event.stopImmediatePropagation();
+ return;
+ }
+
+ var currentSelection = window.getSelection(),
+ currentSelectedNode = currentSelection.anchorNode,
+ caretAtTheEndOfText = editor.caret.position.atTheEnd(),
+ isTextNodeHasParentBetweenContenteditable = false;
+
+ /**
+ * Allow making new in same block by SHIFT+ENTER and forbids to prevent default browser behaviour
+ */
+ if (event.shiftKey && !enableLineBreaks) {
+
+ editor.callback.enterPressedOnBlock(editor.content.currentBlock, event);
+ event.preventDefault();
+ return;
+ }
+
+ /**
+ * Workaround situation when caret at the Text node that has some wrapper Elements
+ * Split block cant handle this.
+ * We need to save default behavior
+ */
+ isTextNodeHasParentBetweenContenteditable = currentSelectedNode && currentSelectedNode.parentNode.contentEditable != 'true';
+
+ /**
+ * Split blocks when input has several nodes and caret placed in textNode
+ */
+ if (currentSelectedNode.nodeType == editor.core.nodeTypes.TEXT && !isTextNodeHasParentBetweenContenteditable && !caretAtTheEndOfText) {
+
+ event.preventDefault();
+
+ editor.core.log('Splitting Text node...');
+
+ editor.content.splitBlock(currentInputIndex);
+
+ /** Show plus button when next input after split is empty*/
+ if (!editor.state.inputs[currentInputIndex + 1].textContent.trim()) {
+
+ editor.toolbar.showPlusButton();
+ }
+ } else {
+
+ var islastNode = editor.content.isLastNode(currentSelectedNode);
+
+ if (islastNode && caretAtTheEndOfText) {
+
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopImmediatePropagation();
+
+ editor.core.log('ENTER clicked in last textNode. Create new BLOCK');
+
+ editor.content.insertBlock({
+ type: NEW_BLOCK_TYPE,
+ block: editor.tools[NEW_BLOCK_TYPE].render()
+ }, true);
+
+ editor.toolbar.move();
+ editor.toolbar.open();
+
+ /** Show plus button with empty block */
+ editor.toolbar.showPlusButton();
+ }
+ }
+
+ /** get all inputs after new appending block */
+ editor.ui.saveInputs();
+ };
+
+ /**
+ * Escape behaviour
+ * @param event
+ * @private
+ *
+ * @description Closes toolbox and toolbar. Prevents default behaviour
+ */
+ var escapeKeyPressedOnRedactorsZone_ = function escapeKeyPressedOnRedactorsZone_(event) {
+
+ /** Close all toolbar */
+ editor.toolbar.close();
+
+ /** Close toolbox */
+ editor.toolbar.toolbox.close();
+
+ event.preventDefault();
+ };
+
+ /**
+ * @param {Event} event
+ * @private
+ *
+ * closes and moves toolbar
+ */
+ var arrowKeyPressed_ = function arrowKeyPressed_(event) {
+
+ editor.content.workingNodeChanged();
+
+ /* Closing toolbar */
+ editor.toolbar.close();
+ editor.toolbar.move();
+ };
+
+ /**
+ * @private
+ * @param {Event} event
+ *
+ * @description Closes all opened bars from toolbar.
+ * If block is mark, clears highlightning
+ */
+ var defaultKeyPressedOnRedactorsZone_ = function defaultKeyPressedOnRedactorsZone_() {
+
+ editor.toolbar.close();
+
+ if (!editor.toolbar.inline.actionsOpened) {
+
+ editor.toolbar.inline.close();
+ editor.content.clearMark();
+ }
+ };
+
+ /**
+ * Handler when clicked on redactors area
+ *
+ * @protected
+ * @param event
+ *
+ * @description Detects clicked area. If it is first-level block area, marks as detected and
+ * on next enter press will be inserted new block
+ * Otherwise, save carets position (input index) and put caret to the editable zone.
+ *
+ * @see detectWhenClickedOnFirstLevelBlockArea_
+ *
+ */
+ callbacks.redactorClicked = function (event) {
+
+ detectWhenClickedOnFirstLevelBlockArea_();
+
+ editor.content.workingNodeChanged(event.target);
+ editor.ui.saveInputs();
+
+ var selectedText = editor.toolbar.inline.getSelectionText(),
+ firstLevelBlock;
+
+ /** If selection range took off, then we hide inline toolbar */
+ if (selectedText.length === 0) {
+
+ editor.toolbar.inline.close();
+ }
+
+ /** Update current input index in memory when caret focused into existed input */
+ if (event.target.contentEditable == 'true') {
+
+ editor.caret.saveCurrentInputIndex();
+ }
+
+ if (editor.content.currentNode === null) {
+
+ /**
+ * If inputs in redactor does not exits, then we put input index 0 not -1
+ */
+ var indexOfLastInput = editor.state.inputs.length > 0 ? editor.state.inputs.length - 1 : 0;
+
+ /** If we have any inputs */
+ if (editor.state.inputs.length) {
+
+ /** getting firstlevel parent of input */
+ firstLevelBlock = editor.content.getFirstLevelBlock(editor.state.inputs[indexOfLastInput]);
+ }
+
+ /** If input is empty, then we set caret to the last input */
+ if (editor.state.inputs.length && editor.state.inputs[indexOfLastInput].textContent === '' && firstLevelBlock.dataset.tool == editor.settings.initialBlockPlugin) {
+
+ editor.caret.setToBlock(indexOfLastInput);
+ } else {
+
+ /** Create new input when caret clicked in redactors area */
+ var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;
+
+ editor.content.insertBlock({
+ type: NEW_BLOCK_TYPE,
+ block: editor.tools[NEW_BLOCK_TYPE].render()
+ });
+
+ /** If there is no inputs except inserted */
+ if (editor.state.inputs.length === 1) {
+
+ editor.caret.setToBlock(indexOfLastInput);
+ } else {
+
+ /** Set caret to this appended input */
+ editor.caret.setToNextBlock(indexOfLastInput);
+ }
+ }
+ } else {
+
+ /** Close all panels */
+ editor.toolbar.settings.close();
+ editor.toolbar.toolbox.close();
+ }
+
+ /**
+ * Move toolbar and open
+ */
+ editor.toolbar.move();
+ editor.toolbar.open();
+
+ var inputIsEmpty = !editor.content.currentNode.textContent.trim(),
+ currentNodeType = editor.content.currentNode.dataset.tool,
+ isInitialType = currentNodeType == editor.settings.initialBlockPlugin;
+
+ /** Hide plus buttons */
+ editor.toolbar.hidePlusButton();
+
+ if (!inputIsEmpty) {
+
+ /** Mark current block */
+ editor.content.markBlock();
+ }
+
+ if (isInitialType && inputIsEmpty) {
+
+ /** Show plus button */
+ editor.toolbar.showPlusButton();
+ }
+ };
+
+ /**
+ * This method allows to define, is caret in contenteditable element or not.
+ *
+ * @private
+ *
+ * @description Otherwise, if we get TEXT node from range container, that will means we have input index.
+ * In this case we use default browsers behaviour (if plugin allows that) or overwritten action.
+ * Therefore, to be sure that we've clicked first-level block area, we should have currentNode, which always
+ * specifies to the first-level block. Other cases we just ignore.
+ */
+ var detectWhenClickedOnFirstLevelBlockArea_ = function detectWhenClickedOnFirstLevelBlockArea_() {
+
+ var selection = window.getSelection(),
+ anchorNode = selection.anchorNode,
+ flag = false;
+
+ if (selection.rangeCount === 0) {
+
+ editor.content.editorAreaHightlighted = true;
+ } else {
+
+ if (!editor.core.isDomNode(anchorNode)) {
+
+ anchorNode = anchorNode.parentNode;
+ }
+
+ /** Already founded, without loop */
+ if (anchorNode.contentEditable == 'true') {
+
+ flag = true;
+ }
+
+ while (anchorNode.contentEditable != 'true') {
+
+ anchorNode = anchorNode.parentNode;
+
+ if (anchorNode.contentEditable == 'true') {
+
+ flag = true;
+ }
+
+ if (anchorNode == document.body) {
+
+ break;
+ }
+ }
+
+ /** If editable element founded, flag is "TRUE", Therefore we return "FALSE" */
+ editor.content.editorAreaHightlighted = !flag;
+ }
+ };
+
+ /**
+ * Toolbar button click handler
+ *
+ * @param {Object} event - cursor to the button
+ * @protected
+ *
+ * @description gets current tool and calls render method
+ */
+ callbacks.toolbarButtonClicked = function (event) {
+
+ var button = this;
+
+ editor.toolbar.current = button.dataset.type;
+
+ editor.toolbar.toolbox.toolClicked(event);
+ editor.toolbar.close();
+ };
+
+ /**
+ * Show or Hide toolbox when plus button is clicked
+ */
+ callbacks.plusButtonClicked = function () {
+
+ if (!editor.nodes.toolbox.classList.contains('opened')) {
+
+ editor.toolbar.toolbox.open();
+ } else {
+
+ editor.toolbar.toolbox.close();
+ }
+ };
+
+ /**
+ * Block handlers for KeyDown events
+ *
+ * @protected
+ * @param {Object} event
+ *
+ * Handles keydowns on block
+ * @see blockRightOrDownArrowPressed_
+ * @see backspacePressed_
+ * @see blockLeftOrUpArrowPressed_
+ */
+ callbacks.blockKeydown = function (event) {
+
+ var block = event.target; // event.target is input
+
+ switch (event.keyCode) {
+
+ case editor.core.keys.DOWN:
+ case editor.core.keys.RIGHT:
+ blockRightOrDownArrowPressed_(event);
+ break;
+
+ case editor.core.keys.BACKSPACE:
+ backspacePressed_(block, event);
+ break;
+
+ case editor.core.keys.UP:
+ case editor.core.keys.LEFT:
+ blockLeftOrUpArrowPressed_(event);
+ break;
+
+ }
+ };
+
+ /**
+ * RIGHT or DOWN keydowns on block
+ *
+ * @param {Object} event
+ * @private
+ *
+ * @description watches the selection and gets closest editable element.
+ * Uses method getDeepestTextNodeFromPosition to get the last node of next block
+ * Sets caret if it is contenteditable
+ */
+ var blockRightOrDownArrowPressed_ = function blockRightOrDownArrowPressed_(event) {
+
+ var selection = window.getSelection(),
+ inputs = editor.state.inputs,
+ focusedNode = selection.anchorNode,
+ focusedNodeHolder;
+
+ /** Check for caret existance */
+ if (!focusedNode) {
+
+ return false;
+ }
+
+ /** Looking for closest (parent) contentEditable element of focused node */
+ while (focusedNode.contentEditable != 'true') {
+
+ focusedNodeHolder = focusedNode.parentNode;
+ focusedNode = focusedNodeHolder;
+ }
+
+ /** Input index in DOM level */
+ var editableElementIndex = 0;
+
+ while (focusedNode != inputs[editableElementIndex]) {
+
+ editableElementIndex++;
+ }
+
+ /**
+ * Founded contentEditable element doesn't have childs
+ * Or maybe New created block
+ */
+ if (!focusedNode.textContent) {
+
+ editor.caret.setToNextBlock(editableElementIndex);
+ return;
+ }
+
+ /**
+ * Do nothing when caret doesn not reaches the end of last child
+ */
+ var caretInLastChild = false,
+ caretAtTheEndOfText = false;
+
+ var lastChild, deepestTextnode;
+
+ lastChild = focusedNode.childNodes[focusedNode.childNodes.length - 1];
+
+ if (editor.core.isDomNode(lastChild)) {
+
+ deepestTextnode = editor.content.getDeepestTextNodeFromPosition(lastChild, lastChild.childNodes.length);
+ } else {
+
+ deepestTextnode = lastChild;
+ }
+
+ caretInLastChild = selection.anchorNode == deepestTextnode;
+ caretAtTheEndOfText = deepestTextnode.length == selection.anchorOffset;
+
+ if (!caretInLastChild || !caretAtTheEndOfText) {
+
+ editor.core.log('arrow [down|right] : caret does not reached the end');
+ return false;
+ }
+
+ editor.caret.setToNextBlock(editableElementIndex);
+ };
+
+ /**
+ * LEFT or UP keydowns on block
+ *
+ * @param {Object} event
+ * @private
+ *
+ * watches the selection and gets closest editable element.
+ * Uses method getDeepestTextNodeFromPosition to get the last node of previous block
+ * Sets caret if it is contenteditable
+ *
+ */
+ var blockLeftOrUpArrowPressed_ = function blockLeftOrUpArrowPressed_(event) {
+
+ var selection = window.getSelection(),
+ inputs = editor.state.inputs,
+ focusedNode = selection.anchorNode,
+ focusedNodeHolder;
+
+ /** Check for caret existance */
+ if (!focusedNode) {
+
+ return false;
+ }
+
+ /**
+ * LEFT or UP not at the beginning
+ */
+ if (selection.anchorOffset !== 0) {
+
+ return false;
+ }
+
+ /** Looking for parent contentEditable block */
+ while (focusedNode.contentEditable != 'true') {
+
+ focusedNodeHolder = focusedNode.parentNode;
+ focusedNode = focusedNodeHolder;
+ }
+
+ /** Input index in DOM level */
+ var editableElementIndex = 0;
+
+ while (focusedNode != inputs[editableElementIndex]) {
+
+ editableElementIndex++;
+ }
+
+ /**
+ * Do nothing if caret is not at the beginning of first child
+ */
+ var caretInFirstChild = false,
+ caretAtTheBeginning = false;
+
+ var firstChild, deepestTextnode;
+
+ /**
+ * Founded contentEditable element doesn't have childs
+ * Or maybe New created block
+ */
+ if (!focusedNode.textContent) {
+
+ editor.caret.setToPreviousBlock(editableElementIndex);
+ return;
+ }
+
+ firstChild = focusedNode.childNodes[0];
+
+ if (editor.core.isDomNode(firstChild)) {
+
+ deepestTextnode = editor.content.getDeepestTextNodeFromPosition(firstChild, 0);
+ } else {
+
+ deepestTextnode = firstChild;
+ }
+
+ caretInFirstChild = selection.anchorNode == deepestTextnode;
+ caretAtTheBeginning = selection.anchorOffset === 0;
+
+ if (caretInFirstChild && caretAtTheBeginning) {
+
+ editor.caret.setToPreviousBlock(editableElementIndex);
+ }
+ };
+
+ /**
+ * Handles backspace keydown
+ *
+ * @param {Element} block
+ * @param {Object} event
+ * @private
+ *
+ * @description if block is empty, delete the block and set caret to the previous block
+ * If block is not empty, try to merge two blocks - current and previous
+ * But it we try'n to remove first block, then we should set caret to the next block, not previous.
+ * If we removed the last block, create new one
+ */
+ var backspacePressed_ = function backspacePressed_(block, event) {
+
+ var currentInputIndex = editor.caret.getCurrentInputIndex(),
+ range,
+ selectionLength,
+ firstLevelBlocksCount;
+
+ if (editor.core.isNativeInput(event.target)) {
+
+ /** If input value is empty - remove block */
+ if (event.target.value.trim() == '') {
+
+ block.remove();
+ } else {
+
+ return;
+ }
+ }
+
+ if (block.textContent.trim()) {
+
+ range = editor.content.getRange();
+ selectionLength = range.endOffset - range.startOffset;
+
+ if (editor.caret.position.atStart() && !selectionLength && editor.state.inputs[currentInputIndex - 1]) {
+
+ editor.content.mergeBlocks(currentInputIndex);
+ } else {
+
+ return;
+ }
+ }
+
+ if (!selectionLength) {
+
+ block.remove();
+ }
+
+ firstLevelBlocksCount = editor.nodes.redactor.childNodes.length;
+
+ /**
+ * If all blocks are removed
+ */
+ if (firstLevelBlocksCount === 0) {
+
+ /** update currentNode variable */
+ editor.content.currentNode = null;
+
+ /** Inserting new empty initial block */
+ editor.ui.addInitialBlock();
+
+ /** Updating inputs state after deleting last block */
+ editor.ui.saveInputs();
+
+ /** Set to current appended block */
+ window.setTimeout(function () {
+
+ editor.caret.setToPreviousBlock(1);
+ }, 10);
+ } else {
+
+ if (editor.caret.inputIndex !== 0) {
+
+ /** Target block is not first */
+ editor.caret.setToPreviousBlock(editor.caret.inputIndex);
+ } else {
+
+ /** If we try to delete first block */
+ editor.caret.setToNextBlock(editor.caret.inputIndex);
+ }
+ }
+
+ editor.toolbar.move();
+
+ if (!editor.toolbar.opened) {
+
+ editor.toolbar.open();
+ }
+
+ /** Updating inputs state */
+ editor.ui.saveInputs();
+
+ /** Prevent default browser behaviour */
+ event.preventDefault();
+ };
+
+ /**
+ * used by UI module
+ * Clicks on block settings button
+ *
+ * @param {Object} event
+ * @protected
+ * @description Opens toolbar settings
+ */
+ callbacks.showSettingsButtonClicked = function (event) {
+
+ /**
+ * Get type of current block
+ * It uses to append settings from tool.settings property.
+ * ...
+ * Type is stored in data-type attribute on block
+ */
+ var currentToolType = editor.content.currentNode.dataset.tool;
+
+ editor.toolbar.settings.toggle(currentToolType);
+
+ /** Close toolbox when settings button is active */
+ editor.toolbar.toolbox.close();
+ editor.toolbar.settings.hideRemoveActions();
+ };
+
+ return callbacks;
+ }({});
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * Codex Editor Caret Module
+ *
+ * @author Codex Team
+ * @version 1.0
+ */
+
+ module.exports = function (caret) {
+
+ var editor = codex.editor;
+
+ /**
+ * @var {int} InputIndex - editable element in DOM
+ */
+ caret.inputIndex = null;
+
+ /**
+ * @var {int} offset - caret position in a text node.
+ */
+ caret.offset = null;
+
+ /**
+ * @var {int} focusedNodeIndex - we get index of child node from first-level block
+ */
+ caret.focusedNodeIndex = null;
+
+ /**
+ * Creates Document Range and sets caret to the element.
+ * @protected
+ * @uses caret.save — if you need to save caret position
+ * @param {Element} el - Changed Node.
+ */
+ caret.set = function (el, index, offset) {
+
+ offset = offset || caret.offset || 0;
+ index = index || caret.focusedNodeIndex || 0;
+
+ var childs = el.childNodes,
+ nodeToSet;
+
+ if (childs.length === 0) {
+
+ nodeToSet = el;
+ } else {
+
+ nodeToSet = childs[index];
+ }
+
+ /** If Element is INPUT */
+ if (el.contentEditable != 'true') {
+
+ el.focus();
+ return;
+ }
+
+ if (editor.core.isDomNode(nodeToSet)) {
+
+ nodeToSet = editor.content.getDeepestTextNodeFromPosition(nodeToSet, nodeToSet.childNodes.length);
+ }
+
+ var range = document.createRange(),
+ selection = window.getSelection();
+
+ window.setTimeout(function () {
+
+ range.setStart(nodeToSet, offset);
+ range.setEnd(nodeToSet, offset);
+
+ selection.removeAllRanges();
+ selection.addRange(range);
+
+ editor.caret.saveCurrentInputIndex();
+ }, 20);
+ };
+
+ /**
+ * @protected
+ * Updates index of input and saves it in caret object
+ */
+ caret.saveCurrentInputIndex = function () {
+
+ /** Index of Input that we paste sanitized content */
+ var selection = window.getSelection(),
+ inputs = editor.state.inputs,
+ focusedNode = selection.anchorNode,
+ focusedNodeHolder;
+
+ if (!focusedNode) {
+
+ return;
+ }
+
+ /** Looking for parent contentEditable block */
+ while (focusedNode.contentEditable != 'true') {
+
+ focusedNodeHolder = focusedNode.parentNode;
+ focusedNode = focusedNodeHolder;
+ }
+
+ /** Input index in DOM level */
+ var editableElementIndex = 0;
+
+ while (focusedNode != inputs[editableElementIndex]) {
+
+ editableElementIndex++;
+ }
+
+ caret.inputIndex = editableElementIndex;
+ };
+
+ /**
+ * Returns current input index (caret object)
+ */
+ caret.getCurrentInputIndex = function () {
+
+ return caret.inputIndex;
+ };
+
+ /**
+ * @param {int} index - index of first-level block after that we set caret into next input
+ */
+ caret.setToNextBlock = function (index) {
+
+ var inputs = editor.state.inputs,
+ nextInput = inputs[index + 1];
+
+ if (!nextInput) {
+
+ editor.core.log('We are reached the end');
+ return;
+ }
+
+ /**
+ * When new Block created or deleted content of input
+ * We should add some text node to set caret
+ */
+ if (!nextInput.childNodes.length) {
+
+ var emptyTextElement = document.createTextNode('');
+
+ nextInput.appendChild(emptyTextElement);
+ }
+
+ editor.caret.inputIndex = index + 1;
+ editor.caret.set(nextInput, 0, 0);
+ editor.content.workingNodeChanged(nextInput);
+ };
+
+ /**
+ * @param {int} index - index of target input.
+ * Sets caret to input with this index
+ */
+ caret.setToBlock = function (index) {
+
+ var inputs = editor.state.inputs,
+ targetInput = inputs[index];
+
+ if (!targetInput) {
+
+ return;
+ }
+
+ /**
+ * When new Block created or deleted content of input
+ * We should add some text node to set caret
+ */
+ if (!targetInput.childNodes.length) {
+
+ var emptyTextElement = document.createTextNode('');
+
+ targetInput.appendChild(emptyTextElement);
+ }
+
+ editor.caret.inputIndex = index;
+ editor.caret.set(targetInput, 0, 0);
+ editor.content.workingNodeChanged(targetInput);
+ };
+
+ /**
+ * @param {int} index - index of input
+ */
+ caret.setToPreviousBlock = function (index) {
+
+ index = index || 0;
+
+ var inputs = editor.state.inputs,
+ previousInput = inputs[index - 1],
+ lastChildNode,
+ lengthOfLastChildNode,
+ emptyTextElement;
+
+ if (!previousInput) {
+
+ editor.core.log('We are reached first node');
+ return;
+ }
+
+ lastChildNode = editor.content.getDeepestTextNodeFromPosition(previousInput, previousInput.childNodes.length);
+ lengthOfLastChildNode = lastChildNode.length;
+
+ /**
+ * When new Block created or deleted content of input
+ * We should add some text node to set caret
+ */
+ if (!previousInput.childNodes.length) {
+
+ emptyTextElement = document.createTextNode('');
+ previousInput.appendChild(emptyTextElement);
+ }
+ editor.caret.inputIndex = index - 1;
+ editor.caret.set(previousInput, previousInput.childNodes.length - 1, lengthOfLastChildNode);
+ editor.content.workingNodeChanged(inputs[index - 1]);
+ };
+
+ caret.position = {
+
+ atStart: function atStart() {
+
+ var selection = window.getSelection(),
+ anchorOffset = selection.anchorOffset,
+ anchorNode = selection.anchorNode,
+ firstLevelBlock = editor.content.getFirstLevelBlock(anchorNode),
+ pluginsRender = firstLevelBlock.childNodes[0];
+
+ if (!editor.core.isDomNode(anchorNode)) {
+
+ anchorNode = anchorNode.parentNode;
+ }
+
+ var isFirstNode = anchorNode === pluginsRender.childNodes[0],
+ isOffsetZero = anchorOffset === 0;
+
+ return isFirstNode && isOffsetZero;
+ },
+
+ atTheEnd: function atTheEnd() {
+
+ var selection = window.getSelection(),
+ anchorOffset = selection.anchorOffset,
+ anchorNode = selection.anchorNode;
+
+ /** Caret is at the end of input */
+ return !anchorNode || !anchorNode.length || anchorOffset === anchorNode.length;
+ }
+ };
+
+ /**
+ * Inserts node at the caret location
+ * @param {HTMLElement|DocumentFragment} node
+ */
+ caret.insertNode = function (node) {
+
+ var selection,
+ range,
+ lastNode = node;
+
+ if (node.nodeType == editor.core.nodeTypes.DOCUMENT_FRAGMENT) {
+
+ lastNode = node.lastChild;
+ }
+
+ selection = window.getSelection();
+
+ range = selection.getRangeAt(0);
+ range.deleteContents();
+
+ range.insertNode(node);
+
+ range.setStartAfter(lastNode);
+ range.collapse(true);
+
+ selection.removeAllRanges();
+ selection.addRange(range);
+ };
+
+ return caret;
+ }({});
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * Codex Editor Content Module
+ * Works with DOM
+ *
+ * @module Codex Editor content module
+ *
+ * @author Codex Team
+ * @version 1.3.13
+ *
+ * @description Module works with Elements that have been appended to the main DOM
+ */
+
+ module.exports = function (content) {
+
+ var editor = codex.editor;
+
+ /**
+ * Links to current active block
+ * @type {null | Element}
+ */
+ content.currentNode = null;
+
+ /**
+ * clicked in redactor area
+ * @type {null | Boolean}
+ */
+ content.editorAreaHightlighted = null;
+
+ /**
+ * @deprecated
+ * Synchronizes redactor with original textarea
+ */
+ content.sync = function () {
+
+ editor.core.log('syncing...');
+
+ /**
+ * Save redactor content to editor.state
+ */
+ editor.state.html = editor.nodes.redactor.innerHTML;
+ };
+
+ /**
+ * Appends background to the block
+ *
+ * @description add CSS class to highlight visually first-level block area
+ */
+ content.markBlock = function () {
+
+ editor.content.currentNode.classList.add(editor.ui.className.BLOCK_HIGHLIGHTED);
+ };
+
+ /**
+ * Clear background
+ *
+ * @description clears styles that highlights block
+ */
+ content.clearMark = function () {
+
+ if (editor.content.currentNode) {
+
+ editor.content.currentNode.classList.remove(editor.ui.className.BLOCK_HIGHLIGHTED);
+ }
+ };
+
+ /**
+ * Finds first-level block
+ *
+ * @param {Element} node - selected or clicked in redactors area node
+ * @protected
+ *
+ * @description looks for first-level block.
+ * gets parent while node is not first-level
+ */
+ content.getFirstLevelBlock = function (node) {
+
+ if (!editor.core.isDomNode(node)) {
+
+ node = node.parentNode;
+ }
+
+ if (node === editor.nodes.redactor || node === document.body) {
+
+ return null;
+ } else {
+
+ while (!node.classList.contains(editor.ui.className.BLOCK_CLASSNAME)) {
+
+ node = node.parentNode;
+ }
+
+ return node;
+ }
+ };
+
+ /**
+ * Trigger this event when working node changed
+ * @param {Element} targetNode - first-level of this node will be current
+ * @protected
+ *
+ * @description If targetNode is first-level then we set it as current else we look for parents to find first-level
+ */
+ content.workingNodeChanged = function (targetNode) {
+
+ /** Clear background from previous marked block before we change */
+ editor.content.clearMark();
+
+ if (!targetNode) {
+
+ return;
+ }
+
+ content.currentNode = content.getFirstLevelBlock(targetNode);
+ };
+
+ /**
+ * Replaces one redactor block with another
+ * @protected
+ * @param {Element} targetBlock - block to replace. Mostly currentNode.
+ * @param {Element} newBlock
+ * @param {string} newBlockType - type of new block; we need to store it to data-attribute
+ *
+ * [!] Function does not saves old block content.
+ * You can get it manually and pass with newBlock.innerHTML
+ */
+ content.replaceBlock = function (targetBlock, newBlock) {
+
+ if (!targetBlock || !newBlock) {
+
+ editor.core.log('replaceBlock: missed params');
+ return;
+ }
+
+ /** If target-block is not a frist-level block, then we iterate parents to find it */
+ while (!targetBlock.classList.contains(editor.ui.className.BLOCK_CLASSNAME)) {
+
+ targetBlock = targetBlock.parentNode;
+ }
+
+ /** Replacing */
+ editor.nodes.redactor.replaceChild(newBlock, targetBlock);
+
+ /**
+ * Set new node as current
+ */
+ editor.content.workingNodeChanged(newBlock);
+
+ /**
+ * Add block handlers
+ */
+ editor.ui.addBlockHandlers(newBlock);
+
+ /**
+ * Save changes
+ */
+ editor.ui.saveInputs();
+ };
+
+ /**
+ * @protected
+ *
+ * Inserts new block to redactor
+ * Wrapps block into a DIV with BLOCK_CLASSNAME class
+ *
+ * @param blockData {object}
+ * @param blockData.block {Element} element with block content
+ * @param blockData.type {string} block plugin
+ * @param needPlaceCaret {bool} pass true to set caret in new block
+ *
+ */
+ content.insertBlock = function (blockData, needPlaceCaret) {
+
+ var workingBlock = editor.content.currentNode,
+ newBlockContent = blockData.block,
+ blockType = blockData.type,
+ isStretched = blockData.stretched;
+
+ var newBlock = composeNewBlock_(newBlockContent, blockType, isStretched);
+
+ if (workingBlock) {
+
+ editor.core.insertAfter(workingBlock, newBlock);
+ } else {
+
+ /**
+ * If redactor is empty, append as first child
+ */
+ editor.nodes.redactor.appendChild(newBlock);
+ }
+
+ /**
+ * Block handler
+ */
+ editor.ui.addBlockHandlers(newBlock);
+
+ /**
+ * Set new node as current
+ */
+ editor.content.workingNodeChanged(newBlock);
+
+ /**
+ * Save changes
+ */
+ editor.ui.saveInputs();
+
+ if (needPlaceCaret) {
+
+ /**
+ * If we don't know input index then we set default value -1
+ */
+ var currentInputIndex = editor.caret.getCurrentInputIndex() || -1;
+
+ if (currentInputIndex == -1) {
+
+ var editableElement = newBlock.querySelector('[contenteditable]'),
+ emptyText = document.createTextNode('');
+
+ editableElement.appendChild(emptyText);
+ editor.caret.set(editableElement, 0, 0);
+
+ editor.toolbar.move();
+ editor.toolbar.showPlusButton();
+ } else {
+
+ if (currentInputIndex === editor.state.inputs.length - 1) return;
+
+ /** Timeout for browsers execution */
+ window.setTimeout(function () {
+
+ /** Setting to the new input */
+ editor.caret.setToNextBlock(currentInputIndex);
+ editor.toolbar.move();
+ editor.toolbar.open();
+ }, 10);
+ }
+ }
+
+ /**
+ * Block is inserted, wait for new click that defined focusing on editors area
+ * @type {boolean}
+ */
+ content.editorAreaHightlighted = false;
+ };
+
+ /**
+ * Replaces blocks with saving content
+ * @protected
+ * @param {Element} noteToReplace
+ * @param {Element} newNode
+ * @param {Element} blockType
+ */
+ content.switchBlock = function (blockToReplace, newBlock, tool) {
+
+ tool = tool || editor.content.currentNode.dataset.tool;
+ var newBlockComposed = composeNewBlock_(newBlock, tool);
+
+ /** Replacing */
+ editor.content.replaceBlock(blockToReplace, newBlockComposed);
+
+ /** Save new Inputs when block is changed */
+ editor.ui.saveInputs();
+ };
+
+ /**
+ * Iterates between child noted and looking for #text node on deepest level
+ * @protected
+ *
+ * @param {Element} block - node where find
+ * @param {int} postiton - starting postion
+ * Example: childNodex.length to find from the end
+ * or 0 to find from the start
+ * @return {Text} block
+ * @uses DFS
+ */
+ content.getDeepestTextNodeFromPosition = function (block, position) {
+
+ /**
+ * Clear Block from empty and useless spaces with trim.
+ * Such nodes we should remove
+ */
+ var blockChilds = block.childNodes,
+ index,
+ node,
+ text;
+
+ for (index = 0; index < blockChilds.length; index++) {
+
+ node = blockChilds[index];
+
+ if (node.nodeType == editor.core.nodeTypes.TEXT) {
+
+ text = node.textContent.trim();
+
+ /** Text is empty. We should remove this child from node before we start DFS
+ * decrease the quantity of childs.
+ */
+ if (text === '') {
+
+ block.removeChild(node);
+ position--;
+ }
+ }
+ }
+
+ if (block.childNodes.length === 0) {
+
+ return document.createTextNode('');
+ }
+
+ /** Setting default position when we deleted all empty nodes */
+ if (position < 0) position = 1;
+
+ var lookingFromStart = false;
+
+ /** For looking from START */
+ if (position === 0) {
+
+ lookingFromStart = true;
+ position = 1;
+ }
+
+ while (position) {
+
+ /** initial verticle of node. */
+ if (lookingFromStart) {
+
+ block = block.childNodes[0];
+ } else {
+
+ block = block.childNodes[position - 1];
+ }
+
+ if (block.nodeType == editor.core.nodeTypes.TAG) {
+
+ position = block.childNodes.length;
+ } else if (block.nodeType == editor.core.nodeTypes.TEXT) {
+
+ position = 0;
+ }
+ }
+
+ return block;
+ };
+
+ /**
+ * @private
+ * @param {Element} block - current plugins render
+ * @param {String} tool - plugins name
+ * @param {Boolean} isStretched - make stretched block or not
+ *
+ * @description adds necessary information to wrap new created block by first-level holder
+ */
+ var composeNewBlock_ = function composeNewBlock_(block, tool, isStretched) {
+
+ var newBlock = editor.draw.node('DIV', editor.ui.className.BLOCK_CLASSNAME, {}),
+ blockContent = editor.draw.node('DIV', editor.ui.className.BLOCK_CONTENT, {});
+
+ blockContent.appendChild(block);
+ newBlock.appendChild(blockContent);
+
+ if (isStretched) {
+
+ blockContent.classList.add(editor.ui.className.BLOCK_STRETCHED);
+ }
+
+ newBlock.dataset.tool = tool;
+ return newBlock;
+ };
+
+ /**
+ * Returns Range object of current selection
+ * @protected
+ */
+ content.getRange = function () {
+
+ var selection = window.getSelection().getRangeAt(0);
+
+ return selection;
+ };
+
+ /**
+ * Divides block in two blocks (after and before caret)
+ *
+ * @protected
+ * @param {int} inputIndex - target input index
+ *
+ * @description splits current input content to the separate blocks
+ * When enter is pressed among the words, that text will be splited.
+ */
+ content.splitBlock = function (inputIndex) {
+
+ var selection = window.getSelection(),
+ anchorNode = selection.anchorNode,
+ anchorNodeText = anchorNode.textContent,
+ caretOffset = selection.anchorOffset,
+ textBeforeCaret,
+ textNodeBeforeCaret,
+ textAfterCaret,
+ textNodeAfterCaret;
+
+ var currentBlock = editor.content.currentNode.querySelector('[contentEditable]');
+
+ textBeforeCaret = anchorNodeText.substring(0, caretOffset);
+ textAfterCaret = anchorNodeText.substring(caretOffset);
+
+ textNodeBeforeCaret = document.createTextNode(textBeforeCaret);
+
+ if (textAfterCaret) {
+
+ textNodeAfterCaret = document.createTextNode(textAfterCaret);
+ }
+
+ var previousChilds = [],
+ nextChilds = [],
+ reachedCurrent = false;
+
+ if (textNodeAfterCaret) {
+
+ nextChilds.push(textNodeAfterCaret);
+ }
+
+ for (var i = 0, child; !!(child = currentBlock.childNodes[i]); i++) {
+
+ if (child != anchorNode) {
+
+ if (!reachedCurrent) {
+
+ previousChilds.push(child);
+ } else {
+
+ nextChilds.push(child);
+ }
+ } else {
+
+ reachedCurrent = true;
+ }
+ }
+
+ /** Clear current input */
+ editor.state.inputs[inputIndex].innerHTML = '';
+
+ /**
+ * Append all childs founded before anchorNode
+ */
+ var previousChildsLength = previousChilds.length;
+
+ for (i = 0; i < previousChildsLength; i++) {
+
+ editor.state.inputs[inputIndex].appendChild(previousChilds[i]);
+ }
+
+ editor.state.inputs[inputIndex].appendChild(textNodeBeforeCaret);
+
+ /**
+ * Append text node which is after caret
+ */
+ var nextChildsLength = nextChilds.length,
+ newNode = document.createElement('div');
+
+ for (i = 0; i < nextChildsLength; i++) {
+
+ newNode.appendChild(nextChilds[i]);
+ }
+
+ newNode = newNode.innerHTML;
+
+ /** This type of block creates when enter is pressed */
+ var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;
+
+ /**
+ * Make new paragraph with text after caret
+ */
+ editor.content.insertBlock({
+ type: NEW_BLOCK_TYPE,
+ block: editor.tools[NEW_BLOCK_TYPE].render({
+ text: newNode
+ })
+ }, true);
+ };
+
+ /**
+ * Merges two blocks — current and target
+ * If target index is not exist, then previous will be as target
+ *
+ * @protected
+ * @param {int} currentInputIndex
+ * @param {int} targetInputIndex
+ *
+ * @description gets two inputs indexes and merges into one
+ */
+ content.mergeBlocks = function (currentInputIndex, targetInputIndex) {
+
+ /** If current input index is zero, then prevent method execution */
+ if (currentInputIndex === 0) {
+
+ return;
+ }
+
+ var targetInput,
+ currentInputContent = editor.state.inputs[currentInputIndex].innerHTML;
+
+ if (!targetInputIndex) {
+
+ targetInput = editor.state.inputs[currentInputIndex - 1];
+ } else {
+
+ targetInput = editor.state.inputs[targetInputIndex];
+ }
+
+ targetInput.innerHTML += currentInputContent;
+ };
+
+ /**
+ * Iterates all right siblings and parents, which has right siblings
+ * while it does not reached the first-level block
+ *
+ * @param {Element} node
+ * @return {boolean}
+ */
+ content.isLastNode = function (node) {
+
+ // console.log('погнали перебор родителей');
+
+ var allChecked = false;
+
+ while (!allChecked) {
+
+ // console.log('Смотрим на %o', node);
+ // console.log('Проверим, пустые ли соседи справа');
+
+ if (!allSiblingsEmpty_(node)) {
+
+ // console.log('Есть непустые соседи. Узел не последний. Выходим.');
+ return false;
+ }
+
+ node = node.parentNode;
+
+ /**
+ * Проверяем родителей до тех пор, пока не найдем блок первого уровня
+ */
+ if (node.classList.contains(editor.ui.className.BLOCK_CONTENT)) {
+
+ allChecked = true;
+ }
+ }
+
+ return true;
+ };
+
+ /**
+ * Checks if all element right siblings is empty
+ * @param node
+ */
+ var allSiblingsEmpty_ = function allSiblingsEmpty_(node) {
+
+ /**
+ * Нужно убедиться, что после пустого соседа ничего нет
+ */
+ var sibling = node.nextSibling;
+
+ while (sibling) {
+
+ if (sibling.textContent.length) {
+
+ return false;
+ }
+
+ sibling = sibling.nextSibling;
+ }
+
+ return true;
+ };
+
+ /**
+ * @public
+ *
+ * @param {string} htmlData - html content as string
+ * @param {string} plainData - plain text
+ * @return {string} - html content as string
+ */
+ content.wrapTextWithParagraphs = function (htmlData, plainData) {
+
+ if (!htmlData.trim()) {
+
+ return wrapPlainTextWithParagraphs(plainData);
+ }
+
+ var wrapper = document.createElement('DIV'),
+ newWrapper = document.createElement('DIV'),
+ i,
+ paragraph,
+ firstLevelBlocks = ['DIV', 'P'],
+ blockTyped,
+ node;
+
+ /**
+ * Make HTML Element to Wrap Text
+ * It allows us to work with input data as HTML content
+ */
+ wrapper.innerHTML = htmlData;
+ paragraph = document.createElement('P');
+
+ for (i = 0; i < wrapper.childNodes.length; i++) {
+
+ node = wrapper.childNodes[i];
+
+ blockTyped = firstLevelBlocks.indexOf(node.tagName) != -1;
+
+ /**
+ * If node is first-levet
+ * we add this node to our new wrapper
+ */
+ if (blockTyped) {
+
+ /**
+ * If we had splitted inline nodes to paragraph before
+ */
+ if (paragraph.childNodes.length) {
+
+ newWrapper.appendChild(paragraph.cloneNode(true));
+
+ /** empty paragraph */
+ paragraph = null;
+ paragraph = document.createElement('P');
+ }
+
+ newWrapper.appendChild(node.cloneNode(true));
+ } else {
+
+ /** Collect all inline nodes to one as paragraph */
+ paragraph.appendChild(node.cloneNode(true));
+
+ /** if node is last we should append this node to paragraph and paragraph to new wrapper */
+ if (i == wrapper.childNodes.length - 1) {
+
+ newWrapper.appendChild(paragraph.cloneNode(true));
+ }
+ }
+ }
+
+ return newWrapper.innerHTML;
+ };
+
+ /**
+ * Splits strings on new line and wraps paragraphs with
tag
+ * @param plainText
+ * @returns {string}
+ */
+ var wrapPlainTextWithParagraphs = function wrapPlainTextWithParagraphs(plainText) {
+
+ if (!plainText) return '';
+
+ return '
' + plainText.split('\n\n').join('
') + '
';
+ };
+
+ /**
+ * Finds closest Contenteditable parent from Element
+ * @param {Element} node element looking from
+ * @return {Element} node contenteditable
+ */
+ content.getEditableParent = function (node) {
+
+ while (node && node.contentEditable != 'true') {
+
+ node = node.parentNode;
+ }
+
+ return node;
+ };
+
+ /**
+ * Clear editors content
+ *
+ * @param {Boolean} all — if true, delete all article data (content, id, etc.)
+ */
+ content.clear = function (all) {
+
+ editor.nodes.redactor.innerHTML = '';
+ editor.content.sync();
+ editor.ui.saveInputs();
+ if (all) {
+
+ editor.state.blocks = {};
+ } else if (editor.state.blocks) {
+
+ editor.state.blocks.items = [];
+ }
+
+ editor.content.currentNode = null;
+ };
+
+ /**
+ *
+ * Load new data to editor
+ * If editor is not empty, just append articleData.items
+ *
+ * @param articleData.items
+ */
+ content.load = function (articleData) {
+
+ var currentContent = Object.assign({}, editor.state.blocks);
+
+ editor.content.clear();
+
+ if (!Object.keys(currentContent).length) {
+
+ editor.state.blocks = articleData;
+ } else if (!currentContent.items) {
+
+ currentContent.items = articleData.items;
+ editor.state.blocks = currentContent;
+ } else {
+
+ currentContent.items = currentContent.items.concat(articleData.items);
+ editor.state.blocks = currentContent;
+ }
+
+ editor.renderer.makeBlocksFromData();
+ };
+
+ return content;
+ }({});
+
+/***/ }),
+/* 6 */
+/***/ (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; };
+
+ /**
+ * Codex Editor Destroyer module
+ *
+ * @auhor Codex Team
+ * @version 1.0
+ */
+
+ module.exports = function (destroyer) {
+
+ var editor = codex.editor;
+
+ destroyer.removeNodes = function () {
+
+ editor.nodes.wrapper.remove();
+ editor.nodes.notifications.remove();
+ };
+
+ destroyer.destroyPlugins = function () {
+
+ for (var tool in editor.tools) {
+
+ if (typeof editor.tools[tool].destroy === 'function') {
+
+ editor.tools[tool].destroy();
+ }
+ }
+ };
+
+ destroyer.destroyScripts = function () {
+
+ var scripts = document.getElementsByTagName('SCRIPT');
+
+ for (var i = 0; i < scripts.length; i++) {
+
+ if (scripts[i].id.indexOf(editor.scriptPrefix) + 1) {
+
+ scripts[i].remove();
+ i--;
+ }
+ }
+ };
+
+ /**
+ * Delete editor data from webpage.
+ * You should send settings argument with boolean flags:
+ * @param settings.ui- remove redactor event listeners and DOM nodes
+ * @param settings.scripts - remove redactor scripts from DOM
+ * @param settings.plugins - remove plugin's objects
+ * @param settings.core - remove editor core. You can remove core only if UI and scripts flags is true
+ * }
+ *
+ */
+ destroyer.destroy = function (settings) {
+
+ if (!settings || (typeof settings === 'undefined' ? 'undefined' : _typeof(settings)) !== 'object') {
+
+ return;
+ }
+
+ if (settings.ui) {
+
+ destroyer.removeNodes();
+ editor.listeners.removeAll();
+ }
+
+ if (settings.scripts) {
+
+ destroyer.destroyScripts();
+ }
+
+ if (settings.plugins) {
+
+ destroyer.destroyPlugins();
+ }
+
+ if (settings.ui && settings.scripts && settings.core) {
+
+ delete codex.editor;
+ }
+ };
+
+ return destroyer;
+ }({});
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports) {
+
+ "use strict";
+
+ /**
+ * Codex Editor Listeners module
+ *
+ * @author Codex Team
+ * @version 1.0
+ */
+
+ /**
+ * Module-decorator for event listeners assignment
+ */
+ module.exports = function (listeners) {
+
+ var allListeners = [];
+
+ /**
+ * Search methods
+ *
+ * byElement, byType and byHandler returns array of suitable listeners
+ * one and all takes element, eventType, and handler and returns first (all) suitable listener
+ *
+ */
+ listeners.search = function () {
+
+ var byElement = function byElement(element, context) {
+
+ var listenersOnElement = [];
+
+ context = context || allListeners;
+
+ for (var i = 0; i < context.length; i++) {
+
+ var listener = context[i];
+
+ if (listener.element === element) {
+
+ listenersOnElement.push(listener);
+ }
+ }
+
+ return listenersOnElement;
+ };
+
+ var byType = function byType(eventType, context) {
+
+ var listenersWithType = [];
+
+ context = context || allListeners;
+
+ for (var i = 0; i < context.length; i++) {
+
+ var listener = context[i];
+
+ if (listener.type === eventType) {
+
+ listenersWithType.push(listener);
+ }
+ }
+
+ return listenersWithType;
+ };
+
+ var byHandler = function byHandler(handler, context) {
+
+ var listenersWithHandler = [];
+
+ context = context || allListeners;
+
+ for (var i = 0; i < context.length; i++) {
+
+ var listener = context[i];
+
+ if (listener.handler === handler) {
+
+ listenersWithHandler.push(listener);
+ }
+ }
+
+ return listenersWithHandler;
+ };
+
+ var one = function one(element, eventType, handler) {
+
+ var result = allListeners;
+
+ if (element) result = byElement(element, result);
+
+ if (eventType) result = byType(eventType, result);
+
+ if (handler) result = byHandler(handler, result);
+
+ return result[0];
+ };
+
+ var all = function all(element, eventType, handler) {
+
+ var result = allListeners;
+
+ if (element) result = byElement(element, result);
+
+ if (eventType) result = byType(eventType, result);
+
+ if (handler) result = byHandler(handler, result);
+
+ return result;
+ };
+
+ return {
+ byElement: byElement,
+ byType: byType,
+ byHandler: byHandler,
+ one: one,
+ all: all
+ };
+ }();
+
+ listeners.add = function (element, eventType, handler, isCapture) {
+
+ element.addEventListener(eventType, handler, isCapture);
+
+ var data = {
+ element: element,
+ type: eventType,
+ handler: handler
+ };
+
+ var alreadyAddedListener = listeners.search.one(element, eventType, handler);
+
+ if (!alreadyAddedListener) {
+
+ allListeners.push(data);
+ }
+ };
+
+ listeners.remove = function (element, eventType, handler) {
+
+ element.removeEventListener(eventType, handler);
+
+ var existingListeners = listeners.search.all(element, eventType, handler);
+
+ for (var i = 0; i < existingListeners.length; i++) {
+
+ var index = allListeners.indexOf(existingListeners[i]);
+
+ if (index > 0) {
+
+ allListeners.splice(index, 1);
+ }
+ }
+ };
+
+ listeners.removeAll = function () {
+
+ allListeners.map(function (current) {
+
+ listeners.remove(current.element, current.type, current.handler);
+ });
+ };
+
+ listeners.get = function (element, eventType, handler) {
+
+ return listeners.search.all(element, eventType, handler);
+ };
+
+ return listeners;
+ }({});
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * Codex Editor Notification Module
+ *
+ * @author Codex Team
+ * @version 1.0
+ */
+
+ module.exports = function (notifications) {
+
+ var editor = codex.editor;
+
+ var queue = [];
+
+ var addToQueue = function addToQueue(settings) {
+
+ queue.push(settings);
+
+ var index = 0;
+
+ while (index < queue.length && queue.length > 5) {
+
+ if (queue[index].type == 'confirm' || queue[index].type == 'prompt') {
+
+ index++;
+ continue;
+ }
+
+ queue[index].close();
+ queue.splice(index, 1);
+ }
+ };
+
+ notifications.createHolder = function () {
+
+ var holder = editor.draw.node('DIV', 'cdx-notifications-block');
+
+ editor.nodes.notifications = document.body.appendChild(holder);
+
+ return holder;
+ };
+
+ /**
+ * Error notificator. Shows block with message
+ * @protected
+ */
+ notifications.errorThrown = function (errorMsg, event) {
+
+ editor.notifications.notification({ message: 'This action is not available currently', type: event.type });
+ };
+
+ /**
+ *
+ * Appends notification
+ *
+ * settings = {
+ * type - notification type (reserved types: alert, confirm, prompt). Just add class 'cdx-notification-'+type
+ * message - notification message
+ * okMsg - confirm button text (default - 'Ok')
+ * cancelBtn - cancel button text (default - 'Cancel'). Only for confirm and prompt types
+ * confirm - function-handler for ok button click
+ * cancel - function-handler for cancel button click. Only for confirm and prompt types
+ * time - time (in seconds) after which notification will close (default - 10s)
+ * }
+ *
+ * @param settings
+ */
+ notifications.notification = function (constructorSettings) {
+
+ /** Private vars and methods */
+ var notification = null,
+ cancel = null,
+ type = null,
+ confirm = null,
+ inputField = null;
+
+ var confirmHandler = function confirmHandler() {
+
+ close();
+
+ if (typeof confirm !== 'function') {
+
+ return;
+ }
+
+ if (type == 'prompt') {
+
+ confirm(inputField.value);
+ return;
+ }
+
+ confirm();
+ };
+
+ var cancelHandler = function cancelHandler() {
+
+ close();
+
+ if (typeof cancel !== 'function') {
+
+ return;
+ }
+
+ cancel();
+ };
+
+ /** Public methods */
+ function create(settings) {
+
+ if (!(settings && settings.message)) {
+
+ editor.core.log('Can\'t create notification. Message is missed');
+ return;
+ }
+
+ settings.type = settings.type || 'alert';
+ settings.time = settings.time * 1000 || 10000;
+
+ var wrapper = editor.draw.node('DIV', 'cdx-notification'),
+ message = editor.draw.node('DIV', 'cdx-notification__message'),
+ input = editor.draw.node('INPUT', 'cdx-notification__input'),
+ okBtn = editor.draw.node('SPAN', 'cdx-notification__ok-btn'),
+ cancelBtn = editor.draw.node('SPAN', 'cdx-notification__cancel-btn');
+
+ message.textContent = settings.message;
+ okBtn.textContent = settings.okMsg || 'ОК';
+ cancelBtn.textContent = settings.cancelMsg || 'Отмена';
+
+ editor.listeners.add(okBtn, 'click', confirmHandler);
+ editor.listeners.add(cancelBtn, 'click', cancelHandler);
+
+ wrapper.appendChild(message);
+
+ if (settings.type == 'prompt') {
+
+ wrapper.appendChild(input);
+ }
+
+ wrapper.appendChild(okBtn);
+
+ if (settings.type == 'prompt' || settings.type == 'confirm') {
+
+ wrapper.appendChild(cancelBtn);
+ }
+
+ wrapper.classList.add('cdx-notification-' + settings.type);
+ wrapper.dataset.type = settings.type;
+
+ notification = wrapper;
+ type = settings.type;
+ confirm = settings.confirm;
+ cancel = settings.cancel;
+ inputField = input;
+
+ if (settings.type != 'prompt' && settings.type != 'confirm') {
+
+ window.setTimeout(close, settings.time);
+ }
+ };
+
+ /**
+ * Show notification block
+ */
+ function send() {
+
+ editor.nodes.notifications.appendChild(notification);
+ inputField.focus();
+
+ editor.nodes.notifications.classList.add('cdx-notification__notification-appending');
+
+ window.setTimeout(function () {
+
+ editor.nodes.notifications.classList.remove('cdx-notification__notification-appending');
+ }, 100);
+
+ addToQueue({ type: type, close: close });
+ };
+
+ /**
+ * Remove notification block
+ */
+ function close() {
+
+ notification.remove();
+ };
+
+ if (constructorSettings) {
+
+ create(constructorSettings);
+ send();
+ }
+
+ return {
+ create: create,
+ send: send,
+ close: close
+ };
+ };
+
+ notifications.clear = function () {
+
+ editor.nodes.notifications.innerHTML = '';
+ queue = [];
+ };
+
+ return notifications;
+ }({});
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports) {
+
+ "use strict";
+
+ /**
+ * Codex Editor Parser Module
+ *
+ * @author Codex Team
+ * @version 1.1
+ */
+
+ module.exports = function (parser) {
+
+ var editor = codex.editor;
+
+ /** inserting text */
+ parser.insertPastedContent = function (blockType, tag) {
+
+ editor.content.insertBlock({
+ type: blockType.type,
+ block: blockType.render({
+ text: tag.innerHTML
+ })
+ });
+ };
+
+ /**
+ * Check DOM node for display style: separated block or child-view
+ */
+ parser.isFirstLevelBlock = function (node) {
+
+ return node.nodeType == editor.core.nodeTypes.TAG && node.classList.contains(editor.ui.className.BLOCK_CLASSNAME);
+ };
+
+ return parser;
+ }({});
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * Codex Editor Paste module
+ *
+ * @author Codex Team
+ * @version 1.1.1
+ */
+
+ module.exports = function (paste) {
+
+ var editor = codex.editor;
+
+ var patterns = [];
+
+ paste.prepare = function () {
+
+ var tools = editor.tools;
+
+ for (var tool in tools) {
+
+ if (!tools[tool].renderOnPastePatterns || !Array.isArray(tools[tool].renderOnPastePatterns)) {
+
+ continue;
+ }
+
+ tools[tool].renderOnPastePatterns.map(function (pattern) {
+
+ patterns.push(pattern);
+ });
+ }
+
+ return Promise.resolve();
+ };
+
+ /**
+ * Saves data
+ * @param event
+ */
+ paste.pasted = function (event) {
+
+ var clipBoardData = event.clipboardData || window.clipboardData,
+ content = clipBoardData.getData('Text');
+
+ var result = analize(content);
+
+ if (result) {
+
+ event.preventDefault();
+ event.stopImmediatePropagation();
+ }
+
+ return result;
+ };
+
+ /**
+ * Analizes pated string and calls necessary method
+ */
+
+ var analize = function analize(string) {
+
+ var result = false,
+ content = editor.content.currentNode,
+ plugin = content.dataset.tool;
+
+ patterns.map(function (pattern) {
+
+ var execArray = pattern.regex.exec(string),
+ match = execArray && execArray[0];
+
+ if (match && match === string.trim()) {
+
+ /** current block is not empty */
+ if (content.textContent.trim() && plugin == editor.settings.initialBlockPlugin) {
+
+ pasteToNewBlock_();
+ }
+
+ pattern.callback(string, pattern);
+ result = true;
+ }
+ });
+
+ return result;
+ };
+
+ var pasteToNewBlock_ = function pasteToNewBlock_() {
+
+ /** Create new initial block */
+ editor.content.insertBlock({
+
+ type: editor.settings.initialBlockPlugin,
+ block: editor.tools[editor.settings.initialBlockPlugin].render({
+ text: ''
+ })
+
+ }, false);
+ };
+
+ /**
+ * This method prevents default behaviour.
+ *
+ * @param {Object} event
+ * @protected
+ *
+ * @description We get from clipboard pasted data, sanitize, make a fragment that contains of this sanitized nodes.
+ * Firstly, we need to memorize the caret position. We can do that by getting the range of selection.
+ * After all, we insert clear fragment into caret placed position. Then, we should move the caret to the last node
+ */
+ paste.blockPasteCallback = function (event) {
+
+ if (!needsToHandlePasteEvent(event.target)) {
+
+ return;
+ }
+
+ /** Prevent default behaviour */
+ event.preventDefault();
+
+ /** get html pasted data - dirty data */
+ var htmlData = event.clipboardData.getData('text/html'),
+ plainData = event.clipboardData.getData('text/plain');
+
+ /** Temporary DIV that is used to work with text's paragraphs as DOM-elements*/
+ var paragraphs = editor.draw.node('DIV', '', {}),
+ cleanData,
+ wrappedData;
+
+ /** Create fragment, that we paste to range after proccesing */
+ cleanData = editor.sanitizer.clean(htmlData);
+
+ /**
+ * We wrap pasted text with tags to split it logically
+ * @type {string}
+ */
+ wrappedData = editor.content.wrapTextWithParagraphs(cleanData, plainData);
+ paragraphs.innerHTML = wrappedData;
+
+ /**
+ * If there only one paragraph, just insert in at the caret location
+ */
+ if (paragraphs.childNodes.length == 1) {
+
+ emulateUserAgentBehaviour(paragraphs.firstChild);
+ return;
+ }
+
+ insertPastedParagraphs(paragraphs.childNodes);
+ };
+
+ /**
+ * Checks if we should handle paste event on block
+ * @param block
+ *
+ * @return {boolean}
+ */
+ var needsToHandlePasteEvent = function needsToHandlePasteEvent(block) {
+
+ /** If area is input or textarea then allow default behaviour */
+ if (editor.core.isNativeInput(block)) {
+
+ return false;
+ }
+
+ var editableParent = editor.content.getEditableParent(block);
+
+ /** Allow paste when event target placed in Editable element */
+ if (!editableParent) {
+
+ return false;
+ }
+
+ return true;
+ };
+
+ /**
+ * Inserts new initial plugin blocks with data in paragraphs
+ *
+ * @param {Array} paragraphs - array of paragraphs (
) whit content, that should be inserted
+ */
+ var insertPastedParagraphs = function insertPastedParagraphs(paragraphs) {
+
+ var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin,
+ currentNode = editor.content.currentNode;
+
+ paragraphs.forEach(function (paragraph) {
+
+ /** Don't allow empty paragraphs */
+ if (editor.core.isBlockEmpty(paragraph)) {
+
+ return;
+ }
+
+ editor.content.insertBlock({
+ type: NEW_BLOCK_TYPE,
+ block: editor.tools[NEW_BLOCK_TYPE].render({
+ text: paragraph.innerHTML
+ })
+ });
+
+ editor.caret.inputIndex++;
+ });
+
+ editor.caret.setToPreviousBlock(editor.caret.getCurrentInputIndex() + 1);
+
+ /**
+ * If there was no data in working node, remove it
+ */
+ if (editor.core.isBlockEmpty(currentNode)) {
+
+ currentNode.remove();
+ editor.ui.saveInputs();
+ }
+ };
+
+ /**
+ * Inserts node content at the caret position
+ *
+ * @param {Node} node - DOM node (could be DocumentFragment), that should be inserted at the caret location
+ */
+ var emulateUserAgentBehaviour = function emulateUserAgentBehaviour(node) {
+
+ var newNode;
+
+ if (node.childElementCount) {
+
+ newNode = document.createDocumentFragment();
+
+ node.childNodes.forEach(function (current) {
+
+ if (!editor.core.isDomNode(current) && current.data.trim() === '') {
+
+ return;
+ }
+
+ newNode.appendChild(current.cloneNode(true));
+ });
+ } else {
+
+ newNode = document.createTextNode(node.textContent);
+ }
+
+ editor.caret.insertNode(newNode);
+ };
+
+ return paste;
+ }({});
+
+/***/ }),
+/* 11 */
+/***/ (function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * Codex Editor Renderer Module
+ *
+ * @author Codex Team
+ * @version 1.0
+ */
+
+ module.exports = function (renderer) {
+
+ var editor = codex.editor;
+
+ /**
+ * Asyncronously parses input JSON to redactor blocks
+ */
+ renderer.makeBlocksFromData = function () {
+
+ /**
+ * If redactor is empty, add first paragraph to start writing
+ */
+ if (editor.core.isEmpty(editor.state.blocks) || !editor.state.blocks.items.length) {
+
+ editor.ui.addInitialBlock();
+ return;
+ }
+
+ Promise.resolve()
+
+ /** First, get JSON from state */
+ .then(function () {
+
+ return editor.state.blocks;
+ })
+
+ /** Then, start to iterate they */
+ .then(editor.renderer.appendBlocks)
+
+ /** Write log if something goes wrong */
+ .catch(function (error) {
+
+ editor.core.log('Error while parsing JSON: %o', 'error', error);
+ });
+ };
+
+ /**
+ * Parses JSON to blocks
+ * @param {object} data
+ * @return Primise -> nodeList
+ */
+ renderer.appendBlocks = function (data) {
+
+ var blocks = data.items;
+
+ /**
+ * Sequence of one-by-one blocks appending
+ * Uses to save blocks order after async-handler
+ */
+ var nodeSequence = Promise.resolve();
+
+ for (var index = 0; index < blocks.length; index++) {
+
+ /** Add node to sequence at specified index */
+ editor.renderer.appendNodeAtIndex(nodeSequence, blocks, index);
+ }
+ };
+
+ /**
+ * Append node at specified index
+ */
+ renderer.appendNodeAtIndex = function (nodeSequence, blocks, index) {
+
+ /** We need to append node to sequence */
+ nodeSequence
+
+ /** first, get node async-aware */
+ .then(function () {
+
+ return editor.renderer.getNodeAsync(blocks, index);
+ })
+
+ /**
+ * second, compose editor-block from JSON object
+ */
+ .then(editor.renderer.createBlockFromData)
+
+ /**
+ * now insert block to redactor
+ */
+ .then(function (blockData) {
+
+ /**
+ * blockData has 'block', 'type' and 'stretched' information
+ */
+ editor.content.insertBlock(blockData);
+
+ /** Pass created block to next step */
+ return blockData.block;
+ })
+
+ /** Log if something wrong with node */
+ .catch(function (error) {
+
+ editor.core.log('Node skipped while parsing because %o', 'error', error);
+ });
+ };
+
+ /**
+ * Asynchronously returns block data from blocksList by index
+ * @return Promise to node
+ */
+ renderer.getNodeAsync = function (blocksList, index) {
+
+ return Promise.resolve().then(function () {
+
+ return {
+ tool: blocksList[index],
+ position: index
+ };
+ });
+ };
+
+ /**
+ * Creates editor block by JSON-data
+ *
+ * @uses render method of each plugin
+ *
+ * @param {Object} toolData.tool
+ * { header : {
+ * text: '',
+ * type: 'H3', ...
+ * }
+ * }
+ * @param {Number} toolData.position - index in input-blocks array
+ * @return {Object} with type and Element
+ */
+ renderer.createBlockFromData = function (toolData) {
+
+ /** New parser */
+ var block,
+ tool = toolData.tool,
+ pluginName = tool.type;
+
+ /** Get first key of object that stores plugin name */
+ // for (var pluginName in blockData) break;
+
+ /** Check for plugin existance */
+ if (!editor.tools[pluginName]) {
+
+ throw Error('Plugin \xAB' + pluginName + '\xBB not found');
+ }
+
+ /** Check for plugin having render method */
+ if (typeof editor.tools[pluginName].render != 'function') {
+
+ throw Error('Plugin \xAB' + pluginName + '\xBB must have \xABrender\xBB method');
+ }
+
+ if (editor.tools[pluginName].available === false) {
+
+ block = editor.draw.unavailableBlock();
+
+ block.innerHTML = editor.tools[pluginName].loadingMessage;
+
+ /**
+ * Saver will extract data from initial block data by position in array
+ */
+ block.dataset.inputPosition = toolData.position;
+ } else {
+
+ /** New Parser */
+ block = editor.tools[pluginName].render(tool.data);
+ }
+
+ /** is first-level block stretched */
+ var stretched = editor.tools[pluginName].isStretched || false;
+
+ /** Retrun type and block */
+ return {
+ type: pluginName,
+ block: block,
+ stretched: stretched
+ };
+ };
+
+ return renderer;
+ }({});
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ /**
+ * Codex Sanitizer
+ */
+
+ module.exports = function (sanitizer) {
+
+ /** HTML Janitor library */
+ var janitor = __webpack_require__(13);
+
+ /** Codex Editor */
+ var editor = codex.editor;
+
+ sanitizer.prepare = function () {
+
+ if (editor.settings.sanitizer && !editor.core.isEmpty(editor.settings.sanitizer)) {
+
+ Config.CUSTOM = editor.settings.sanitizer;
+ }
+ };
+
+ /**
+ * Basic config
+ */
+ var Config = {
+
+ /** User configuration */
+ CUSTOM: null,
+
+ BASIC: {
+
+ tags: {
+ p: {},
+ a: {
+ href: true,
+ target: '_blank',
+ rel: 'nofollow'
+ }
+ }
+ }
+ };
+
+ sanitizer.Config = Config;
+
+ /**
+ *
+ * @param userCustomConfig
+ * @returns {*}
+ * @private
+ *
+ * @description If developer uses editor's API, then he can customize sane restrictions.
+ * Or, sane config can be defined globally in editors initialization. That config will be used everywhere
+ * At least, if there is no config overrides, that API uses BASIC Default configation
+ */
+ var init_ = function init_(userCustomConfig) {
+
+ var configuration = userCustomConfig || Config.CUSTOM || Config.BASIC;
+
+ return new janitor(configuration);
+ };
+
+ /**
+ * Cleans string from unwanted tags
+ * @protected
+ * @param {String} dirtyString - taint string
+ * @param {Object} customConfig - allowed tags
+ */
+ sanitizer.clean = function (dirtyString, customConfig) {
+
+ var janitorInstance = init_(customConfig);
+
+ return janitorInstance.clean(dirtyString);
+ };
+
+ return sanitizer;
+ }({});
+
+/***/ }),
+/* 13 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (root, factory) {
+ if (true) {
+ !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ } else if (typeof exports === 'object') {
+ module.exports = factory();
+ } else {
+ root.HTMLJanitor = factory();
+ }
+ }(this, function () {
+
+ /**
+ * @param {Object} config.tags Dictionary of allowed tags.
+ * @param {boolean} config.keepNestedBlockElements Default false.
+ */
+ function HTMLJanitor(config) {
+
+ var tagDefinitions = config['tags'];
+ var tags = Object.keys(tagDefinitions);
+
+ var validConfigValues = tags
+ .map(function(k) { return typeof tagDefinitions[k]; })
+ .every(function(type) { return type === 'object' || type === 'boolean' || type === 'function'; });
+
+ if(!validConfigValues) {
+ throw new Error("The configuration was invalid");
+ }
+
+ this.config = config;
+ }
+
+ // TODO: not exhaustive?
+ var blockElementNames = ['P', 'LI', 'TD', 'TH', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'PRE'];
+ function isBlockElement(node) {
+ return blockElementNames.indexOf(node.nodeName) !== -1;
+ }
+
+ var inlineElementNames = ['A', 'B', 'STRONG', 'I', 'EM', 'SUB', 'SUP', 'U', 'STRIKE'];
+ function isInlineElement(node) {
+ return inlineElementNames.indexOf(node.nodeName) !== -1;
+ }
+
+ HTMLJanitor.prototype.clean = function (html) {
+ var sandbox = document.createElement('div');
+ sandbox.innerHTML = html;
+
+ this._sanitize(sandbox);
+
+ return sandbox.innerHTML;
+ };
+
+ HTMLJanitor.prototype._sanitize = function (parentNode) {
+ var treeWalker = createTreeWalker(parentNode);
+ var node = treeWalker.firstChild();
+ if (!node) { return; }
+
+ do {
+ // Ignore nodes that have already been sanitized
+ if (node._sanitized) {
+ continue;
+ }
+
+ if (node.nodeType === Node.TEXT_NODE) {
+ // If this text node is just whitespace and the previous or next element
+ // sibling is a block element, remove it
+ // N.B.: This heuristic could change. Very specific to a bug with
+ // `contenteditable` in Firefox: http://jsbin.com/EyuKase/1/edit?js,output
+ // FIXME: make this an option?
+ if (node.data.trim() === ''
+ && ((node.previousElementSibling && isBlockElement(node.previousElementSibling))
+ || (node.nextElementSibling && isBlockElement(node.nextElementSibling)))) {
+ parentNode.removeChild(node);
+ this._sanitize(parentNode);
+ break;
+ } else {
+ continue;
+ }
+ }
+
+ // Remove all comments
+ if (node.nodeType === Node.COMMENT_NODE) {
+ parentNode.removeChild(node);
+ this._sanitize(parentNode);
+ break;
+ }
+
+ var isInline = isInlineElement(node);
+ var containsBlockElement;
+ if (isInline) {
+ containsBlockElement = Array.prototype.some.call(node.childNodes, isBlockElement);
+ }
+
+ // Block elements should not be nested (e.g. ...); if
+ // they are, we want to unwrap the inner block element.
+ var isNotTopContainer = !! parentNode.parentNode;
+ var isNestedBlockElement =
+ isBlockElement(parentNode) &&
+ isBlockElement(node) &&
+ isNotTopContainer;
+
+ var nodeName = node.nodeName.toLowerCase();
+
+ var allowedAttrs = getAllowedAttrs(this.config, nodeName, node);
+
+ var isInvalid = isInline && containsBlockElement;
+
+ // Drop tag entirely according to the whitelist *and* if the markup
+ // is invalid.
+ if (isInvalid || shouldRejectNode(node, allowedAttrs)
+ || (!this.config.keepNestedBlockElements && isNestedBlockElement)) {
+ // Do not keep the inner text of SCRIPT/STYLE elements.
+ if (! (node.nodeName === 'SCRIPT' || node.nodeName === 'STYLE')) {
+ while (node.childNodes.length > 0) {
+ parentNode.insertBefore(node.childNodes[0], node);
+ }
+ }
+ parentNode.removeChild(node);
+
+ this._sanitize(parentNode);
+ break;
+ }
+
+ // Sanitize attributes
+ for (var a = 0; a < node.attributes.length; a += 1) {
+ var attr = node.attributes[a];
+
+ if (shouldRejectAttr(attr, allowedAttrs, node)) {
+ node.removeAttribute(attr.name);
+ // Shift the array to continue looping.
+ a = a - 1;
+ }
+ }
+
+ // Sanitize children
+ this._sanitize(node);
+
+ // Mark node as sanitized so it's ignored in future runs
+ node._sanitized = true;
+ } while ((node = treeWalker.nextSibling()));
+ };
+
+ function createTreeWalker(node) {
+ return document.createTreeWalker(node,
+ NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT,
+ null, false);
+ }
+
+ function getAllowedAttrs(config, nodeName, node){
+ if (typeof config.tags[nodeName] === 'function') {
+ return config.tags[nodeName](node);
+ } else {
+ return config.tags[nodeName];
+ }
+ }
+
+ function shouldRejectNode(node, allowedAttrs){
+ if (typeof allowedAttrs === 'undefined') {
+ return true;
+ } else if (typeof allowedAttrs === 'boolean') {
+ return !allowedAttrs;
+ }
+
+ return false;
+ }
+
+ function shouldRejectAttr(attr, allowedAttrs, node){
+ var attrName = attr.name.toLowerCase();
+
+ if (allowedAttrs === true){
+ return false;
+ } else if (typeof allowedAttrs[attrName] === 'function'){
+ return !allowedAttrs[attrName](attr.value, node);
+ } else if (typeof allowedAttrs[attrName] === 'undefined'){
+ return true;
+ } else if (allowedAttrs[attrName] === false) {
+ return true;
+ } else if (typeof allowedAttrs[attrName] === 'string') {
+ return (allowedAttrs[attrName] !== attr.value);
+ }
+
+ return false;
+ }
+
+ return HTMLJanitor;
+
+ }));
+
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * Codex Editor Saver
+ *
+ * @author Codex Team
+ * @version 1.1.0
+ */
+
+ module.exports = function (saver) {
+
+ var editor = codex.editor;
+
+ /**
+ * @public
+ * Save blocks
+ */
+ saver.save = function () {
+
+ /** Save html content of redactor to memory */
+ editor.state.html = editor.nodes.redactor.innerHTML;
+
+ /** Clean jsonOutput state */
+ editor.state.jsonOutput = [];
+
+ return saveBlocks(editor.nodes.redactor.childNodes);
+ };
+
+ /**
+ * @private
+ * Save each block data
+ *
+ * @param blocks
+ * @returns {Promise.}
+ */
+ var saveBlocks = function saveBlocks(blocks) {
+
+ var data = [];
+
+ for (var index = 0; index < blocks.length; index++) {
+
+ data.push(getBlockData(blocks[index]));
+ }
+
+ return Promise.all(data).then(makeOutput).catch(editor.core.log);
+ };
+
+ /** Save and validate block data */
+ var getBlockData = function getBlockData(block) {
+
+ return saveBlockData(block).then(validateBlockData).catch(editor.core.log);
+ };
+
+ /**
+ * @private
+ * Call block`s plugin save method and return saved data
+ *
+ * @param block
+ * @returns {Object}
+ */
+ var saveBlockData = function saveBlockData(block) {
+
+ var pluginName = block.dataset.tool;
+
+ /** Check for plugin existence */
+ if (!editor.tools[pluginName]) {
+
+ editor.core.log('Plugin \xAB' + pluginName + '\xBB not found', 'error');
+ return { data: null, pluginName: null };
+ }
+
+ /** Check for plugin having save method */
+ if (typeof editor.tools[pluginName].save !== 'function') {
+
+ editor.core.log('Plugin \xAB' + pluginName + '\xBB must have save method', 'error');
+ return { data: null, pluginName: null };
+ }
+
+ /** Result saver */
+ var blockContent = block.childNodes[0],
+ pluginsContent = blockContent.childNodes[0],
+ position = pluginsContent.dataset.inputPosition;
+
+ /** If plugin wasn't available then return data from cache */
+ if (editor.tools[pluginName].available === false) {
+
+ return Promise.resolve({ data: codex.editor.state.blocks.items[position].data, pluginName: pluginName });
+ }
+
+ return Promise.resolve(pluginsContent).then(editor.tools[pluginName].save).then(function (data) {
+ return Object({ data: data, pluginName: pluginName });
+ });
+ };
+
+ /**
+ * Call plugin`s validate method. Return false if validation failed
+ *
+ * @param data
+ * @param pluginName
+ * @returns {Object|Boolean}
+ */
+ var validateBlockData = function validateBlockData(_ref) {
+ var data = _ref.data,
+ pluginName = _ref.pluginName;
+
+
+ if (!data || !pluginName) {
+
+ return false;
+ }
+
+ if (editor.tools[pluginName].validate) {
+
+ var result = editor.tools[pluginName].validate(data);
+
+ /**
+ * Do not allow invalid data
+ */
+ if (!result) {
+
+ return false;
+ }
+ }
+
+ return { data: data, pluginName: pluginName };
+ };
+
+ /**
+ * Compile article output
+ *
+ * @param savedData
+ * @returns {{time: number, version, items: (*|Array)}}
+ */
+ var makeOutput = function makeOutput(savedData) {
+
+ savedData = savedData.filter(function (blockData) {
+ return blockData;
+ });
+
+ var items = savedData.map(function (blockData) {
+ return Object({ type: blockData.pluginName, data: blockData.data });
+ });
+
+ editor.state.jsonOutput = items;
+
+ return {
+ id: editor.state.blocks.id || null,
+ time: +new Date(),
+ version: editor.version,
+ items: items
+ };
+ };
+
+ return saver;
+ }({});
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports) {
+
+ 'use strict';
+
+ /**
+ *
+ * Codex.Editor Transport Module
+ *
+ * @copyright 2017 Codex-Team
+ * @version 1.2.0
+ */
+
+ module.exports = function (transport) {
+
+ var editor = codex.editor;
+
+ /**
+ * @private {Object} current XmlHttpRequest instance
+ */
+ var currentRequest = null;
+
+ /**
+ * @type {null} | {DOMElement} input - keeps input element in memory
+ */
+ transport.input = null;
+
+ /**
+ * @property {Object} arguments - keep plugin settings and defined callbacks
+ */
+ transport.arguments = null;
+
+ /**
+ * Prepares input element where will be files
+ */
+ transport.prepare = function () {
+
+ var input = editor.draw.node('INPUT', '', { type: 'file' });
+
+ editor.listeners.add(input, 'change', editor.transport.fileSelected);
+ editor.transport.input = input;
+ };
+
+ /** Clear input when files is uploaded */
+ transport.clearInput = function () {
+
+ /** Remove old input */
+ transport.input = null;
+
+ /** Prepare new one */
+ transport.prepare();
+ };
+
+ /**
+ * Callback for file selection
+ * @param {Event} event
+ */
+ transport.fileSelected = function () {
+
+ var input = this,
+ i,
+ files = input.files,
+ formData = new FormData();
+
+ if (editor.transport.arguments.multiple === true) {
+
+ for (i = 0; i < files.length; i++) {
+
+ formData.append('files[]', files[i], files[i].name);
+ }
+ } else {
+
+ formData.append('files', files[0], files[0].name);
+ }
+
+ currentRequest = editor.core.ajax({
+ type: 'POST',
+ data: formData,
+ url: editor.transport.arguments.url,
+ beforeSend: editor.transport.arguments.beforeSend,
+ success: editor.transport.arguments.success,
+ error: editor.transport.arguments.error,
+ progress: editor.transport.arguments.progress
+ });
+
+ /** Clear input */
+ transport.clearInput();
+ };
+
+ /**
+ * Use plugin callbacks
+ * @protected
+ *
+ * @param {Object} args - can have :
+ * @param {String} args.url - fetch URL
+ * @param {Function} args.beforeSend - function calls before sending ajax
+ * @param {Function} args.success - success callback
+ * @param {Function} args.error - on error handler
+ * @param {Function} args.progress - xhr onprogress handler
+ * @param {Boolean} args.multiple - allow select several files
+ * @param {String} args.accept - adds accept attribute
+ */
+ transport.selectAndUpload = function (args) {
+
+ transport.arguments = args;
+
+ if (args.multiple === true) {
+
+ transport.input.setAttribute('multiple', 'multiple');
+ }
+
+ if (args.accept) {
+
+ transport.input.setAttribute('accept', args.accept);
+ }
+
+ transport.input.click();
+ };
+
+ transport.abort = function () {
+
+ currentRequest.abort();
+
+ currentRequest = null;
+ };
+
+ return transport;
+ }({});
+
+/***/ }),
+/* 16 */
+/***/ (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 Events() {
+ _classCallCheck(this, Events);
+
+ this.subscribers = {};
+ }
+
+ _createClass(Events, [{
+ key: "on",
+ value: function on(eventName, callback) {
+
+ if (!(eventName in this.subscribers)) {
+
+ this.subscribers[eventName] = [];
+ }
+
+ // group by events
+ this.subscribers[eventName].push(callback);
+ }
+ }, {
+ key: "emit",
+ value: function emit(eventName, data) {
+
+ this.subscribers[eventName].reduce(function (previousData, currentHandler) {
+
+ var newData = currentHandler(previousData);
+
+ return newData ? newData : previousData;
+ }, data);
+ }
+ }]);
+
+ return Events;
+ }();
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * Inline toolbar
+ *
+ * Contains from tools:
+ * Bold, Italic, Underline and Anchor
+ *
+ * @author Codex Team
+ * @version 1.0
+ */
+
+ module.exports = function (inline) {
+
+ var editor = codex.editor;
+
+ inline.buttonsOpened = null;
+ inline.actionsOpened = null;
+ inline.wrappersOffset = null;
+
+ /**
+ * saving selection that need for execCommand for styling
+ *
+ */
+ inline.storedSelection = null;
+
+ /**
+ * @protected
+ *
+ * Open inline toobar
+ */
+ inline.show = function () {
+
+ var currentNode = editor.content.currentNode,
+ tool = currentNode.dataset.tool,
+ plugin;
+
+ /**
+ * tool allowed to open inline toolbar
+ */
+ plugin = editor.tools[tool];
+
+ if (!plugin.showInlineToolbar) return;
+
+ var selectedText = inline.getSelectionText(),
+ toolbar = editor.nodes.inlineToolbar.wrapper;
+
+ if (selectedText.length > 0) {
+
+ /** Move toolbar and open */
+ editor.toolbar.inline.move();
+
+ /** Open inline toolbar */
+ toolbar.classList.add('opened');
+
+ /** show buttons of inline toolbar */
+ editor.toolbar.inline.showButtons();
+ }
+ };
+
+ /**
+ * @protected
+ *
+ * Closes inline toolbar
+ */
+ inline.close = function () {
+
+ var toolbar = editor.nodes.inlineToolbar.wrapper;
+
+ toolbar.classList.remove('opened');
+ };
+
+ /**
+ * @private
+ *
+ * Moving toolbar
+ */
+ inline.move = function () {
+
+ if (!this.wrappersOffset) {
+
+ this.wrappersOffset = this.getWrappersOffset();
+ }
+
+ var coords = this.getSelectionCoords(),
+ defaultOffset = 0,
+ toolbar = editor.nodes.inlineToolbar.wrapper,
+ newCoordinateX,
+ newCoordinateY;
+
+ if (toolbar.offsetHeight === 0) {
+
+ defaultOffset = 40;
+ }
+
+ newCoordinateX = coords.x - this.wrappersOffset.left;
+ newCoordinateY = coords.y + window.scrollY - this.wrappersOffset.top - defaultOffset - toolbar.offsetHeight;
+
+ toolbar.style.transform = 'translate3D(' + Math.floor(newCoordinateX) + 'px, ' + Math.floor(newCoordinateY) + 'px, 0)';
+
+ /** Close everything */
+ editor.toolbar.inline.closeButtons();
+ editor.toolbar.inline.closeAction();
+ };
+
+ /**
+ * @private
+ *
+ * Tool Clicked
+ */
+
+ inline.toolClicked = function (event, type) {
+
+ /**
+ * For simple tools we use default browser function
+ * For more complicated tools, we should write our own behavior
+ */
+ switch (type) {
+ case 'createLink':
+ editor.toolbar.inline.createLinkAction(event, type);break;
+ default:
+ editor.toolbar.inline.defaultToolAction(type);break;
+ }
+
+ /**
+ * highlight buttons
+ * after making some action
+ */
+ editor.nodes.inlineToolbar.buttons.childNodes.forEach(editor.toolbar.inline.hightlight);
+ };
+
+ /**
+ * @private
+ *
+ * Saving wrappers offset in DOM
+ */
+ inline.getWrappersOffset = function () {
+
+ var wrapper = editor.nodes.wrapper,
+ offset = this.getOffset(wrapper);
+
+ this.wrappersOffset = offset;
+ return offset;
+ };
+
+ /**
+ * @private
+ *
+ * Calculates offset of DOM element
+ *
+ * @param el
+ * @returns {{top: number, left: number}}
+ */
+ inline.getOffset = function (el) {
+
+ var _x = 0;
+ var _y = 0;
+
+ while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
+
+ _x += el.offsetLeft + el.clientLeft;
+ _y += el.offsetTop + el.clientTop;
+ el = el.offsetParent;
+ }
+ return { top: _y, left: _x };
+ };
+
+ /**
+ * @private
+ *
+ * Calculates position of selected text
+ * @returns {{x: number, y: number}}
+ */
+ inline.getSelectionCoords = function () {
+
+ var sel = document.selection,
+ range;
+ var x = 0,
+ y = 0;
+
+ if (sel) {
+
+ if (sel.type != 'Control') {
+
+ range = sel.createRange();
+ range.collapse(true);
+ x = range.boundingLeft;
+ y = range.boundingTop;
+ }
+ } else if (window.getSelection) {
+
+ sel = window.getSelection();
+
+ if (sel.rangeCount) {
+
+ range = sel.getRangeAt(0).cloneRange();
+ if (range.getClientRects) {
+
+ range.collapse(true);
+ var rect = range.getClientRects()[0];
+
+ if (!rect) {
+
+ return;
+ }
+
+ x = rect.left;
+ y = rect.top;
+ }
+ }
+ }
+ return { x: x, y: y };
+ };
+
+ /**
+ * @private
+ *
+ * Returns selected text as String
+ * @returns {string}
+ */
+ inline.getSelectionText = function () {
+
+ var selectedText = '';
+
+ // all modern browsers and IE9+
+ if (window.getSelection) {
+
+ selectedText = window.getSelection().toString();
+ }
+
+ return selectedText;
+ };
+
+ /** Opens buttons block */
+ inline.showButtons = function () {
+
+ var buttons = editor.nodes.inlineToolbar.buttons;
+
+ buttons.classList.add('opened');
+
+ editor.toolbar.inline.buttonsOpened = true;
+
+ /** highlight buttons */
+ editor.nodes.inlineToolbar.buttons.childNodes.forEach(editor.toolbar.inline.hightlight);
+ };
+
+ /** Makes buttons disappear */
+ inline.closeButtons = function () {
+
+ var buttons = editor.nodes.inlineToolbar.buttons;
+
+ buttons.classList.remove('opened');
+
+ editor.toolbar.inline.buttonsOpened = false;
+ };
+
+ /** Open buttons defined action if exist */
+ inline.showActions = function () {
+
+ var action = editor.nodes.inlineToolbar.actions;
+
+ action.classList.add('opened');
+
+ editor.toolbar.inline.actionsOpened = true;
+ };
+
+ /** Close actions block */
+ inline.closeAction = function () {
+
+ var action = editor.nodes.inlineToolbar.actions;
+
+ action.innerHTML = '';
+ action.classList.remove('opened');
+ editor.toolbar.inline.actionsOpened = false;
+ };
+
+ /**
+ * Callback for keydowns in inline toolbar "Insert link..." input
+ */
+ var inlineToolbarAnchorInputKeydown_ = function inlineToolbarAnchorInputKeydown_(event) {
+
+ if (event.keyCode != editor.core.keys.ENTER) {
+
+ return;
+ }
+
+ var editable = editor.content.currentNode,
+ storedSelection = editor.toolbar.inline.storedSelection;
+
+ editor.toolbar.inline.restoreSelection(editable, storedSelection);
+ editor.toolbar.inline.setAnchor(this.value);
+
+ /**
+ * Preventing events that will be able to happen
+ */
+ event.preventDefault();
+ event.stopImmediatePropagation();
+
+ editor.toolbar.inline.clearRange();
+ };
+
+ /** Action for link creation or for setting anchor */
+ inline.createLinkAction = function (event) {
+
+ var isActive = this.isLinkActive();
+
+ var editable = editor.content.currentNode,
+ storedSelection = editor.toolbar.inline.saveSelection(editable);
+
+ /** Save globally selection */
+ editor.toolbar.inline.storedSelection = storedSelection;
+
+ if (isActive) {
+
+ /**
+ * Changing stored selection. if we want to remove anchor from word
+ * we should remove anchor from whole word, not only selected part.
+ * The solution is than we get the length of current link
+ * Change start position to - end of selection minus length of anchor
+ */
+ editor.toolbar.inline.restoreSelection(editable, storedSelection);
+
+ editor.toolbar.inline.defaultToolAction('unlink');
+ } else {
+
+ /** Create input and close buttons */
+ var action = editor.draw.inputForLink();
+
+ editor.nodes.inlineToolbar.actions.appendChild(action);
+
+ editor.toolbar.inline.closeButtons();
+ editor.toolbar.inline.showActions();
+
+ /**
+ * focus to input
+ * Solution: https://developer.mozilla.org/ru/docs/Web/API/HTMLElement/focus
+ * Prevents event after showing input and when we need to focus an input which is in unexisted form
+ */
+ action.focus();
+ event.preventDefault();
+
+ /** Callback to link action */
+ editor.listeners.add(action, 'keydown', inlineToolbarAnchorInputKeydown_, false);
+ }
+ };
+
+ inline.isLinkActive = function () {
+
+ var isActive = false;
+
+ editor.nodes.inlineToolbar.buttons.childNodes.forEach(function (tool) {
+
+ var dataType = tool.dataset.type;
+
+ if (dataType == 'link' && tool.classList.contains('hightlighted')) {
+
+ isActive = true;
+ }
+ });
+
+ return isActive;
+ };
+
+ /** default action behavior of tool */
+ inline.defaultToolAction = function (type) {
+
+ document.execCommand(type, false, null);
+ };
+
+ /**
+ * @private
+ *
+ * Sets URL
+ *
+ * @param {String} url - URL
+ */
+ inline.setAnchor = function (url) {
+
+ document.execCommand('createLink', false, url);
+
+ /** Close after URL inserting */
+ editor.toolbar.inline.closeAction();
+ };
+
+ /**
+ * @private
+ *
+ * Saves selection
+ */
+ inline.saveSelection = function (containerEl) {
+
+ var range = window.getSelection().getRangeAt(0),
+ preSelectionRange = range.cloneRange(),
+ start;
+
+ preSelectionRange.selectNodeContents(containerEl);
+ preSelectionRange.setEnd(range.startContainer, range.startOffset);
+
+ start = preSelectionRange.toString().length;
+
+ return {
+ start: start,
+ end: start + range.toString().length
+ };
+ };
+
+ /**
+ * @private
+ *
+ * Sets to previous selection (Range)
+ *
+ * @param {Element} containerEl - editable element where we restore range
+ * @param {Object} savedSel - range basic information to restore
+ */
+ inline.restoreSelection = function (containerEl, savedSel) {
+
+ var range = document.createRange(),
+ charIndex = 0;
+
+ range.setStart(containerEl, 0);
+ range.collapse(true);
+
+ var nodeStack = [containerEl],
+ node,
+ foundStart = false,
+ stop = false,
+ nextCharIndex;
+
+ while (!stop && (node = nodeStack.pop())) {
+
+ if (node.nodeType == 3) {
+
+ nextCharIndex = charIndex + node.length;
+
+ if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
+
+ range.setStart(node, savedSel.start - charIndex);
+ foundStart = true;
+ }
+ if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
+
+ range.setEnd(node, savedSel.end - charIndex);
+ stop = true;
+ }
+ charIndex = nextCharIndex;
+ } else {
+
+ var i = node.childNodes.length;
+
+ while (i--) {
+
+ nodeStack.push(node.childNodes[i]);
+ }
+ }
+ }
+
+ var sel = window.getSelection();
+
+ sel.removeAllRanges();
+ sel.addRange(range);
+ };
+
+ /**
+ * @private
+ *
+ * Removes all ranges from window selection
+ */
+ inline.clearRange = function () {
+
+ var selection = window.getSelection();
+
+ selection.removeAllRanges();
+ };
+
+ /**
+ * @private
+ *
+ * sets or removes hightlight
+ */
+ inline.hightlight = function (tool) {
+
+ var dataType = tool.dataset.type;
+
+ if (document.queryCommandState(dataType)) {
+
+ editor.toolbar.inline.setButtonHighlighted(tool);
+ } else {
+
+ editor.toolbar.inline.removeButtonsHighLight(tool);
+ }
+
+ /**
+ *
+ * hightlight for anchors
+ */
+ var selection = window.getSelection(),
+ tag = selection.anchorNode.parentNode;
+
+ if (tag.tagName == 'A' && dataType == 'link') {
+
+ editor.toolbar.inline.setButtonHighlighted(tool);
+ }
+ };
+
+ /**
+ * @private
+ *
+ * Mark button if text is already executed
+ */
+ inline.setButtonHighlighted = function (button) {
+
+ button.classList.add('hightlighted');
+
+ /** At link tool we also change icon */
+ if (button.dataset.type == 'link') {
+
+ var icon = button.childNodes[0];
+
+ icon.classList.remove('ce-icon-link');
+ icon.classList.add('ce-icon-unlink');
+ }
+ };
+
+ /**
+ * @private
+ *
+ * Removes hightlight
+ */
+ inline.removeButtonsHighLight = function (button) {
+
+ button.classList.remove('hightlighted');
+
+ /** At link tool we also change icon */
+ if (button.dataset.type == 'link') {
+
+ var icon = button.childNodes[0];
+
+ icon.classList.remove('ce-icon-unlink');
+ icon.classList.add('ce-icon-link');
+ }
+ };
+
+ return inline;
+ }({});
+
+/***/ }),
+/* 18 */
+/***/ (function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * Toolbar settings
+ *
+ * @version 1.0.5
+ */
+
+ module.exports = function (settings) {
+
+ var editor = codex.editor;
+
+ settings.opened = false;
+
+ settings.setting = null;
+ settings.actions = null;
+
+ /**
+ * Append and open settings
+ */
+ settings.open = function (toolType) {
+
+ /**
+ * Append settings content
+ * It's stored in tool.settings
+ */
+ if (!editor.tools[toolType] || !editor.tools[toolType].makeSettings) {
+
+ return;
+ }
+
+ /**
+ * Draw settings block
+ */
+ var settingsBlock = editor.tools[toolType].makeSettings();
+
+ editor.nodes.pluginSettings.appendChild(settingsBlock);
+
+ /** Open settings block */
+ editor.nodes.blockSettings.classList.add('opened');
+ this.opened = true;
+ };
+
+ /**
+ * Close and clear settings
+ */
+ settings.close = function () {
+
+ editor.nodes.blockSettings.classList.remove('opened');
+ editor.nodes.pluginSettings.innerHTML = '';
+
+ this.opened = false;
+ };
+
+ /**
+ * @param {string} toolType - plugin type
+ */
+ settings.toggle = function (toolType) {
+
+ if (!this.opened) {
+
+ this.open(toolType);
+ } else {
+
+ this.close();
+ }
+ };
+
+ /**
+ * Here we will draw buttons and add listeners to components
+ */
+ settings.makeRemoveBlockButton = function () {
+
+ var removeBlockWrapper = editor.draw.node('SPAN', 'ce-toolbar__remove-btn', {}),
+ settingButton = editor.draw.node('SPAN', 'ce-toolbar__remove-setting', { innerHTML: '' }),
+ actionWrapper = editor.draw.node('DIV', 'ce-toolbar__remove-confirmation', {}),
+ confirmAction = editor.draw.node('DIV', 'ce-toolbar__remove-confirm', { textContent: 'Удалить блок' }),
+ cancelAction = editor.draw.node('DIV', 'ce-toolbar__remove-cancel', { textContent: 'Отмена' });
+
+ editor.listeners.add(settingButton, 'click', editor.toolbar.settings.removeButtonClicked, false);
+
+ editor.listeners.add(confirmAction, 'click', editor.toolbar.settings.confirmRemovingRequest, false);
+
+ editor.listeners.add(cancelAction, 'click', editor.toolbar.settings.cancelRemovingRequest, false);
+
+ actionWrapper.appendChild(confirmAction);
+ actionWrapper.appendChild(cancelAction);
+
+ removeBlockWrapper.appendChild(settingButton);
+ removeBlockWrapper.appendChild(actionWrapper);
+
+ /** Save setting */
+ editor.toolbar.settings.setting = settingButton;
+ editor.toolbar.settings.actions = actionWrapper;
+
+ return removeBlockWrapper;
+ };
+
+ settings.removeButtonClicked = function () {
+
+ var action = editor.toolbar.settings.actions;
+
+ if (action.classList.contains('opened')) {
+
+ editor.toolbar.settings.hideRemoveActions();
+ } else {
+
+ editor.toolbar.settings.showRemoveActions();
+ }
+
+ editor.toolbar.toolbox.close();
+ editor.toolbar.settings.close();
+ };
+
+ settings.cancelRemovingRequest = function () {
+
+ editor.toolbar.settings.actions.classList.remove('opened');
+ };
+
+ settings.confirmRemovingRequest = function () {
+
+ var currentBlock = editor.content.currentNode,
+ firstLevelBlocksCount;
+
+ currentBlock.remove();
+
+ firstLevelBlocksCount = editor.nodes.redactor.childNodes.length;
+
+ /**
+ * If all blocks are removed
+ */
+ if (firstLevelBlocksCount === 0) {
+
+ /** update currentNode variable */
+ editor.content.currentNode = null;
+
+ /** Inserting new empty initial block */
+ editor.ui.addInitialBlock();
+ }
+
+ editor.ui.saveInputs();
+
+ editor.toolbar.close();
+ };
+
+ settings.showRemoveActions = function () {
+
+ editor.toolbar.settings.actions.classList.add('opened');
+ };
+
+ settings.hideRemoveActions = function () {
+
+ editor.toolbar.settings.actions.classList.remove('opened');
+ };
+
+ return settings;
+ }({});
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ /**
+ * Codex Editor toolbar module
+ *
+ * Contains:
+ * - Inline toolbox
+ * - Toolbox within plus button
+ * - Settings section
+ *
+ * @author Codex Team
+ * @version 1.0
+ */
+
+ module.exports = function (toolbar) {
+
+ var editor = codex.editor;
+
+ toolbar.settings = __webpack_require__(18);
+ toolbar.inline = __webpack_require__(17);
+ toolbar.toolbox = __webpack_require__(20);
+
+ /**
+ * Margin between focused node and toolbar
+ */
+ toolbar.defaultToolbarHeight = 49;
+
+ toolbar.defaultOffset = 34;
+
+ toolbar.opened = false;
+
+ toolbar.current = null;
+
+ /**
+ * @protected
+ */
+ toolbar.open = function () {
+
+ if (editor.hideToolbar) {
+
+ return;
+ }
+
+ var toolType = editor.content.currentNode.dataset.tool;
+
+ if (!editor.tools[toolType] || !editor.tools[toolType].makeSettings) {
+
+ editor.nodes.showSettingsButton.classList.add('hide');
+ } else {
+
+ editor.nodes.showSettingsButton.classList.remove('hide');
+ }
+
+ editor.nodes.toolbar.classList.add('opened');
+ this.opened = true;
+ };
+
+ /**
+ * @protected
+ */
+ toolbar.close = function () {
+
+ editor.nodes.toolbar.classList.remove('opened');
+
+ toolbar.opened = false;
+ toolbar.current = null;
+
+ for (var button in editor.nodes.toolbarButtons) {
+
+ editor.nodes.toolbarButtons[button].classList.remove('selected');
+ }
+
+ /** Close toolbox when toolbar is not displayed */
+ editor.toolbar.toolbox.close();
+ editor.toolbar.settings.close();
+ };
+
+ toolbar.toggle = function () {
+
+ if (!this.opened) {
+
+ this.open();
+ } else {
+
+ this.close();
+ }
+ };
+
+ toolbar.hidePlusButton = function () {
+
+ editor.nodes.plusButton.classList.add('hide');
+ };
+
+ toolbar.showPlusButton = function () {
+
+ editor.nodes.plusButton.classList.remove('hide');
+ };
+
+ /**
+ * Moving toolbar to the specified node
+ */
+ toolbar.move = function () {
+
+ /** Close Toolbox when we move toolbar */
+ editor.toolbar.toolbox.close();
+
+ if (!editor.content.currentNode) {
+
+ return;
+ }
+
+ var newYCoordinate = editor.content.currentNode.offsetTop - editor.toolbar.defaultToolbarHeight / 2 + editor.toolbar.defaultOffset;
+
+ editor.nodes.toolbar.style.transform = 'translate3D(0, ' + Math.floor(newYCoordinate) + 'px, 0)';
+
+ /** Close trash actions */
+ editor.toolbar.settings.hideRemoveActions();
+ };
+
+ return toolbar;
+ }({});
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports) {
+
+ 'use strict';
+
+ /**
+ * Codex Editor toolbox
+ *
+ * All tools be able to appended here
+ *
+ * @author Codex Team
+ * @version 1.0
+ */
+
+ module.exports = function (toolbox) {
+
+ var editor = codex.editor;
+
+ toolbox.opened = false;
+ toolbox.openedOnBlock = null;
+
+ /** Shows toolbox */
+ toolbox.open = function () {
+
+ /** Close setting if toolbox is opened */
+ if (editor.toolbar.settings.opened) {
+
+ editor.toolbar.settings.close();
+ }
+
+ /** Add 'toolbar-opened' class for current block **/
+ toolbox.openedOnBlock = editor.content.currentNode;
+ toolbox.openedOnBlock.classList.add('toolbar-opened');
+
+ /** display toolbox */
+ editor.nodes.toolbox.classList.add('opened');
+
+ /** Animate plus button */
+ editor.nodes.plusButton.classList.add('clicked');
+
+ /** toolbox state */
+ editor.toolbar.toolbox.opened = true;
+ };
+
+ /** Closes toolbox */
+ toolbox.close = function () {
+
+ /** Remove 'toolbar-opened' class from current block **/
+ if (toolbox.openedOnBlock) toolbox.openedOnBlock.classList.remove('toolbar-opened');
+ toolbox.openedOnBlock = null;
+
+ /** Makes toolbox disappear */
+ editor.nodes.toolbox.classList.remove('opened');
+
+ /** Rotate plus button */
+ editor.nodes.plusButton.classList.remove('clicked');
+
+ /** toolbox state */
+ editor.toolbar.toolbox.opened = false;
+
+ editor.toolbar.current = null;
+ };
+
+ toolbox.leaf = function () {
+
+ var currentTool = editor.toolbar.current,
+ tools = Object.keys(editor.tools),
+ barButtons = editor.nodes.toolbarButtons,
+ nextToolIndex = 0,
+ toolToSelect = void 0,
+ visibleTool = void 0,
+ tool = void 0;
+
+ if (!currentTool) {
+
+ /** Get first tool from object*/
+ for (tool in editor.tools) {
+
+ if (editor.tools[tool].displayInToolbox) {
+
+ break;
+ }
+
+ nextToolIndex++;
+ }
+ } else {
+
+ nextToolIndex = (tools.indexOf(currentTool) + 1) % tools.length;
+ visibleTool = tools[nextToolIndex];
+
+ while (!editor.tools[visibleTool].displayInToolbox) {
+
+ nextToolIndex = (nextToolIndex + 1) % tools.length;
+ visibleTool = tools[nextToolIndex];
+ }
+ }
+
+ toolToSelect = tools[nextToolIndex];
+
+ for (var button in barButtons) {
+
+ barButtons[button].classList.remove('selected');
+ }
+
+ barButtons[toolToSelect].classList.add('selected');
+ editor.toolbar.current = toolToSelect;
+ };
+
+ /**
+ * Transforming selected node type into selected toolbar element type
+ * @param {event} event
+ */
+ toolbox.toolClicked = function (event) {
+
+ /**
+ * UNREPLACEBLE_TOOLS this types of tools are forbidden to replace even they are empty
+ */
+ var UNREPLACEBLE_TOOLS = ['image', 'link', 'list', 'instagram', 'twitter', 'embed'],
+ tool = editor.tools[editor.toolbar.current],
+ workingNode = editor.content.currentNode,
+ currentInputIndex = editor.caret.inputIndex,
+ newBlockContent,
+ appendCallback,
+ blockData;
+
+ /** Make block from plugin */
+ newBlockContent = tool.render();
+
+ /** information about block */
+ blockData = {
+ block: newBlockContent,
+ type: tool.type,
+ stretched: false
+ };
+
+ if (workingNode && UNREPLACEBLE_TOOLS.indexOf(workingNode.dataset.tool) === -1 && workingNode.textContent.trim() === '') {
+
+ /** Replace current block */
+ editor.content.switchBlock(workingNode, newBlockContent, tool.type);
+ } else {
+
+ /** Insert new Block from plugin */
+ editor.content.insertBlock(blockData);
+
+ /** increase input index */
+ currentInputIndex++;
+ }
+
+ /** Fire tool append callback */
+ appendCallback = tool.appendCallback;
+
+ if (appendCallback && typeof appendCallback == 'function') {
+
+ appendCallback.call(event);
+ }
+
+ window.setTimeout(function () {
+
+ /** Set caret to current block */
+ editor.caret.setToBlock(currentInputIndex);
+ }, 10);
+
+ /**
+ * Changing current Node
+ */
+ editor.content.workingNodeChanged();
+
+ /**
+ * Move toolbar when node is changed
+ */
+ editor.toolbar.move();
+ };
+
+ return toolbox;
+ }({});
+
+/***/ }),
+/* 21 */
+/***/ (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 Codex Editor Tools Submodule
+ *
+ * Creates Instances from Plugins and binds external config to the instances
+ */
+
+ /**
+ * Load user defined tools
+ * Tools must contain the following important objects:
+ *
+ * @typedef {Object} ToolsConfig
+ * @property {String} iconClassname - this a icon in toolbar
+ * @property {Boolean} displayInToolbox - will be displayed in toolbox. Default value is TRUE
+ * @property {Boolean} enableLineBreaks - inserts new block or break lines. Default value is FALSE
+ */
+
+ /**
+ * Class properties:
+ *
+ * @property {String} this.name - name of this module
+ * @property {Array} this.toolInstances - list of tool instances
+ *
+ */
+ module.exports = function () {
+ _createClass(Tools, [{
+ key: 'state',
+
+
+ /**
+ * @param Editor
+ * @param Editor.modules {@link CodexEditor#moduleInstances}
+ * @param Editor.config {@link CodexEditor#configuration}
+ */
+ set: function set(Editor) {
+
+ this.Editor = Editor;
+ }
+
+ /**
+ * If config wasn't passed by user
+ * @return {ToolsConfig}
+ */
+
+ }, {
+ key: 'defaultConfig',
+ get: function get() {
+
+ return {
+ iconClassName: 'default-icon',
+ displayInToolbox: false,
+ enableLineBreaks: false
+ };
+ }
+
+ /**
+ * @constructor
+ *
+ * @param {ToolsConfig} config
+ */
+
+ }], [{
+ key: 'name',
+ get: function get() {
+
+ return 'tools';
+ }
+ }]);
+
+ function Tools(config) {
+ _classCallCheck(this, Tools);
+
+ this.config = config;
+
+ this.availabPlugins = {};
+ this.toolInstances = [];
+ }
+
+ /**
+ * Creates instances via passed or default configuration
+ * @return {boolean}
+ */
+
+
+ _createClass(Tools, [{
+ key: 'prepare',
+ value: function prepare() {
+
+ var toolConfig = this.defaultConfig;
+
+ if (!this.config.hasOwnProperty('tools')) {
+
+ return false;
+ }
+
+ /**
+ * Preparation Decorator
+ *
+ * @param toolBindedPreparationFunction
+ * @return {Promise}
+ */
+ function waitNextToolPreparation(toolBindedPreparationFunction) {
+
+ return new Promise(function (resolve, reject) {
+
+ toolBindedPreparationFunction().then(resolve).catch(function (error) {
+
+ console.log('Plugin is not available because of ', error);
+
+ // anyway, go ahead even plugin is not available
+ resolve();
+ });
+ });
+ }
+
+ return new Promise(function (resolvePreparation, rejectPreparation) {
+
+ var toolPreparationList = [];
+
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = this.config.tools[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ var tool = _step.value;
+
+
+ var toolName = tool.name;
+
+ if (toolName in this.config.toolsConfig) {
+
+ toolConfig = this.config.toolsConfig[toolName];
+ }
+
+ if (tool.prepare && typeof tool.prepare === 'function') {
+
+ toolPreparationList.push(tool.prepare.bind(toolConfig));
+ }
+ }
+
+ // continue editor initialization if non of tools doesn't need preparation
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+
+ if (toolPreparationList.length === 0) {
+
+ resolvePreparation();
+ } else {
+
+ toolPreparationList.reduce(function (previousToolPrepared, currentToolReadyToPreparation, iteration) {
+
+ return previousToolPrepared.then(function () {
+ return waitNextToolPreparation(currentToolReadyToPreparation);
+ }).then(function () {
+
+ if (iteration == toolPreparationList.length - 1) {
+
+ resolvePreparation();
+ }
+ });
+ }, Promise.resolve());
+ }
+ });
+
+ /**
+ * - getting class and config
+ * - push to the toolinstnaces property created instances
+ */
+ // for(let tool in this.config.tools) {
+ // let toolClass = this.config.tools[tool],
+ // toolConfig;
+ //
+ // if (tool in this.config.toolConfig) {
+ // toolConfig = this.config.toolConfig[tool];
+ // } else {
+ // toolConfig = this.defaultConfig;
+ // }
+ //
+ // this.toolInstances.push(new toolClass(toolConfig));
+ // }
+ }
+
+ /**
+ * Returns all tools
+ * @return {Array}
+ */
+
+ }, {
+ key: 'getTools',
+ value: function getTools() {
+
+ return this.toolInstances;
+ }
+ }]);
+
+ return Tools;
+ }();
+ // /**
+ // * Module working with plugins
+ // */
+ // module.exports = (function () {
+ //
+ // let editor = codex.editor;
+ //
+ // /**
+ // * Initialize plugins before using
+ // * Ex. Load scripts or call some internal methods
+ // * @return Promise
+ // */
+ // function prepare() {
+ //
+ // 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) {
+ //
+ // /**
+ // * @calls allPluginsProcessed__ when all plugins prepared or failed
+ // */
+ // return new Promise (function (allPluginsProcessed__) {
+ //
+ // /**
+ // * pluck each element from queue
+ // * First, send resolved Promise as previous value
+ // * Each plugins "prepare" method returns a Promise, that's why
+ // * reduce current element will not be able to continue while can't get
+ // * a resolved Promise
+ // *
+ // * If last plugin is "prepared" then go to the next stage of initialization
+ // */
+ // plugins.reduce(function (previousValue, plugin, iteration) {
+ //
+ // return previousValue.then(function () {
+ //
+ // /**
+ // * Wait till plugins prepared
+ // * @calls pluginIsReady__ when plugin is ready or failed
+ // */
+ // return new Promise ( function (pluginIsReady__) {
+ //
+ // callPluginsPrepareMethod_( plugin )
+ //
+ // .then( pluginIsReady__ )
+ // .then( function () {
+ //
+ // plugin.available = true;
+ //
+ // })
+ //
+ // .catch(function (error) {
+ //
+ // editor.core.log(`Plugin «${plugin.type}» was not loaded. Preparation failed because %o`, 'warn', error);
+ // plugin.available = false;
+ // plugin.loadingMessage = error;
+ //
+ // /** Go ahead even some plugin has problems */
+ // pluginIsReady__();
+ //
+ // })
+ //
+ // .then(function () {
+ //
+ // /** If last plugin has problems then just ignore and continue */
+ // if (iteration == plugins.length - 1) {
+ //
+ // allPluginsProcessed__();
+ //
+ // }
+ //
+ // });
+ //
+ // });
+ //
+ // });
+ //
+ // }, Promise.resolve() );
+ //
+ // });
+ //
+ // }
+ //
+ // var callPluginsPrepareMethod_ = function (plugin) {
+ //
+ // return plugin.prepare( plugin.config || {} );
+ //
+ // };
+ //
+ // return {
+ // prepare: prepare
+ // };
+ //
+ // }());
+
+/***/ }),
+/* 22 */
+/***/ (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 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'
+ };
+
+ /**
+ * @class
+ *
+ * @classdesc Makes CodeX Editor UI:
+ *
+ *
+ *
+ *
+ *
+ *
+ * @property {EditorConfig} config - editor configuration {@link CodexEditor#configuration}
+ * @property {Object} Editor - available editor modules {@link CodexEditor#moduleInstances}
+ */
+ module.exports = function () {
+ _createClass(UI, null, [{
+ key: 'name',
+
+
+ /**
+ * Module key name
+ * @returns {string}
+ */
+ get: function get() {
+
+ return 'ui';
+ }
+
+ /**
+ * @constructor
+ *
+ * @param {EditorConfig} config
+ */
+
+ }]);
+
+ function UI(config) {
+ _classCallCheck(this, UI);
+
+ this.config = config;
+ this.Editor = null;
+ }
+
+ /**
+ * Editor modules setter
+ * @param {object} Editor - available editor modules
+ */
+
+
+ _createClass(UI, [{
+ key: 'prepare',
+
+
+ /**
+ * @protected
+ *
+ * Making main interface
+ */
+ value: function prepare() {
+
+ console.log('ui prepare fired');
+
+ return;
+
+ return new Promise(function (resolve, reject) {
+
+ var wrapper = this.modules.dom.make('DIV', [CSS_.editorWrapper], {}),
+ redactor = this.modules.dom.make('DIV', [CSS_.editorZone], {}),
+ toolbar = makeToolBar_();
+
+ wrapper.appendChild(toolbar);
+ wrapper.appendChild(redactor);
+
+ /** Save created ui-elements to static nodes state */
+ editor.nodes.wrapper = wrapper;
+ editor.nodes.redactor = redactor;
+
+ /** Append editor wrapper with redactor zone into holder */
+ editor.nodes.holder.appendChild(wrapper);
+
+ resolve();
+ })
+
+ /** Add toolbox tools */
+ .then(addTools_)
+
+ /** Make container for inline toolbar */
+ .then(makeInlineToolbar_)
+
+ /** Add inline toolbar tools */
+ .then(addInlineToolbarTools_)
+
+ /** Draw wrapper for notifications */
+ .then(makeNotificationHolder_)
+
+ /** Add eventlisteners to redactor elements */
+ .then(bindEvents_).catch(function () {
+
+ editor.core.log("Can't draw editor interface");
+ });
+ }
+ }, {
+ key: 'state',
+ set: function set(Editor) {
+
+ this.Editor = Editor;
+ }
+ }]);
+
+ return UI;
+ }();
+ // /**
+ // * Codex Editor UI module
+ // *
+ // * @author Codex Team
+ // * @version 1.2.0
+ // */
+ //
+ // module.exports = (function (ui) {
+ //
+ // let editor = codex.editor;
+ //
+ // /**
+ // * Basic editor classnames
+ // */
+ // ui.prepare = function () {
+ //
+
+ //
+ // };
+ //
+ // /**
+ // * @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);
+ //
+ // /**
+ // * 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);
+ // /**
+ // * Add callbacks to this buttons
+ // */
+ // editor.ui.setInlineToolbarButtonBehaviour(toolButton, tool.command);
+ //
+ // }
+ //
+ // };
+ //
+ // /**
+ // * @private
+ // * Bind editor UI events
+ // */
+ // var bindEvents_ = function () {
+ //
+ // editor.core.log('ui.bindEvents fired', 'info');
+ //
+ // // 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);
+ //
+ // /** All keydowns on Redactor zone */
+ // editor.listeners.add(editor.nodes.redactor, 'keydown', editor.callback.redactorKeyDown, false);
+ //
+ // /** All keydowns on Document */
+ // editor.listeners.add(document, 'keyup', editor.callback.globalKeyup, false );
+ //
+ // /**
+ // * 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);
+ //
+ // /**
+ // * Clicks to SETTINGS button in toolbar
+ // */
+ // editor.listeners.add(editor.nodes.showSettingsButton, 'click', editor.callback.showSettingsButtonClicked, false );
+ //
+ // /** Bind click listeners on toolbar buttons */
+ // for (var button in editor.nodes.toolbarButtons) {
+ //
+ // editor.listeners.add(editor.nodes.toolbarButtons[button], 'click', editor.callback.toolbarButtonClicked, false);
+ //
+ // }
+ //
+ // };
+ //
+ // ui.addBlockHandlers = function (block) {
+ //
+ // if (!block) return;
+ //
+ // /**
+ // * 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);
+ //
+ // }
+ //
+ // });
+ //
+ // };
+ //
+ // /**
+ // * Adds first initial block on empty redactor
+ // */
+ // ui.addInitialBlock = function () {
+ //
+ // 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);
+ //
+ // };
+ //
+ // ui.setInlineToolbarButtonBehaviour = function (button, type) {
+ //
+ // editor.listeners.add(button, 'mousedown', function (event) {
+ //
+ // editor.toolbar.inline.toolClicked(event, type);
+ //
+ // }, false);
+ //
+ // };
+ //
+ // return ui;
+ //
+ // })({});
+
/***/ })
/******/ ]);
//# sourceMappingURL=codex-editor.js.map
\ No newline at end of file
diff --git a/codex-editor.js.map b/codex-editor.js.map
index 7b599ad5..09538645 100644
--- a/codex-editor.js.map
+++ b/codex-editor.js.map
@@ -1 +1 @@
-{"version":3,"sources":["webpack:///webpack/bootstrap 5fc2d6f1c1d34aecf6ab","webpack:///./src/codex.js"],"names":["modules","require","module","exports","config","moduleInstances","Promise","resolve","then","configuration","init","start","console","log","catch","error","constructModules","configureModules","forEach","Module","name","state","getModulesDiff","moduleName","prepareDecorator","prepare","holderId","placeholder","sanitizer","p","b","a","hideToolbar"],"mappings":";;AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,uBAAe;AACf;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;;;;;;;;;;;;ACtCA;;;;;;;;;AASA;;;;AAIA;;;;;;AAMA;;;AAGA,KAAMA,UAAU,CACZ,mBAAAC,CAAQ,6IAAR,CADY,EAEZ,mBAAAA,CAAQ,8IAAR,CAFY,EAGZ,mBAAAA,CAAQ,4IAAR,CAHY,EAIZ,mBAAAA,CAAQ,+IAAR,CAJY,CAAhB;;AAOA;;;;;;;;;;AAUAC,QAAOC,OAAP;AAAA;AAAA;;;AAEI;AAFJ,6BAGyB;;AAEjB,oBAAO,SAAP;AAEH;;AAED;;;;;AATJ;;AAaI,0BAAYC,MAAZ,EAAoB;;AAEhB;;AAEA;;;;AAJgB;;AAAA;;AAOhB,cAAKA,MAAL,GAAc,EAAd;;AAEA;;;AAGA,cAAKC,eAAL,GAAuB,EAAvB;;AAEAC,iBAAQC,OAAR,GACKC,IADL,CACU,YAAM;;AAER,mBAAKC,aAAL,GAAqBL,MAArB;AAEH,UALL,EAMKI,IANL,CAMU;AAAA,oBAAM,MAAKE,IAAL,EAAN;AAAA,UANV,EAOKF,IAPL,CAOU;AAAA,oBAAM,MAAKG,KAAL,EAAN;AAAA,UAPV,EAQKH,IARL,CAQU,YAAM;;AAERI,qBAAQC,GAAR,CAAY,uBAAZ;AAEH,UAZL,EAaKC,KAbL,CAaW,iBAAS;;AAEZF,qBAAQC,GAAR,CAAY,4CAAZ,EAA0DE,KAA1D;AAEH,UAjBL;AAmBH;;AAED;;;;;;AAhDJ;AAAA;;;AA4EI;;;;;AA5EJ,gCAiFW;;AAEH;;;AAGA,kBAAKC,gBAAL;;AAEA;;;AAGA,kBAAKC,gBAAL;AAEH;;AAED;;;;AA/FJ;AAAA;AAAA,4CAkGuB;AAAA;;AAEfjB,qBAAQkB,OAAR,CAAiB,kBAAU;;AAEvB,wBAAKb,eAAL,CAAqBc,OAAOC,IAA5B,IAAoC,IAAID,MAAJ,CAAW;AAC3Cf,6BAAS,OAAKK;AAD6B,kBAAX,CAApC;AAIH,cAND;AAQH;;AAED;;;;;;AA9GJ;AAAA;AAAA,4CAmHuB;;AAEf,kBAAI,IAAIW,IAAR,IAAgB,KAAKf,eAArB,EAAsC;;AAElC;;;AAGA,sBAAKA,eAAL,CAAqBe,IAArB,EAA2BC,KAA3B,GAAmC,KAAKC,cAAL,CAAqBF,IAArB,CAAnC;AAEH;AAEJ;;AAED;;;;AAhIJ;AAAA;AAAA,wCAmIoBA,IAnIpB,EAmI2B;;AAEnB,iBAAIpB,UAAU,EAAd;;AAEA,kBAAI,IAAIuB,UAAR,IAAsB,KAAKlB,eAA3B,EAA4C;;AAExC;;;AAGA,qBAAIkB,cAAcH,IAAlB,EAAwB;;AAEpB;AAEH;AACDpB,yBAAQuB,UAAR,IAAsB,KAAKlB,eAAL,CAAqBkB,UAArB,CAAtB;AAEH;;AAED,oBAAOvB,OAAP;AAEH;;AAED;;;;;;AAzJJ;AAAA;AAAA,iCA8JY;;AAEJ,iBAAIwB,mBAAmB,SAAnBA,gBAAmB;AAAA,wBAAUtB,OAAOuB,OAAP,EAAV;AAAA,cAAvB;;AAEA,oBAAOnB,QAAQC,OAAR,GACFC,IADE,CACGgB,iBAAiB,KAAKnB,eAAL,CAAqB,MAArB,CAAjB,CADH,EAEFG,IAFE,CAEGgB,iBAAiB,KAAKnB,eAAL,CAAqB,IAArB,CAAjB,CAFH,EAGFG,IAHE,CAGGgB,iBAAiB,KAAKnB,eAAL,CAAqB,OAArB,CAAjB,CAHH,EAIFS,KAJE,CAII,UAAUC,KAAV,EAAiB;;AAEpBH,yBAAQC,GAAR,CAAY,eAAZ,EAA6BE,KAA7B;AAEH,cARE,CAAP;AASH;AA3KL;AAAA;AAAA,6BAoDmC;AAAA,iBAAbX,MAAa,uEAAJ,EAAI;;;AAE3B,kBAAKA,MAAL,CAAYsB,QAAZ,GAAuBtB,OAAOsB,QAA9B;AACA,kBAAKtB,MAAL,CAAYuB,WAAZ,GAA0BvB,OAAOuB,WAAP,IAAsB,qBAAhD;AACA,kBAAKvB,MAAL,CAAYwB,SAAZ,GAAwBxB,OAAOwB,SAAP,IAAoB;AACxCC,oBAAG,IADqC;AAExCC,oBAAG,IAFqC;AAGxCC,oBAAG;AAHqC,cAA5C;;AAMA,kBAAK3B,MAAL,CAAY4B,WAAZ,GAA0B5B,OAAO4B,WAAP,GAAqB5B,OAAO4B,WAA5B,GAA0C,KAApE;AAEH;;AAED;;;;AAlEJ;AAAA,6BAsEwB;;AAEhB,oBAAO,KAAK5B,MAAZ;AAEH;AA1EL;;AAAA;AAAA;;AA+KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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 5fc2d6f1c1d34aecf6ab","/**\n * Codex Editor\n *\n *\n *\n *\n * @author CodeX Team\n */\n\n/**\n * @typedef {CodexEditor} CodexEditor - editor class\n */\n\n/**\n * @typedef {Object} EditorConfig\n * @property {String} holderId - Element to append Editor\n * ...\n */\n\n/**\n * All Editor components\n */\nconst modules = [\n require('./src/modules/dom'),\n require('./src/modules/core'),\n require('./src/modules/ui'),\n require('./src/modules/tools')\n];\n\n/**\n * @class\n *\n * @classdesc CodeX Editor base class\n *\n * @property this.config - all settings\n * @property this.moduleInstances - constructed editor components\n *\n * @type {CodexEditor}\n */\nmodule.exports = class CodexEditor {\n\n /** Editor version */\n static get version() {\n\n return VERSION;\n\n }\n\n /**\n * @param {EditorConfig} config - user configuration\n *\n */\n constructor(config) {\n\n 'use strict';\n\n /**\n * Configuration object\n */\n this.config = {};\n\n /**\n * Editor Components\n */\n this.moduleInstances = {};\n\n Promise.resolve()\n .then(() => {\n\n this.configuration = config;\n\n })\n .then(() => this.init())\n .then(() => this.start())\n .then(() => {\n\n console.log('CodeX Editor is ready');\n\n })\n .catch(error => {\n\n console.log('CodeX Editor does not ready beecause of %o', error);\n\n });\n\n }\n\n /**\n * Setting for configuration\n * @param {object} config\n */\n set configuration(config = {}) {\n\n this.config.holderId = config.holderId;\n this.config.placeholder = config.placeholder || 'write your story...';\n this.config.sanitizer = config.sanitizer || {\n p: true,\n b: true,\n a: true\n };\n\n this.config.hideToolbar = config.hideToolbar ? config.hideToolbar : false;\n\n }\n\n /**\n * Returns private property\n * @returns {{}|*}\n */\n get configuration() {\n\n return this.config;\n\n }\n\n /**\n * Initializes modules:\n * - make and save instances\n * - configure\n */\n init() {\n\n /**\n * Make modules instances and save it to the @property this.moduleInstances\n */\n this.constructModules();\n\n /**\n * Modules configuration\n */\n this.configureModules();\n\n }\n\n /**\n * Make modules instances and save it to the @property this.moduleInstances\n */\n constructModules() {\n\n modules.forEach( Module => {\n\n this.moduleInstances[Module.name] = new Module({\n config : this.configuration\n });\n\n });\n\n }\n\n /**\n * Modules instances configuration:\n * - pass other modules to the 'state' property\n * - ...\n */\n configureModules() {\n\n for(let name in this.moduleInstances) {\n\n /**\n * Module does not need self-instance\n */\n this.moduleInstances[name].state = this.getModulesDiff( name );\n\n }\n\n }\n\n /**\n * Return modules without passed name\n */\n getModulesDiff( name ) {\n\n let modules = {};\n\n for(let moduleName in this.moduleInstances) {\n\n /**\n * Skip module with passed name\n */\n if (moduleName == name) {\n\n continue;\n\n }\n modules[moduleName] = this.moduleInstances[moduleName];\n\n }\n\n return modules;\n\n }\n\n /**\n * Start Editor!\n *\n * @return {Promise}\n */\n start() {\n\n let prepareDecorator = module => module.prepare();\n\n return Promise.resolve()\n .then(prepareDecorator(this.moduleInstances['core']))\n .then(prepareDecorator(this.moduleInstances['ui']))\n .then(prepareDecorator(this.moduleInstances['tools']))\n .catch(function (error) {\n\n console.log('Error occured', error);\n\n });\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// 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// ./src/codex.js"],"sourceRoot":""}
\ No newline at end of file
+{"version":3,"sources":["webpack:///webpack/bootstrap 229ff37c08e532c02f84","webpack:///./src/codex.js","webpack:///./src/components/modules ^\\.\\/.*$","webpack:///./src/components/modules/_anchors.js","webpack:///./src/components/modules/_callbacks.js","webpack:///./src/components/modules/_caret.js","webpack:///./src/components/modules/_content.js","webpack:///./src/components/modules/_destroyer.js","webpack:///./src/components/modules/_listeners.js","webpack:///./src/components/modules/_notifications.js","webpack:///./src/components/modules/_parser.js","webpack:///./src/components/modules/_paste.js","webpack:///./src/components/modules/_renderer.js","webpack:///./src/components/modules/_sanitizer.js","webpack:///./~/html-janitor/src/html-janitor.js","webpack:///./src/components/modules/_saver.js","webpack:///./src/components/modules/_transport.js","webpack:///./src/components/modules/eventDispatcher.js","webpack:///./src/components/modules/toolbar/inline.js","webpack:///./src/components/modules/toolbar/settings.js","webpack:///./src/components/modules/toolbar/toolbar.js","webpack:///./src/components/modules/toolbar/toolbox.js","webpack:///./src/components/modules/tools.js","webpack:///./src/components/modules/ui.js"],"names":["modules","editorModules","map","module","exports","config","moduleInstances","Promise","resolve","then","configuration","init","start","console","log","catch","error","constructModules","configureModules","forEach","Module","name","e","state","getModulesDiff","moduleName","prepareDecorator","prepare","holderId","placeholder","sanitizer","p","b","a","hideToolbar","anchors","editor","codex","input","currentNode","settingsOpened","currentBlock","value","dataset","anchor","anchorChanged","newAnchor","target","rusToTranslit","trim","classList","add","ui","className","BLOCK_WITH_ANCHOR","remove","keyDownOnAnchorInput","keyCode","core","keys","ENTER","preventDefault","stopPropagation","blur","toolbar","settings","close","keyUpOnAnchorInput","LEFT","DOWN","string","ru","en","i","length","split","join","toLowerCase","replace","callbacks","globalKeydown","event","enterKeyPressed_","redactorKeyDown","TAB","tabKeyPressedOnRedactorsZone_","enterKeyPressedOnRedactorsZone_","ESC","escapeKeyPressedOnRedactorsZone_","defaultKeyPressedOnRedactorsZone_","globalKeyup","UP","RIGHT","arrowKeyPressed_","isBlockEmpty","content","opened","open","toolbox","leaf","editorAreaHightlighted","caret","inputIndex","enterPressedOnBlock_","NEW_BLOCK_TYPE","initialBlockPlugin","insertBlock","type","block","tools","render","move","contentEditable","saveCurrentInputIndex","currentInputIndex","getCurrentInputIndex","workingNode","tool","isEnterPressedOnToolbar","current","inputs","enableLineBreaks","toolClicked","stopImmediatePropagation","shiftKey","currentSelection","window","getSelection","currentSelectedNode","anchorNode","caretAtTheEndOfText","position","atTheEnd","isTextNodeHasParentBetweenContenteditable","callback","enterPressedOnBlock","parentNode","nodeType","nodeTypes","TEXT","splitBlock","textContent","showPlusButton","islastNode","isLastNode","saveInputs","workingNodeChanged","inline","actionsOpened","clearMark","redactorClicked","detectWhenClickedOnFirstLevelBlockArea_","selectedText","getSelectionText","firstLevelBlock","indexOfLastInput","getFirstLevelBlock","setToBlock","setToNextBlock","inputIsEmpty","currentNodeType","isInitialType","hidePlusButton","markBlock","selection","flag","rangeCount","isDomNode","document","body","toolbarButtonClicked","button","plusButtonClicked","nodes","contains","blockKeydown","blockRightOrDownArrowPressed_","BACKSPACE","backspacePressed_","blockLeftOrUpArrowPressed_","focusedNode","focusedNodeHolder","editableElementIndex","caretInLastChild","lastChild","deepestTextnode","childNodes","getDeepestTextNodeFromPosition","anchorOffset","caretInFirstChild","caretAtTheBeginning","firstChild","setToPreviousBlock","range","selectionLength","firstLevelBlocksCount","isNativeInput","getRange","endOffset","startOffset","atStart","mergeBlocks","redactor","addInitialBlock","setTimeout","showSettingsButtonClicked","currentToolType","toggle","hideRemoveActions","offset","focusedNodeIndex","set","el","index","childs","nodeToSet","focus","createRange","setStart","setEnd","removeAllRanges","addRange","nextInput","emptyTextElement","createTextNode","appendChild","targetInput","previousInput","lastChildNode","lengthOfLastChildNode","pluginsRender","isFirstNode","isOffsetZero","insertNode","node","lastNode","DOCUMENT_FRAGMENT","getRangeAt","deleteContents","setStartAfter","collapse","sync","html","innerHTML","BLOCK_HIGHLIGHTED","BLOCK_CLASSNAME","targetNode","replaceBlock","targetBlock","newBlock","replaceChild","addBlockHandlers","blockData","needPlaceCaret","workingBlock","newBlockContent","blockType","isStretched","stretched","composeNewBlock_","insertAfter","editableElement","querySelector","emptyText","switchBlock","blockToReplace","newBlockComposed","blockChilds","text","removeChild","lookingFromStart","TAG","draw","blockContent","BLOCK_CONTENT","BLOCK_STRETCHED","anchorNodeText","caretOffset","textBeforeCaret","textNodeBeforeCaret","textAfterCaret","textNodeAfterCaret","substring","previousChilds","nextChilds","reachedCurrent","push","child","previousChildsLength","nextChildsLength","newNode","createElement","targetInputIndex","currentInputContent","allChecked","allSiblingsEmpty_","sibling","nextSibling","wrapTextWithParagraphs","htmlData","plainData","wrapPlainTextWithParagraphs","wrapper","newWrapper","paragraph","firstLevelBlocks","blockTyped","indexOf","tagName","cloneNode","plainText","getEditableParent","clear","all","blocks","items","load","articleData","currentContent","Object","assign","concat","renderer","makeBlocksFromData","destroyer","removeNodes","notifications","destroyPlugins","destroy","destroyScripts","scripts","getElementsByTagName","id","scriptPrefix","listeners","removeAll","plugins","allListeners","search","byElement","element","context","listenersOnElement","listener","byType","eventType","listenersWithType","byHandler","handler","listenersWithHandler","one","result","isCapture","addEventListener","data","alreadyAddedListener","removeEventListener","existingListeners","splice","get","queue","addToQueue","createHolder","holder","errorThrown","errorMsg","notification","message","constructorSettings","cancel","confirm","inputField","confirmHandler","cancelHandler","create","time","okBtn","cancelBtn","okMsg","cancelMsg","send","parser","insertPastedContent","tag","isFirstLevelBlock","paste","patterns","renderOnPastePatterns","Array","isArray","pattern","pasted","clipBoardData","clipboardData","getData","analize","plugin","execArray","regex","exec","match","pasteToNewBlock_","blockPasteCallback","needsToHandlePasteEvent","paragraphs","cleanData","wrappedData","clean","emulateUserAgentBehaviour","insertPastedParagraphs","editableParent","childElementCount","createDocumentFragment","isEmpty","appendBlocks","nodeSequence","appendNodeAtIndex","getNodeAsync","createBlockFromData","blocksList","toolData","pluginName","Error","available","unavailableBlock","loadingMessage","inputPosition","janitor","require","Config","CUSTOM","BASIC","tags","href","rel","init_","userCustomConfig","dirtyString","customConfig","janitorInstance","saver","save","jsonOutput","saveBlocks","getBlockData","makeOutput","saveBlockData","validateBlockData","pluginsContent","validate","savedData","filter","Date","version","transport","currentRequest","arguments","fileSelected","clearInput","files","formData","FormData","multiple","append","ajax","url","beforeSend","success","progress","selectAndUpload","args","setAttribute","accept","click","abort","subscribers","eventName","reduce","previousData","currentHandler","newData","buttonsOpened","wrappersOffset","storedSelection","show","showInlineToolbar","inlineToolbar","showButtons","getWrappersOffset","coords","getSelectionCoords","defaultOffset","newCoordinateX","newCoordinateY","offsetHeight","x","left","y","scrollY","top","style","transform","Math","floor","closeButtons","closeAction","createLinkAction","defaultToolAction","buttons","hightlight","getOffset","_x","_y","isNaN","offsetLeft","offsetTop","clientLeft","clientTop","offsetParent","sel","boundingLeft","boundingTop","cloneRange","getClientRects","rect","toString","showActions","action","actions","inlineToolbarAnchorInputKeydown_","editable","restoreSelection","setAnchor","clearRange","isActive","isLinkActive","saveSelection","inputForLink","dataType","execCommand","containerEl","preSelectionRange","selectNodeContents","startContainer","end","savedSel","charIndex","nodeStack","foundStart","stop","nextCharIndex","pop","queryCommandState","setButtonHighlighted","removeButtonsHighLight","icon","setting","toolType","makeSettings","settingsBlock","pluginSettings","blockSettings","makeRemoveBlockButton","removeBlockWrapper","settingButton","actionWrapper","confirmAction","cancelAction","removeButtonClicked","confirmRemovingRequest","cancelRemovingRequest","showRemoveActions","defaultToolbarHeight","showSettingsButton","toolbarButtons","plusButton","newYCoordinate","openedOnBlock","currentTool","barButtons","nextToolIndex","toolToSelect","visibleTool","displayInToolbox","UNREPLACEBLE_TOOLS","appendCallback","call","Editor","iconClassName","availabPlugins","toolInstances","toolConfig","defaultConfig","hasOwnProperty","waitNextToolPreparation","toolBindedPreparationFunction","reject","resolvePreparation","rejectPreparation","toolPreparationList","toolName","toolsConfig","bind","previousToolPrepared","currentToolReadyToPreparation","iteration","SETTINGS_ITEM","CSS_","editorWrapper","editorZone","dom","make","makeToolBar_","addTools_","makeInlineToolbar_","addInlineToolbarTools_","makeNotificationHolder_","bindEvents_"],"mappings":"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H;;AAED;;;;AAhEJ;AAAA,6BAoEwB;;AAEhB,oBAAO,KAAK7B,MAAZ;AAEH;AAxEL;;AAAA;AAAA;;AAqLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;;;;;ACzUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kCAAiC,uDAAuD;AACxF;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;ACrDA;;;;;;;AAOAF,QAAOC,OAAP,GAAiB,UAAU+B,OAAV,EAAmB;;AAEhC,SAAIC,SAASC,MAAMD,MAAnB;;AAEAD,aAAQG,KAAR,GAAsB,IAAtB;AACAH,aAAQI,WAAR,GAAsB,IAAtB;;AAEAJ,aAAQK,cAAR,GAAyB,UAAUC,YAAV,EAAwB;;AAE7CN,iBAAQI,WAAR,GAAsBE,YAAtB;AACAN,iBAAQG,KAAR,CAAcI,KAAd,GAAsBP,QAAQI,WAAR,CAAoBI,OAAp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CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;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;;;;;;;;;;;;ACpVI;;;;;AAKJ,KAAIzhB,YAAY;;AAEZ;;;AAGAgM,sBAAkB,UALN;;AAOZ;;;AAGA6B,oBAAgB,mBAVJ;;AAYZ;;;AAGAC,sBAAkB,qBAfN;;AAiBZ;;;AAGA/B,wBAAoB,mBApBR;;AAsBZ;;;AAGA0W,oBAAgB;AAzBJ,EAAhB;;AA4BA,KAAIC,OAAO;AACPC,oBAAgB,cADT;AAEPC,iBAAgB;AAFT,EAAX;;AAMA;;;;;;;;;;;;;AAaA9lB,QAAOC,OAAP;AAAA;AAAA;;;AAEI;;;;AAFJ,6BAMsB;;AAEd,oBAAO,IAAP;AAEH;;AAED;;;;;;AAZJ;;AAiBI,iBAAaC,MAAb,EAAsB;AAAA;;AAElB,cAAKA,MAAL,GAAcA,MAAd;AACA,cAAKskB,MAAL,GAAc,IAAd;AAEH;;AAGD;;;;;;AAzBJ;AAAA;;;AAmCI;;;;;AAnCJ,mCAwCc;;AAEN9jB,qBAAQC,GAAR,CAAY,kBAAZ;;AAEA;;AAEA,oBAAO,IAAIP,OAAJ,CAAY,UAAUC,OAAV,EAAmB4kB,MAAnB,EAA2B;;AAE1C,qBAAItS,UAAW,KAAK9S,OAAL,CAAakmB,GAAb,CAAiBC,IAAjB,CAAsB,KAAtB,EAA6B,CAAEJ,KAAKC,aAAP,CAA7B,EAAqD,EAArD,CAAf;AAAA,qBACItZ,WAAW,KAAK1M,OAAL,CAAakmB,GAAb,CAAiBC,IAAjB,CAAsB,KAAtB,EAA6B,CAAEJ,KAAKE,UAAP,CAA7B,EAAkD,EAAlD,CADf;AAAA,qBAEIjiB,UAAWoiB,cAFf;;AAIAtT,yBAAQ7E,WAAR,CAAoBjK,OAApB;AACA8O,yBAAQ7E,WAAR,CAAoBvB,QAApB;;AAEA;AACAtK,wBAAOyI,KAAP,CAAaiI,OAAb,GAAwBA,OAAxB;AACA1Q,wBAAOyI,KAAP,CAAa6B,QAAb,GAAwBA,QAAxB;;AAEA;AACAtK,wBAAOyI,KAAP,CAAa8L,MAAb,CAAoB1I,WAApB,CAAgC6E,OAAhC;;AAEAtS;AAEH,cAlBM;;AAoBP;AApBO,cAqBNC,IArBM,CAqBD4lB,SArBC;;AAuBP;AAvBO,cAwBN5lB,IAxBM,CAwBD6lB,kBAxBC;;AA0BP;AA1BO,cA2BN7lB,IA3BM,CA2BD8lB,sBA3BC;;AA6BP;AA7BO,cA8BN9lB,IA9BM,CA8BD+lB,uBA9BC;;AAgCP;AAhCO,cAiCN/lB,IAjCM,CAiCDgmB,WAjCC,EAmCN1lB,KAnCM,CAmCC,YAAY;;AAEhBqB,wBAAOsB,IAAP,CAAY5C,GAAZ,CAAgB,6BAAhB;AAEH,cAvCM,CAAP;AAyCH;AAvFL;AAAA;AAAA,2BA6Bc6jB,MA7Bd,EA6BsB;;AAEd,kBAAKA,MAAL,GAAcA,MAAd;AAEH;AAjCL;;AAAA;AAAA;AA0FA;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 229ff37c08e532c02f84","/**\n * Codex Editor\n *\n *\n *\n *\n * @author CodeX Team\n */\n\n/**\n * @typedef {CodexEditor} CodexEditor - editor class\n */\n\n/**\n * @typedef {Object} EditorConfig\n * @property {String} holderId - Element to append Editor\n * ...\n */\n\n'use strict';\n\n/**\n * Require Editor modules places in components/modules dir\n */\nlet modules = editorModules.map( module => {\n\n return require('./components/modules/' + module );\n\n});\n\n/**\n * @class\n *\n * @classdesc CodeX Editor base class\n *\n * @property this.config - all settings\n * @property this.moduleInstances - constructed editor components\n *\n * @type {CodexEditor}\n */\nmodule.exports = class CodexEditor {\n\n /** Editor version */\n static get version() {\n\n return VERSION;\n\n }\n\n /**\n * @param {EditorConfig} config - user configuration\n *\n */\n constructor(config) {\n\n /**\n * Configuration object\n */\n this.config = {};\n\n /**\n * Editor Components\n */\n this.moduleInstances = {};\n\n Promise.resolve()\n .then(() => {\n\n this.configuration = config;\n\n })\n .then(() => this.init())\n .then(() => this.start())\n .then(() => {\n\n console.log('CodeX Editor is ready');\n\n })\n .catch(error => {\n\n console.log('CodeX Editor does not ready beecause of %o', error);\n\n });\n\n }\n\n /**\n * Setting for configuration\n * @param {object} config\n */\n set configuration(config = {}) {\n\n this.config.holderId = config.holderId;\n this.config.placeholder = config.placeholder || 'write your story...';\n this.config.sanitizer = config.sanitizer || {\n p: true,\n b: true,\n a: true\n };\n\n this.config.hideToolbar = config.hideToolbar ? config.hideToolbar : false;\n\n }\n\n /**\n * Returns private property\n * @returns {{}|*}\n */\n get configuration() {\n\n return this.config;\n\n }\n\n /**\n * Initializes modules:\n * - make and save instances\n * - configure\n */\n init() {\n\n /**\n * Make modules instances and save it to the @property this.moduleInstances\n */\n this.constructModules();\n\n /**\n * Modules configuration\n */\n this.configureModules();\n\n }\n\n /**\n * Make modules instances and save it to the @property this.moduleInstances\n */\n constructModules() {\n\n modules.forEach( Module => {\n\n try {\n\n this.moduleInstances[Module.name] = new Module({\n config : this.configuration\n });\n\n } catch ( e ) {\n\n console.log('Module %o skipped because %o', Module, e);\n\n }\n\n });\n\n }\n\n /**\n * Modules instances configuration:\n * - pass other modules to the 'state' property\n * - ...\n */\n configureModules() {\n\n for(let name in this.moduleInstances) {\n\n /**\n * Module does not need self-instance\n */\n this.moduleInstances[name].state = this.getModulesDiff( name );\n\n }\n\n }\n\n /**\n * Return modules without passed name\n */\n getModulesDiff( name ) {\n\n let modules = {};\n\n for(let moduleName in this.moduleInstances) {\n\n /**\n * Skip module with passed name\n */\n if (moduleName == name) {\n\n continue;\n\n }\n modules[moduleName] = this.moduleInstances[moduleName];\n\n }\n\n return modules;\n\n }\n\n /**\n * Start Editor!\n *\n * @return {Promise}\n */\n start() {\n\n let prepareDecorator = module => module.prepare();\n\n return Promise.resolve()\n .then(prepareDecorator(this.moduleInstances['ui']))\n .then(prepareDecorator(this.moduleInstances['tools']))\n .catch(function (error) {\n\n console.log('Error occured', error);\n\n });\n\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// 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// ./src/codex.js","var map = {\n\t\"./_anchors\": 2,\n\t\"./_anchors.js\": 2,\n\t\"./_callbacks\": 3,\n\t\"./_callbacks.js\": 3,\n\t\"./_caret\": 4,\n\t\"./_caret.js\": 4,\n\t\"./_content\": 5,\n\t\"./_content.js\": 5,\n\t\"./_destroyer\": 6,\n\t\"./_destroyer.js\": 6,\n\t\"./_listeners\": 7,\n\t\"./_listeners.js\": 7,\n\t\"./_notifications\": 8,\n\t\"./_notifications.js\": 8,\n\t\"./_parser\": 9,\n\t\"./_parser.js\": 9,\n\t\"./_paste\": 10,\n\t\"./_paste.js\": 10,\n\t\"./_renderer\": 11,\n\t\"./_renderer.js\": 11,\n\t\"./_sanitizer\": 12,\n\t\"./_sanitizer.js\": 12,\n\t\"./_saver\": 14,\n\t\"./_saver.js\": 14,\n\t\"./_transport\": 15,\n\t\"./_transport.js\": 15,\n\t\"./eventDispatcher\": 16,\n\t\"./eventDispatcher.js\": 16,\n\t\"./toolbar/inline\": 17,\n\t\"./toolbar/inline.js\": 17,\n\t\"./toolbar/settings\": 18,\n\t\"./toolbar/settings.js\": 18,\n\t\"./toolbar/toolbar\": 19,\n\t\"./toolbar/toolbar.js\": 19,\n\t\"./toolbar/toolbox\": 20,\n\t\"./toolbar/toolbox.js\": 20,\n\t\"./tools\": 21,\n\t\"./tools.js\": 21,\n\t\"./ui\": 22,\n\t\"./ui.js\": 22\n};\nfunction webpackContext(req) {\n\treturn __webpack_require__(webpackContextResolve(req));\n};\nfunction webpackContextResolve(req) {\n\treturn map[req] || (function() { throw new Error(\"Cannot find module '\" + req + \"'.\") }());\n};\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = 1;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/components/modules ^\\.\\/.*$\n// module id = 1\n// module chunks = 0","/**\n * Codex Editor Anchors module\n *\n * @author Codex Team\n * @version 1.0\n */\n\nmodule.exports = function (anchors) {\n\n let editor = codex.editor;\n\n anchors.input = null;\n anchors.currentNode = null;\n\n anchors.settingsOpened = function (currentBlock) {\n\n anchors.currentNode = currentBlock;\n anchors.input.value = anchors.currentNode.dataset.anchor || '';\n\n };\n\n anchors.anchorChanged = function (e) {\n\n var newAnchor = e.target.value = anchors.rusToTranslit(e.target.value);\n\n anchors.currentNode.dataset.anchor = newAnchor;\n\n if (newAnchor.trim() !== '') {\n\n anchors.currentNode.classList.add(editor.ui.className.BLOCK_WITH_ANCHOR);\n\n } else {\n\n anchors.currentNode.classList.remove(editor.ui.className.BLOCK_WITH_ANCHOR);\n\n }\n\n };\n\n anchors.keyDownOnAnchorInput = function (e) {\n\n if (e.keyCode == editor.core.keys.ENTER) {\n\n e.preventDefault();\n e.stopPropagation();\n\n e.target.blur();\n editor.toolbar.settings.close();\n\n }\n\n };\n\n anchors.keyUpOnAnchorInput = function (e) {\n\n if (e.keyCode >= editor.core.keys.LEFT && e.keyCode <= editor.core.keys.DOWN) {\n\n e.stopPropagation();\n\n }\n\n };\n\n anchors.rusToTranslit = function (string) {\n\n var ru = [\n 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й',\n 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф',\n 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ь', 'Ы', 'Ь', 'Э', 'Ю', 'Я'\n ],\n en = [\n 'A', 'B', 'V', 'G', 'D', 'E', 'E', 'Zh', 'Z', 'I', 'Y',\n 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F',\n 'H', 'C', 'Ch', 'Sh', 'Sch', '', 'Y', '', 'E', 'Yu', 'Ya'\n ];\n\n for (var i = 0; i < ru.length; i++) {\n\n string = string.split(ru[i]).join(en[i]);\n string = string.split(ru[i].toLowerCase()).join(en[i].toLowerCase());\n\n }\n\n string = string.replace(/[^0-9a-zA-Z_]+/g, '-');\n\n return string;\n\n };\n\n return anchors;\n\n}({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_anchors.js","/**\n * @module Codex Editor Callbacks module\n * @description Module works with editor added Elements\n *\n * @author Codex Team\n * @version 1.4.0\n */\n\nmodule.exports = (function (callbacks) {\n\n let editor = codex.editor;\n\n /**\n * used by UI module\n * @description Routes all keydowns on document\n * @param {Object} event\n */\n callbacks.globalKeydown = function (event) {\n\n switch (event.keyCode) {\n case editor.core.keys.ENTER : enterKeyPressed_(event); break;\n }\n\n };\n\n /**\n * used by UI module\n * @description Routes all keydowns on redactors area\n * @param {Object} event\n */\n callbacks.redactorKeyDown = function (event) {\n\n switch (event.keyCode) {\n case editor.core.keys.TAB : tabKeyPressedOnRedactorsZone_(event); break;\n case editor.core.keys.ENTER : enterKeyPressedOnRedactorsZone_(event); break;\n case editor.core.keys.ESC : escapeKeyPressedOnRedactorsZone_(event); break;\n default : defaultKeyPressedOnRedactorsZone_(event); break;\n }\n\n };\n\n /**\n * used by UI module\n * @description Routes all keyup events\n * @param {Object} event\n */\n callbacks.globalKeyup = function (event) {\n\n switch (event.keyCode) {\n case editor.core.keys.UP :\n case editor.core.keys.LEFT :\n case editor.core.keys.RIGHT :\n case editor.core.keys.DOWN : arrowKeyPressed_(event); break;\n }\n\n };\n\n /**\n * @param {Object} event\n * @private\n *\n * Handles behaviour when tab pressed\n * @description if Content is empty show toolbox (if it is closed) or leaf tools\n * uses Toolbars toolbox module to handle the situation\n */\n var tabKeyPressedOnRedactorsZone_ = function (event) {\n\n /**\n * Wait for solution. Would like to know the behaviour\n * @todo Add spaces\n */\n event.preventDefault();\n\n\n if (!editor.core.isBlockEmpty(editor.content.currentNode)) {\n\n return;\n\n }\n\n if ( !editor.toolbar.opened ) {\n\n editor.toolbar.open();\n\n }\n\n if (editor.toolbar.opened && !editor.toolbar.toolbox.opened) {\n\n editor.toolbar.toolbox.open();\n\n } else {\n\n editor.toolbar.toolbox.leaf();\n\n }\n\n };\n\n /**\n * Handles global EnterKey Press\n * @see enterPressedOnBlock_\n * @param {Object} event\n */\n var enterKeyPressed_ = function () {\n\n if (editor.content.editorAreaHightlighted) {\n\n /**\n * it means that we lose input index, saved index before is not correct\n * therefore we need to set caret when we insert new block\n */\n editor.caret.inputIndex = -1;\n\n enterPressedOnBlock_();\n\n }\n\n };\n\n /**\n * Callback for enter key pressing in first-level block area\n *\n * @param {Event} event\n * @private\n *\n * @description Inserts new block with initial type from settings\n */\n var enterPressedOnBlock_ = function () {\n\n var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;\n\n editor.content.insertBlock({\n type : NEW_BLOCK_TYPE,\n block : editor.tools[NEW_BLOCK_TYPE].render()\n }, true );\n\n editor.toolbar.move();\n editor.toolbar.open();\n\n };\n\n\n /**\n * ENTER key handler\n *\n * @param {Object} event\n * @private\n *\n * @description Makes new block with initial type from settings\n */\n var enterKeyPressedOnRedactorsZone_ = function (event) {\n\n if (event.target.contentEditable == 'true') {\n\n /** Update input index */\n editor.caret.saveCurrentInputIndex();\n\n }\n\n var currentInputIndex = editor.caret.getCurrentInputIndex() || 0,\n workingNode = editor.content.currentNode,\n tool = workingNode.dataset.tool,\n isEnterPressedOnToolbar = editor.toolbar.opened &&\n editor.toolbar.current &&\n event.target == editor.state.inputs[currentInputIndex];\n\n /** The list of tools which needs the default browser behaviour */\n var enableLineBreaks = editor.tools[tool].enableLineBreaks;\n\n /** This type of block creates when enter is pressed */\n var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;\n\n /**\n * When toolbar is opened, select tool instead of making new paragraph\n */\n if ( isEnterPressedOnToolbar ) {\n\n event.preventDefault();\n\n editor.toolbar.toolbox.toolClicked(event);\n\n editor.toolbar.close();\n\n /**\n * Stop other listeners callback executions\n */\n event.stopPropagation();\n event.stopImmediatePropagation();\n\n return;\n\n }\n\n /**\n * Allow paragraph lineBreaks with shift enter\n * Or if shiftkey pressed and enter and enabledLineBreaks, the let new block creation\n */\n if ( event.shiftKey || enableLineBreaks ) {\n\n event.stopPropagation();\n event.stopImmediatePropagation();\n return;\n\n }\n\n var currentSelection = window.getSelection(),\n currentSelectedNode = currentSelection.anchorNode,\n caretAtTheEndOfText = editor.caret.position.atTheEnd(),\n isTextNodeHasParentBetweenContenteditable = false;\n\n /**\n * Allow making new in same block by SHIFT+ENTER and forbids to prevent default browser behaviour\n */\n if ( event.shiftKey && !enableLineBreaks ) {\n\n editor.callback.enterPressedOnBlock(editor.content.currentBlock, event);\n event.preventDefault();\n return;\n\n }\n\n /**\n * Workaround situation when caret at the Text node that has some wrapper Elements\n * Split block cant handle this.\n * We need to save default behavior\n */\n isTextNodeHasParentBetweenContenteditable = currentSelectedNode && currentSelectedNode.parentNode.contentEditable != 'true';\n\n /**\n * Split blocks when input has several nodes and caret placed in textNode\n */\n if (\n currentSelectedNode.nodeType == editor.core.nodeTypes.TEXT &&\n !isTextNodeHasParentBetweenContenteditable &&\n !caretAtTheEndOfText\n ) {\n\n event.preventDefault();\n\n editor.core.log('Splitting Text node...');\n\n editor.content.splitBlock(currentInputIndex);\n\n /** Show plus button when next input after split is empty*/\n if (!editor.state.inputs[currentInputIndex + 1].textContent.trim()) {\n\n editor.toolbar.showPlusButton();\n\n }\n\n } else {\n\n var islastNode = editor.content.isLastNode(currentSelectedNode);\n\n if ( islastNode && caretAtTheEndOfText ) {\n\n event.preventDefault();\n event.stopPropagation();\n event.stopImmediatePropagation();\n\n editor.core.log('ENTER clicked in last textNode. Create new BLOCK');\n\n editor.content.insertBlock({\n type: NEW_BLOCK_TYPE,\n block: editor.tools[NEW_BLOCK_TYPE].render()\n }, true);\n\n editor.toolbar.move();\n editor.toolbar.open();\n\n /** Show plus button with empty block */\n editor.toolbar.showPlusButton();\n\n }\n\n }\n\n /** get all inputs after new appending block */\n editor.ui.saveInputs();\n\n };\n\n /**\n * Escape behaviour\n * @param event\n * @private\n *\n * @description Closes toolbox and toolbar. Prevents default behaviour\n */\n var escapeKeyPressedOnRedactorsZone_ = function (event) {\n\n /** Close all toolbar */\n editor.toolbar.close();\n\n /** Close toolbox */\n editor.toolbar.toolbox.close();\n\n event.preventDefault();\n\n };\n\n /**\n * @param {Event} event\n * @private\n *\n * closes and moves toolbar\n */\n var arrowKeyPressed_ = function (event) {\n\n editor.content.workingNodeChanged();\n\n /* Closing toolbar */\n editor.toolbar.close();\n editor.toolbar.move();\n\n };\n\n /**\n * @private\n * @param {Event} event\n *\n * @description Closes all opened bars from toolbar.\n * If block is mark, clears highlightning\n */\n var defaultKeyPressedOnRedactorsZone_ = function () {\n\n editor.toolbar.close();\n\n if (!editor.toolbar.inline.actionsOpened) {\n\n editor.toolbar.inline.close();\n editor.content.clearMark();\n\n }\n\n };\n\n /**\n * Handler when clicked on redactors area\n *\n * @protected\n * @param event\n *\n * @description Detects clicked area. If it is first-level block area, marks as detected and\n * on next enter press will be inserted new block\n * Otherwise, save carets position (input index) and put caret to the editable zone.\n *\n * @see detectWhenClickedOnFirstLevelBlockArea_\n *\n */\n callbacks.redactorClicked = function (event) {\n\n detectWhenClickedOnFirstLevelBlockArea_();\n\n editor.content.workingNodeChanged(event.target);\n editor.ui.saveInputs();\n\n var selectedText = editor.toolbar.inline.getSelectionText(),\n firstLevelBlock;\n\n /** If selection range took off, then we hide inline toolbar */\n if (selectedText.length === 0) {\n\n editor.toolbar.inline.close();\n\n }\n\n /** Update current input index in memory when caret focused into existed input */\n if (event.target.contentEditable == 'true') {\n\n editor.caret.saveCurrentInputIndex();\n\n }\n\n if (editor.content.currentNode === null) {\n\n /**\n * If inputs in redactor does not exits, then we put input index 0 not -1\n */\n var indexOfLastInput = editor.state.inputs.length > 0 ? editor.state.inputs.length - 1 : 0;\n\n /** If we have any inputs */\n if (editor.state.inputs.length) {\n\n /** getting firstlevel parent of input */\n firstLevelBlock = editor.content.getFirstLevelBlock(editor.state.inputs[indexOfLastInput]);\n\n }\n\n /** If input is empty, then we set caret to the last input */\n if (editor.state.inputs.length && editor.state.inputs[indexOfLastInput].textContent === '' && firstLevelBlock.dataset.tool == editor.settings.initialBlockPlugin) {\n\n editor.caret.setToBlock(indexOfLastInput);\n\n } else {\n\n /** Create new input when caret clicked in redactors area */\n var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;\n\n editor.content.insertBlock({\n type : NEW_BLOCK_TYPE,\n block : editor.tools[NEW_BLOCK_TYPE].render()\n });\n\n /** If there is no inputs except inserted */\n if (editor.state.inputs.length === 1) {\n\n editor.caret.setToBlock(indexOfLastInput);\n\n } else {\n\n /** Set caret to this appended input */\n editor.caret.setToNextBlock(indexOfLastInput);\n\n }\n\n }\n\n } else {\n\n /** Close all panels */\n editor.toolbar.settings.close();\n editor.toolbar.toolbox.close();\n\n }\n\n /**\n * Move toolbar and open\n */\n editor.toolbar.move();\n editor.toolbar.open();\n\n var inputIsEmpty = !editor.content.currentNode.textContent.trim(),\n currentNodeType = editor.content.currentNode.dataset.tool,\n isInitialType = currentNodeType == editor.settings.initialBlockPlugin;\n\n\n /** Hide plus buttons */\n editor.toolbar.hidePlusButton();\n\n if (!inputIsEmpty) {\n\n /** Mark current block */\n editor.content.markBlock();\n\n }\n\n if ( isInitialType && inputIsEmpty ) {\n\n /** Show plus button */\n editor.toolbar.showPlusButton();\n\n }\n\n\n };\n\n /**\n * This method allows to define, is caret in contenteditable element or not.\n *\n * @private\n *\n * @description Otherwise, if we get TEXT node from range container, that will means we have input index.\n * In this case we use default browsers behaviour (if plugin allows that) or overwritten action.\n * Therefore, to be sure that we've clicked first-level block area, we should have currentNode, which always\n * specifies to the first-level block. Other cases we just ignore.\n */\n var detectWhenClickedOnFirstLevelBlockArea_ = function () {\n\n var selection = window.getSelection(),\n anchorNode = selection.anchorNode,\n flag = false;\n\n if (selection.rangeCount === 0) {\n\n editor.content.editorAreaHightlighted = true;\n\n } else {\n\n if (!editor.core.isDomNode(anchorNode)) {\n\n anchorNode = anchorNode.parentNode;\n\n }\n\n /** Already founded, without loop */\n if (anchorNode.contentEditable == 'true') {\n\n flag = true;\n\n }\n\n while (anchorNode.contentEditable != 'true') {\n\n anchorNode = anchorNode.parentNode;\n\n if (anchorNode.contentEditable == 'true') {\n\n flag = true;\n\n }\n\n if (anchorNode == document.body) {\n\n break;\n\n }\n\n }\n\n /** If editable element founded, flag is \"TRUE\", Therefore we return \"FALSE\" */\n editor.content.editorAreaHightlighted = !flag;\n\n }\n\n };\n\n /**\n * Toolbar button click handler\n *\n * @param {Object} event - cursor to the button\n * @protected\n *\n * @description gets current tool and calls render method\n */\n callbacks.toolbarButtonClicked = function (event) {\n\n var button = this;\n\n editor.toolbar.current = button.dataset.type;\n\n editor.toolbar.toolbox.toolClicked(event);\n editor.toolbar.close();\n\n };\n\n /**\n * Show or Hide toolbox when plus button is clicked\n */\n callbacks.plusButtonClicked = function () {\n\n if (!editor.nodes.toolbox.classList.contains('opened')) {\n\n editor.toolbar.toolbox.open();\n\n } else {\n\n editor.toolbar.toolbox.close();\n\n }\n\n };\n\n /**\n * Block handlers for KeyDown events\n *\n * @protected\n * @param {Object} event\n *\n * Handles keydowns on block\n * @see blockRightOrDownArrowPressed_\n * @see backspacePressed_\n * @see blockLeftOrUpArrowPressed_\n */\n callbacks.blockKeydown = function (event) {\n\n let block = event.target; // event.target is input\n\n switch (event.keyCode) {\n\n case editor.core.keys.DOWN:\n case editor.core.keys.RIGHT:\n blockRightOrDownArrowPressed_(event);\n break;\n\n case editor.core.keys.BACKSPACE:\n backspacePressed_(block, event);\n break;\n\n case editor.core.keys.UP:\n case editor.core.keys.LEFT:\n blockLeftOrUpArrowPressed_(event);\n break;\n\n }\n\n };\n\n /**\n * RIGHT or DOWN keydowns on block\n *\n * @param {Object} event\n * @private\n *\n * @description watches the selection and gets closest editable element.\n * Uses method getDeepestTextNodeFromPosition to get the last node of next block\n * Sets caret if it is contenteditable\n */\n var blockRightOrDownArrowPressed_ = function (event) {\n\n var selection = window.getSelection(),\n inputs = editor.state.inputs,\n focusedNode = selection.anchorNode,\n focusedNodeHolder;\n\n /** Check for caret existance */\n if (!focusedNode) {\n\n return false;\n\n }\n\n /** Looking for closest (parent) contentEditable element of focused node */\n while (focusedNode.contentEditable != 'true') {\n\n focusedNodeHolder = focusedNode.parentNode;\n focusedNode = focusedNodeHolder;\n\n }\n\n /** Input index in DOM level */\n var editableElementIndex = 0;\n\n while (focusedNode != inputs[editableElementIndex]) {\n\n editableElementIndex ++;\n\n }\n\n /**\n * Founded contentEditable element doesn't have childs\n * Or maybe New created block\n */\n if (!focusedNode.textContent) {\n\n editor.caret.setToNextBlock(editableElementIndex);\n return;\n\n }\n\n /**\n * Do nothing when caret doesn not reaches the end of last child\n */\n var caretInLastChild = false,\n caretAtTheEndOfText = false;\n\n var lastChild,\n deepestTextnode;\n\n lastChild = focusedNode.childNodes[focusedNode.childNodes.length - 1 ];\n\n if (editor.core.isDomNode(lastChild)) {\n\n deepestTextnode = editor.content.getDeepestTextNodeFromPosition(lastChild, lastChild.childNodes.length);\n\n } else {\n\n deepestTextnode = lastChild;\n\n }\n\n caretInLastChild = selection.anchorNode == deepestTextnode;\n caretAtTheEndOfText = deepestTextnode.length == selection.anchorOffset;\n\n if ( !caretInLastChild || !caretAtTheEndOfText ) {\n\n editor.core.log('arrow [down|right] : caret does not reached the end');\n return false;\n\n }\n\n editor.caret.setToNextBlock(editableElementIndex);\n\n };\n\n /**\n * LEFT or UP keydowns on block\n *\n * @param {Object} event\n * @private\n *\n * watches the selection and gets closest editable element.\n * Uses method getDeepestTextNodeFromPosition to get the last node of previous block\n * Sets caret if it is contenteditable\n *\n */\n var blockLeftOrUpArrowPressed_ = function (event) {\n\n var selection = window.getSelection(),\n inputs = editor.state.inputs,\n focusedNode = selection.anchorNode,\n focusedNodeHolder;\n\n /** Check for caret existance */\n if (!focusedNode) {\n\n return false;\n\n }\n\n /**\n * LEFT or UP not at the beginning\n */\n if ( selection.anchorOffset !== 0) {\n\n return false;\n\n }\n\n /** Looking for parent contentEditable block */\n while (focusedNode.contentEditable != 'true') {\n\n focusedNodeHolder = focusedNode.parentNode;\n focusedNode = focusedNodeHolder;\n\n }\n\n /** Input index in DOM level */\n var editableElementIndex = 0;\n\n while (focusedNode != inputs[editableElementIndex]) {\n\n editableElementIndex ++;\n\n }\n\n /**\n * Do nothing if caret is not at the beginning of first child\n */\n var caretInFirstChild = false,\n caretAtTheBeginning = false;\n\n var firstChild,\n deepestTextnode;\n\n /**\n * Founded contentEditable element doesn't have childs\n * Or maybe New created block\n */\n if (!focusedNode.textContent) {\n\n editor.caret.setToPreviousBlock(editableElementIndex);\n return;\n\n }\n\n firstChild = focusedNode.childNodes[0];\n\n if (editor.core.isDomNode(firstChild)) {\n\n deepestTextnode = editor.content.getDeepestTextNodeFromPosition(firstChild, 0);\n\n } else {\n\n deepestTextnode = firstChild;\n\n }\n\n caretInFirstChild = selection.anchorNode == deepestTextnode;\n caretAtTheBeginning = selection.anchorOffset === 0;\n\n if ( caretInFirstChild && caretAtTheBeginning ) {\n\n editor.caret.setToPreviousBlock(editableElementIndex);\n\n }\n\n };\n\n /**\n * Handles backspace keydown\n *\n * @param {Element} block\n * @param {Object} event\n * @private\n *\n * @description if block is empty, delete the block and set caret to the previous block\n * If block is not empty, try to merge two blocks - current and previous\n * But it we try'n to remove first block, then we should set caret to the next block, not previous.\n * If we removed the last block, create new one\n */\n var backspacePressed_ = function (block, event) {\n\n var currentInputIndex = editor.caret.getCurrentInputIndex(),\n range,\n selectionLength,\n firstLevelBlocksCount;\n\n if (editor.core.isNativeInput(event.target)) {\n\n /** If input value is empty - remove block */\n if (event.target.value.trim() == '') {\n\n block.remove();\n\n } else {\n\n return;\n\n }\n\n }\n\n if (block.textContent.trim()) {\n\n range = editor.content.getRange();\n selectionLength = range.endOffset - range.startOffset;\n\n if (editor.caret.position.atStart() && !selectionLength && editor.state.inputs[currentInputIndex - 1]) {\n\n editor.content.mergeBlocks(currentInputIndex);\n\n } else {\n\n return;\n\n }\n\n }\n\n if (!selectionLength) {\n\n block.remove();\n\n }\n\n\n firstLevelBlocksCount = editor.nodes.redactor.childNodes.length;\n\n /**\n * If all blocks are removed\n */\n if (firstLevelBlocksCount === 0) {\n\n /** update currentNode variable */\n editor.content.currentNode = null;\n\n /** Inserting new empty initial block */\n editor.ui.addInitialBlock();\n\n /** Updating inputs state after deleting last block */\n editor.ui.saveInputs();\n\n /** Set to current appended block */\n window.setTimeout(function () {\n\n editor.caret.setToPreviousBlock(1);\n\n }, 10);\n\n } else {\n\n if (editor.caret.inputIndex !== 0) {\n\n /** Target block is not first */\n editor.caret.setToPreviousBlock(editor.caret.inputIndex);\n\n } else {\n\n /** If we try to delete first block */\n editor.caret.setToNextBlock(editor.caret.inputIndex);\n\n }\n\n }\n\n editor.toolbar.move();\n\n if (!editor.toolbar.opened) {\n\n editor.toolbar.open();\n\n }\n\n /** Updating inputs state */\n editor.ui.saveInputs();\n\n /** Prevent default browser behaviour */\n event.preventDefault();\n\n };\n\n /**\n * used by UI module\n * Clicks on block settings button\n *\n * @param {Object} event\n * @protected\n * @description Opens toolbar settings\n */\n callbacks.showSettingsButtonClicked = function (event) {\n\n /**\n * Get type of current block\n * It uses to append settings from tool.settings property.\n * ...\n * Type is stored in data-type attribute on block\n */\n var currentToolType = editor.content.currentNode.dataset.tool;\n\n editor.toolbar.settings.toggle(currentToolType);\n\n /** Close toolbox when settings button is active */\n editor.toolbar.toolbox.close();\n editor.toolbar.settings.hideRemoveActions();\n\n };\n\n return callbacks;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_callbacks.js","/**\n * Codex Editor Caret Module\n *\n * @author Codex Team\n * @version 1.0\n */\n\nmodule.exports = (function (caret) {\n\n let editor = codex.editor;\n\n /**\n * @var {int} InputIndex - editable element in DOM\n */\n caret.inputIndex = null;\n\n /**\n * @var {int} offset - caret position in a text node.\n */\n caret.offset = null;\n\n /**\n * @var {int} focusedNodeIndex - we get index of child node from first-level block\n */\n caret.focusedNodeIndex = null;\n\n /**\n * Creates Document Range and sets caret to the element.\n * @protected\n * @uses caret.save — if you need to save caret position\n * @param {Element} el - Changed Node.\n */\n caret.set = function ( el, index, offset) {\n\n offset = offset || caret.offset || 0;\n index = index || caret.focusedNodeIndex || 0;\n\n var childs = el.childNodes,\n nodeToSet;\n\n if ( childs.length === 0 ) {\n\n nodeToSet = el;\n\n } else {\n\n nodeToSet = childs[index];\n\n }\n\n /** If Element is INPUT */\n if (el.contentEditable != 'true') {\n\n el.focus();\n return;\n\n }\n\n if (editor.core.isDomNode(nodeToSet)) {\n\n nodeToSet = editor.content.getDeepestTextNodeFromPosition(nodeToSet, nodeToSet.childNodes.length);\n\n }\n\n var range = document.createRange(),\n selection = window.getSelection();\n\n window.setTimeout(function () {\n\n range.setStart(nodeToSet, offset);\n range.setEnd(nodeToSet, offset);\n\n selection.removeAllRanges();\n selection.addRange(range);\n\n editor.caret.saveCurrentInputIndex();\n\n }, 20);\n\n };\n\n /**\n * @protected\n * Updates index of input and saves it in caret object\n */\n caret.saveCurrentInputIndex = function () {\n\n /** Index of Input that we paste sanitized content */\n var selection = window.getSelection(),\n inputs = editor.state.inputs,\n focusedNode = selection.anchorNode,\n focusedNodeHolder;\n\n if (!focusedNode) {\n\n return;\n\n }\n\n /** Looking for parent contentEditable block */\n while (focusedNode.contentEditable != 'true') {\n\n focusedNodeHolder = focusedNode.parentNode;\n focusedNode = focusedNodeHolder;\n\n }\n\n /** Input index in DOM level */\n var editableElementIndex = 0;\n\n while (focusedNode != inputs[editableElementIndex]) {\n\n editableElementIndex ++;\n\n }\n\n caret.inputIndex = editableElementIndex;\n\n };\n\n /**\n * Returns current input index (caret object)\n */\n caret.getCurrentInputIndex = function () {\n\n return caret.inputIndex;\n\n };\n\n /**\n * @param {int} index - index of first-level block after that we set caret into next input\n */\n caret.setToNextBlock = function (index) {\n\n var inputs = editor.state.inputs,\n nextInput = inputs[index + 1];\n\n if (!nextInput) {\n\n editor.core.log('We are reached the end');\n return;\n\n }\n\n /**\n * When new Block created or deleted content of input\n * We should add some text node to set caret\n */\n if (!nextInput.childNodes.length) {\n\n var emptyTextElement = document.createTextNode('');\n\n nextInput.appendChild(emptyTextElement);\n\n }\n\n editor.caret.inputIndex = index + 1;\n editor.caret.set(nextInput, 0, 0);\n editor.content.workingNodeChanged(nextInput);\n\n };\n\n /**\n * @param {int} index - index of target input.\n * Sets caret to input with this index\n */\n caret.setToBlock = function (index) {\n\n var inputs = editor.state.inputs,\n targetInput = inputs[index];\n\n if ( !targetInput ) {\n\n return;\n\n }\n\n /**\n * When new Block created or deleted content of input\n * We should add some text node to set caret\n */\n if (!targetInput.childNodes.length) {\n\n var emptyTextElement = document.createTextNode('');\n\n targetInput.appendChild(emptyTextElement);\n\n }\n\n editor.caret.inputIndex = index;\n editor.caret.set(targetInput, 0, 0);\n editor.content.workingNodeChanged(targetInput);\n\n };\n\n /**\n * @param {int} index - index of input\n */\n caret.setToPreviousBlock = function (index) {\n\n index = index || 0;\n\n var inputs = editor.state.inputs,\n previousInput = inputs[index - 1],\n lastChildNode,\n lengthOfLastChildNode,\n emptyTextElement;\n\n\n if (!previousInput) {\n\n editor.core.log('We are reached first node');\n return;\n\n }\n\n lastChildNode = editor.content.getDeepestTextNodeFromPosition(previousInput, previousInput.childNodes.length);\n lengthOfLastChildNode = lastChildNode.length;\n\n /**\n * When new Block created or deleted content of input\n * We should add some text node to set caret\n */\n if (!previousInput.childNodes.length) {\n\n emptyTextElement = document.createTextNode('');\n previousInput.appendChild(emptyTextElement);\n\n }\n editor.caret.inputIndex = index - 1;\n editor.caret.set(previousInput, previousInput.childNodes.length - 1, lengthOfLastChildNode);\n editor.content.workingNodeChanged(inputs[index - 1]);\n\n };\n\n caret.position = {\n\n atStart : function () {\n\n var selection = window.getSelection(),\n anchorOffset = selection.anchorOffset,\n anchorNode = selection.anchorNode,\n firstLevelBlock = editor.content.getFirstLevelBlock(anchorNode),\n pluginsRender = firstLevelBlock.childNodes[0];\n\n if (!editor.core.isDomNode(anchorNode)) {\n\n anchorNode = anchorNode.parentNode;\n\n }\n\n var isFirstNode = anchorNode === pluginsRender.childNodes[0],\n isOffsetZero = anchorOffset === 0;\n\n return isFirstNode && isOffsetZero;\n\n },\n\n atTheEnd : function () {\n\n var selection = window.getSelection(),\n anchorOffset = selection.anchorOffset,\n anchorNode = selection.anchorNode;\n\n /** Caret is at the end of input */\n return !anchorNode || !anchorNode.length || anchorOffset === anchorNode.length;\n\n }\n };\n\n\n /**\n * Inserts node at the caret location\n * @param {HTMLElement|DocumentFragment} node\n */\n caret.insertNode = function (node) {\n\n var selection, range,\n lastNode = node;\n\n if (node.nodeType == editor.core.nodeTypes.DOCUMENT_FRAGMENT) {\n\n lastNode = node.lastChild;\n\n }\n\n selection = window.getSelection();\n\n range = selection.getRangeAt(0);\n range.deleteContents();\n\n range.insertNode(node);\n\n range.setStartAfter(lastNode);\n range.collapse(true);\n\n selection.removeAllRanges();\n selection.addRange(range);\n\n\n };\n\n return caret;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_caret.js","/**\n * Codex Editor Content Module\n * Works with DOM\n *\n * @module Codex Editor content module\n *\n * @author Codex Team\n * @version 1.3.13\n *\n * @description Module works with Elements that have been appended to the main DOM\n */\n\nmodule.exports = (function (content) {\n\n let editor = codex.editor;\n\n /**\n * Links to current active block\n * @type {null | Element}\n */\n content.currentNode = null;\n\n /**\n * clicked in redactor area\n * @type {null | Boolean}\n */\n content.editorAreaHightlighted = null;\n\n /**\n * @deprecated\n * Synchronizes redactor with original textarea\n */\n content.sync = function () {\n\n editor.core.log('syncing...');\n\n /**\n * Save redactor content to editor.state\n */\n editor.state.html = editor.nodes.redactor.innerHTML;\n\n };\n\n /**\n * Appends background to the block\n *\n * @description add CSS class to highlight visually first-level block area\n */\n content.markBlock = function () {\n\n editor.content.currentNode.classList.add(editor.ui.className.BLOCK_HIGHLIGHTED);\n\n };\n\n /**\n * Clear background\n *\n * @description clears styles that highlights block\n */\n content.clearMark = function () {\n\n if (editor.content.currentNode) {\n\n editor.content.currentNode.classList.remove(editor.ui.className.BLOCK_HIGHLIGHTED);\n\n }\n\n };\n\n /**\n * Finds first-level block\n *\n * @param {Element} node - selected or clicked in redactors area node\n * @protected\n *\n * @description looks for first-level block.\n * gets parent while node is not first-level\n */\n content.getFirstLevelBlock = function (node) {\n\n if (!editor.core.isDomNode(node)) {\n\n node = node.parentNode;\n\n }\n\n if (node === editor.nodes.redactor || node === document.body) {\n\n return null;\n\n } else {\n\n while(!node.classList.contains(editor.ui.className.BLOCK_CLASSNAME)) {\n\n node = node.parentNode;\n\n }\n\n return node;\n\n }\n\n };\n\n /**\n * Trigger this event when working node changed\n * @param {Element} targetNode - first-level of this node will be current\n * @protected\n *\n * @description If targetNode is first-level then we set it as current else we look for parents to find first-level\n */\n content.workingNodeChanged = function (targetNode) {\n\n /** Clear background from previous marked block before we change */\n editor.content.clearMark();\n\n if (!targetNode) {\n\n return;\n\n }\n\n content.currentNode = content.getFirstLevelBlock(targetNode);\n\n };\n\n /**\n * Replaces one redactor block with another\n * @protected\n * @param {Element} targetBlock - block to replace. Mostly currentNode.\n * @param {Element} newBlock\n * @param {string} newBlockType - type of new block; we need to store it to data-attribute\n *\n * [!] Function does not saves old block content.\n * You can get it manually and pass with newBlock.innerHTML\n */\n content.replaceBlock = function (targetBlock, newBlock) {\n\n if (!targetBlock || !newBlock) {\n\n editor.core.log('replaceBlock: missed params');\n return;\n\n }\n\n /** If target-block is not a frist-level block, then we iterate parents to find it */\n while(!targetBlock.classList.contains(editor.ui.className.BLOCK_CLASSNAME)) {\n\n targetBlock = targetBlock.parentNode;\n\n }\n\n /** Replacing */\n editor.nodes.redactor.replaceChild(newBlock, targetBlock);\n\n /**\n * Set new node as current\n */\n editor.content.workingNodeChanged(newBlock);\n\n /**\n * Add block handlers\n */\n editor.ui.addBlockHandlers(newBlock);\n\n /**\n * Save changes\n */\n editor.ui.saveInputs();\n\n };\n\n /**\n * @protected\n *\n * Inserts new block to redactor\n * Wrapps block into a DIV with BLOCK_CLASSNAME class\n *\n * @param blockData {object}\n * @param blockData.block {Element} element with block content\n * @param blockData.type {string} block plugin\n * @param needPlaceCaret {bool} pass true to set caret in new block\n *\n */\n content.insertBlock = function ( blockData, needPlaceCaret ) {\n\n var workingBlock = editor.content.currentNode,\n newBlockContent = blockData.block,\n blockType = blockData.type,\n isStretched = blockData.stretched;\n\n var newBlock = composeNewBlock_(newBlockContent, blockType, isStretched);\n\n if (workingBlock) {\n\n editor.core.insertAfter(workingBlock, newBlock);\n\n } else {\n\n /**\n * If redactor is empty, append as first child\n */\n editor.nodes.redactor.appendChild(newBlock);\n\n }\n\n /**\n * Block handler\n */\n editor.ui.addBlockHandlers(newBlock);\n\n /**\n * Set new node as current\n */\n editor.content.workingNodeChanged(newBlock);\n\n /**\n * Save changes\n */\n editor.ui.saveInputs();\n\n\n if ( needPlaceCaret ) {\n\n /**\n * If we don't know input index then we set default value -1\n */\n var currentInputIndex = editor.caret.getCurrentInputIndex() || -1;\n\n\n if (currentInputIndex == -1) {\n\n\n var editableElement = newBlock.querySelector('[contenteditable]'),\n emptyText = document.createTextNode('');\n\n editableElement.appendChild(emptyText);\n editor.caret.set(editableElement, 0, 0);\n\n editor.toolbar.move();\n editor.toolbar.showPlusButton();\n\n\n } else {\n\n if (currentInputIndex === editor.state.inputs.length - 1)\n return;\n\n /** Timeout for browsers execution */\n window.setTimeout(function () {\n\n /** Setting to the new input */\n editor.caret.setToNextBlock(currentInputIndex);\n editor.toolbar.move();\n editor.toolbar.open();\n\n }, 10);\n\n }\n\n }\n\n /**\n * Block is inserted, wait for new click that defined focusing on editors area\n * @type {boolean}\n */\n content.editorAreaHightlighted = false;\n\n };\n\n /**\n * Replaces blocks with saving content\n * @protected\n * @param {Element} noteToReplace\n * @param {Element} newNode\n * @param {Element} blockType\n */\n content.switchBlock = function (blockToReplace, newBlock, tool) {\n\n tool = tool || editor.content.currentNode.dataset.tool;\n var newBlockComposed = composeNewBlock_(newBlock, tool);\n\n /** Replacing */\n editor.content.replaceBlock(blockToReplace, newBlockComposed);\n\n /** Save new Inputs when block is changed */\n editor.ui.saveInputs();\n\n };\n\n /**\n * Iterates between child noted and looking for #text node on deepest level\n * @protected\n *\n * @param {Element} block - node where find\n * @param {int} postiton - starting postion\n * Example: childNodex.length to find from the end\n * or 0 to find from the start\n * @return {Text} block\n * @uses DFS\n */\n content.getDeepestTextNodeFromPosition = function (block, position) {\n\n /**\n * Clear Block from empty and useless spaces with trim.\n * Such nodes we should remove\n */\n var blockChilds = block.childNodes,\n index,\n node,\n text;\n\n for(index = 0; index < blockChilds.length; index++) {\n\n node = blockChilds[index];\n\n if (node.nodeType == editor.core.nodeTypes.TEXT) {\n\n text = node.textContent.trim();\n\n /** Text is empty. We should remove this child from node before we start DFS\n * decrease the quantity of childs.\n */\n if (text === '') {\n\n block.removeChild(node);\n position--;\n\n }\n\n }\n\n }\n\n if (block.childNodes.length === 0) {\n\n return document.createTextNode('');\n\n }\n\n /** Setting default position when we deleted all empty nodes */\n if ( position < 0 )\n position = 1;\n\n var lookingFromStart = false;\n\n /** For looking from START */\n if (position === 0) {\n\n lookingFromStart = true;\n position = 1;\n\n }\n\n while ( position ) {\n\n /** initial verticle of node. */\n if ( lookingFromStart ) {\n\n block = block.childNodes[0];\n\n } else {\n\n block = block.childNodes[position - 1];\n\n }\n\n if ( block.nodeType == editor.core.nodeTypes.TAG ) {\n\n position = block.childNodes.length;\n\n } else if (block.nodeType == editor.core.nodeTypes.TEXT ) {\n\n position = 0;\n\n }\n\n }\n\n return block;\n\n };\n\n /**\n * @private\n * @param {Element} block - current plugins render\n * @param {String} tool - plugins name\n * @param {Boolean} isStretched - make stretched block or not\n *\n * @description adds necessary information to wrap new created block by first-level holder\n */\n var composeNewBlock_ = function (block, tool, isStretched) {\n\n var newBlock = editor.draw.node('DIV', editor.ui.className.BLOCK_CLASSNAME, {}),\n blockContent = editor.draw.node('DIV', editor.ui.className.BLOCK_CONTENT, {});\n\n blockContent.appendChild(block);\n newBlock.appendChild(blockContent);\n\n if (isStretched) {\n\n blockContent.classList.add(editor.ui.className.BLOCK_STRETCHED);\n\n }\n\n newBlock.dataset.tool = tool;\n return newBlock;\n\n };\n\n /**\n * Returns Range object of current selection\n * @protected\n */\n content.getRange = function () {\n\n var selection = window.getSelection().getRangeAt(0);\n\n return selection;\n\n };\n\n /**\n * Divides block in two blocks (after and before caret)\n *\n * @protected\n * @param {int} inputIndex - target input index\n *\n * @description splits current input content to the separate blocks\n * When enter is pressed among the words, that text will be splited.\n */\n content.splitBlock = function (inputIndex) {\n\n var selection = window.getSelection(),\n anchorNode = selection.anchorNode,\n anchorNodeText = anchorNode.textContent,\n caretOffset = selection.anchorOffset,\n textBeforeCaret,\n textNodeBeforeCaret,\n textAfterCaret,\n textNodeAfterCaret;\n\n var currentBlock = editor.content.currentNode.querySelector('[contentEditable]');\n\n\n textBeforeCaret = anchorNodeText.substring(0, caretOffset);\n textAfterCaret = anchorNodeText.substring(caretOffset);\n\n textNodeBeforeCaret = document.createTextNode(textBeforeCaret);\n\n if (textAfterCaret) {\n\n textNodeAfterCaret = document.createTextNode(textAfterCaret);\n\n }\n\n var previousChilds = [],\n nextChilds = [],\n reachedCurrent = false;\n\n if (textNodeAfterCaret) {\n\n nextChilds.push(textNodeAfterCaret);\n\n }\n\n for ( var i = 0, child; !!(child = currentBlock.childNodes[i]); i++) {\n\n if ( child != anchorNode ) {\n\n if ( !reachedCurrent ) {\n\n previousChilds.push(child);\n\n } else {\n\n nextChilds.push(child);\n\n }\n\n } else {\n\n reachedCurrent = true;\n\n }\n\n }\n\n /** Clear current input */\n editor.state.inputs[inputIndex].innerHTML = '';\n\n /**\n * Append all childs founded before anchorNode\n */\n var previousChildsLength = previousChilds.length;\n\n for(i = 0; i < previousChildsLength; i++) {\n\n editor.state.inputs[inputIndex].appendChild(previousChilds[i]);\n\n }\n\n editor.state.inputs[inputIndex].appendChild(textNodeBeforeCaret);\n\n /**\n * Append text node which is after caret\n */\n var nextChildsLength = nextChilds.length,\n newNode = document.createElement('div');\n\n for(i = 0; i < nextChildsLength; i++) {\n\n newNode.appendChild(nextChilds[i]);\n\n }\n\n newNode = newNode.innerHTML;\n\n /** This type of block creates when enter is pressed */\n var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin;\n\n /**\n * Make new paragraph with text after caret\n */\n editor.content.insertBlock({\n type : NEW_BLOCK_TYPE,\n block : editor.tools[NEW_BLOCK_TYPE].render({\n text : newNode\n })\n }, true );\n\n };\n\n /**\n * Merges two blocks — current and target\n * If target index is not exist, then previous will be as target\n *\n * @protected\n * @param {int} currentInputIndex\n * @param {int} targetInputIndex\n *\n * @description gets two inputs indexes and merges into one\n */\n content.mergeBlocks = function (currentInputIndex, targetInputIndex) {\n\n /** If current input index is zero, then prevent method execution */\n if (currentInputIndex === 0) {\n\n return;\n\n }\n\n var targetInput,\n currentInputContent = editor.state.inputs[currentInputIndex].innerHTML;\n\n if (!targetInputIndex) {\n\n targetInput = editor.state.inputs[currentInputIndex - 1];\n\n } else {\n\n targetInput = editor.state.inputs[targetInputIndex];\n\n }\n\n targetInput.innerHTML += currentInputContent;\n\n };\n\n /**\n * Iterates all right siblings and parents, which has right siblings\n * while it does not reached the first-level block\n *\n * @param {Element} node\n * @return {boolean}\n */\n content.isLastNode = function (node) {\n\n // console.log('погнали перебор родителей');\n\n var allChecked = false;\n\n while ( !allChecked ) {\n\n // console.log('Смотрим на %o', node);\n // console.log('Проверим, пустые ли соседи справа');\n\n if ( !allSiblingsEmpty_(node) ) {\n\n // console.log('Есть непустые соседи. Узел не последний. Выходим.');\n return false;\n\n }\n\n node = node.parentNode;\n\n /**\n * Проверяем родителей до тех пор, пока не найдем блок первого уровня\n */\n if ( node.classList.contains(editor.ui.className.BLOCK_CONTENT) ) {\n\n allChecked = true;\n\n }\n\n }\n\n return true;\n\n };\n\n /**\n * Checks if all element right siblings is empty\n * @param node\n */\n var allSiblingsEmpty_ = function (node) {\n\n /**\n * Нужно убедиться, что после пустого соседа ничего нет\n */\n var sibling = node.nextSibling;\n\n while ( sibling ) {\n\n if (sibling.textContent.length) {\n\n return false;\n\n }\n\n sibling = sibling.nextSibling;\n\n }\n\n return true;\n\n };\n\n /**\n * @public\n *\n * @param {string} htmlData - html content as string\n * @param {string} plainData - plain text\n * @return {string} - html content as string\n */\n content.wrapTextWithParagraphs = function (htmlData, plainData) {\n\n if (!htmlData.trim()) {\n\n return wrapPlainTextWithParagraphs(plainData);\n\n }\n\n var wrapper = document.createElement('DIV'),\n newWrapper = document.createElement('DIV'),\n i,\n paragraph,\n firstLevelBlocks = ['DIV', 'P'],\n blockTyped,\n node;\n\n /**\n * Make HTML Element to Wrap Text\n * It allows us to work with input data as HTML content\n */\n wrapper.innerHTML = htmlData;\n paragraph = document.createElement('P');\n\n for (i = 0; i < wrapper.childNodes.length; i++) {\n\n node = wrapper.childNodes[i];\n\n blockTyped = firstLevelBlocks.indexOf(node.tagName) != -1;\n\n /**\n * If node is first-levet\n * we add this node to our new wrapper\n */\n if ( blockTyped ) {\n\n /**\n * If we had splitted inline nodes to paragraph before\n */\n if ( paragraph.childNodes.length ) {\n\n newWrapper.appendChild(paragraph.cloneNode(true));\n\n /** empty paragraph */\n paragraph = null;\n paragraph = document.createElement('P');\n\n }\n\n newWrapper.appendChild(node.cloneNode(true));\n\n } else {\n\n /** Collect all inline nodes to one as paragraph */\n paragraph.appendChild(node.cloneNode(true));\n\n /** if node is last we should append this node to paragraph and paragraph to new wrapper */\n if ( i == wrapper.childNodes.length - 1 ) {\n\n newWrapper.appendChild(paragraph.cloneNode(true));\n\n }\n\n }\n\n }\n\n return newWrapper.innerHTML;\n\n };\n\n /**\n * Splits strings on new line and wraps paragraphs with
tag\n * @param plainText\n * @returns {string}\n */\n var wrapPlainTextWithParagraphs = function (plainText) {\n\n if (!plainText) return '';\n\n return '
' + plainText.split('\\n\\n').join('
') + '
';\n\n };\n\n /**\n * Finds closest Contenteditable parent from Element\n * @param {Element} node element looking from\n * @return {Element} node contenteditable\n */\n content.getEditableParent = function (node) {\n\n while (node && node.contentEditable != 'true') {\n\n node = node.parentNode;\n\n }\n\n return node;\n\n };\n\n /**\n * Clear editors content\n *\n * @param {Boolean} all — if true, delete all article data (content, id, etc.)\n */\n content.clear = function (all) {\n\n editor.nodes.redactor.innerHTML = '';\n editor.content.sync();\n editor.ui.saveInputs();\n if (all) {\n\n editor.state.blocks = {};\n\n } else if (editor.state.blocks) {\n\n editor.state.blocks.items = [];\n\n }\n\n editor.content.currentNode = null;\n\n };\n\n /**\n *\n * Load new data to editor\n * If editor is not empty, just append articleData.items\n *\n * @param articleData.items\n */\n content.load = function (articleData) {\n\n var currentContent = Object.assign({}, editor.state.blocks);\n\n editor.content.clear();\n\n if (!Object.keys(currentContent).length) {\n\n editor.state.blocks = articleData;\n\n } else if (!currentContent.items) {\n\n currentContent.items = articleData.items;\n editor.state.blocks = currentContent;\n\n } else {\n\n currentContent.items = currentContent.items.concat(articleData.items);\n editor.state.blocks = currentContent;\n\n }\n\n editor.renderer.makeBlocksFromData();\n\n };\n\n return content;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_content.js","/**\n * Codex Editor Destroyer module\n *\n * @auhor Codex Team\n * @version 1.0\n */\n\nmodule.exports = function (destroyer) {\n\n let editor = codex.editor;\n\n destroyer.removeNodes = function () {\n\n editor.nodes.wrapper.remove();\n editor.nodes.notifications.remove();\n\n };\n\n destroyer.destroyPlugins = function () {\n\n for (var tool in editor.tools) {\n\n if (typeof editor.tools[tool].destroy === 'function') {\n\n editor.tools[tool].destroy();\n\n }\n\n }\n\n };\n\n destroyer.destroyScripts = function () {\n\n var scripts = document.getElementsByTagName('SCRIPT');\n\n for (var i = 0; i < scripts.length; i++) {\n\n if (scripts[i].id.indexOf(editor.scriptPrefix) + 1) {\n\n scripts[i].remove();\n i--;\n\n }\n\n }\n\n };\n\n\n /**\n * Delete editor data from webpage.\n * You should send settings argument with boolean flags:\n * @param settings.ui- remove redactor event listeners and DOM nodes\n * @param settings.scripts - remove redactor scripts from DOM\n * @param settings.plugins - remove plugin's objects\n * @param settings.core - remove editor core. You can remove core only if UI and scripts flags is true\n * }\n *\n */\n destroyer.destroy = function (settings) {\n\n if (!settings || typeof settings !== 'object') {\n\n return;\n\n }\n\n if (settings.ui) {\n\n destroyer.removeNodes();\n editor.listeners.removeAll();\n\n }\n\n if (settings.scripts) {\n\n destroyer.destroyScripts();\n\n }\n\n if (settings.plugins) {\n\n destroyer.destroyPlugins();\n\n }\n\n if (settings.ui && settings.scripts && settings.core) {\n\n delete codex.editor;\n\n }\n\n };\n\n return destroyer;\n\n}({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_destroyer.js","/**\n * Codex Editor Listeners module\n *\n * @author Codex Team\n * @version 1.0\n */\n\n/**\n * Module-decorator for event listeners assignment\n */\nmodule.exports = function (listeners) {\n\n var allListeners = [];\n\n /**\n * Search methods\n *\n * byElement, byType and byHandler returns array of suitable listeners\n * one and all takes element, eventType, and handler and returns first (all) suitable listener\n *\n */\n listeners.search = function () {\n\n var byElement = function (element, context) {\n\n var listenersOnElement = [];\n\n context = context || allListeners;\n\n for (var i = 0; i < context.length; i++) {\n\n var listener = context[i];\n\n if (listener.element === element) {\n\n listenersOnElement.push(listener);\n\n }\n\n }\n\n return listenersOnElement;\n\n };\n\n var byType = function (eventType, context) {\n\n var listenersWithType = [];\n\n context = context || allListeners;\n\n for (var i = 0; i < context.length; i++) {\n\n var listener = context[i];\n\n if (listener.type === eventType) {\n\n listenersWithType.push(listener);\n\n }\n\n }\n\n return listenersWithType;\n\n };\n\n var byHandler = function (handler, context) {\n\n var listenersWithHandler = [];\n\n context = context || allListeners;\n\n for (var i = 0; i < context.length; i++) {\n\n var listener = context[i];\n\n if (listener.handler === handler) {\n\n listenersWithHandler.push(listener);\n\n }\n\n }\n\n return listenersWithHandler;\n\n };\n\n var one = function (element, eventType, handler) {\n\n var result = allListeners;\n\n if (element)\n result = byElement(element, result);\n\n if (eventType)\n result = byType(eventType, result);\n\n if (handler)\n result = byHandler(handler, result);\n\n return result[0];\n\n };\n\n var all = function (element, eventType, handler) {\n\n var result = allListeners;\n\n if (element)\n result = byElement(element, result);\n\n if (eventType)\n result = byType(eventType, result);\n\n if (handler)\n result = byHandler(handler, result);\n\n return result;\n\n };\n\n return {\n byElement : byElement,\n byType : byType,\n byHandler : byHandler,\n one : one,\n all : all\n };\n\n }();\n\n listeners.add = function (element, eventType, handler, isCapture) {\n\n element.addEventListener(eventType, handler, isCapture);\n\n var data = {\n element: element,\n type: eventType,\n handler: handler\n };\n\n var alreadyAddedListener = listeners.search.one(element, eventType, handler);\n\n if (!alreadyAddedListener) {\n\n allListeners.push(data);\n\n }\n\n };\n\n listeners.remove = function (element, eventType, handler) {\n\n element.removeEventListener(eventType, handler);\n\n var existingListeners = listeners.search.all(element, eventType, handler);\n\n for (var i = 0; i < existingListeners.length; i++) {\n\n var index = allListeners.indexOf(existingListeners[i]);\n\n if (index > 0) {\n\n allListeners.splice(index, 1);\n\n }\n\n }\n\n };\n\n listeners.removeAll = function () {\n\n allListeners.map(function (current) {\n\n listeners.remove(current.element, current.type, current.handler);\n\n });\n\n };\n\n listeners.get = function (element, eventType, handler) {\n\n return listeners.search.all(element, eventType, handler);\n\n };\n\n return listeners;\n\n}({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_listeners.js","/**\n * Codex Editor Notification Module\n *\n * @author Codex Team\n * @version 1.0\n */\n\nmodule.exports = (function (notifications) {\n\n let editor = codex.editor;\n\n var queue = [];\n\n var addToQueue = function (settings) {\n\n queue.push(settings);\n\n var index = 0;\n\n while ( index < queue.length && queue.length > 5) {\n\n if (queue[index].type == 'confirm' || queue[index].type == 'prompt') {\n\n index++;\n continue;\n\n }\n\n queue[index].close();\n queue.splice(index, 1);\n\n }\n\n };\n\n notifications.createHolder = function () {\n\n var holder = editor.draw.node('DIV', 'cdx-notifications-block');\n\n editor.nodes.notifications = document.body.appendChild(holder);\n\n return holder;\n\n };\n\n\n /**\n * Error notificator. Shows block with message\n * @protected\n */\n notifications.errorThrown = function (errorMsg, event) {\n\n editor.notifications.notification({message: 'This action is not available currently', type: event.type});\n\n };\n\n /**\n *\n * Appends notification\n *\n * settings = {\n * type - notification type (reserved types: alert, confirm, prompt). Just add class 'cdx-notification-'+type\n * message - notification message\n * okMsg - confirm button text (default - 'Ok')\n * cancelBtn - cancel button text (default - 'Cancel'). Only for confirm and prompt types\n * confirm - function-handler for ok button click\n * cancel - function-handler for cancel button click. Only for confirm and prompt types\n * time - time (in seconds) after which notification will close (default - 10s)\n * }\n *\n * @param settings\n */\n notifications.notification = function (constructorSettings) {\n\n /** Private vars and methods */\n var notification = null,\n cancel = null,\n type = null,\n confirm = null,\n inputField = null;\n\n var confirmHandler = function () {\n\n close();\n\n if (typeof confirm !== 'function' ) {\n\n return;\n\n }\n\n if (type == 'prompt') {\n\n confirm(inputField.value);\n return;\n\n }\n\n confirm();\n\n };\n\n var cancelHandler = function () {\n\n close();\n\n if (typeof cancel !== 'function' ) {\n\n return;\n\n }\n\n cancel();\n\n };\n\n\n /** Public methods */\n function create(settings) {\n\n if (!(settings && settings.message)) {\n\n editor.core.log('Can\\'t create notification. Message is missed');\n return;\n\n }\n\n settings.type = settings.type || 'alert';\n settings.time = settings.time*1000 || 10000;\n\n var wrapper = editor.draw.node('DIV', 'cdx-notification'),\n message = editor.draw.node('DIV', 'cdx-notification__message'),\n input = editor.draw.node('INPUT', 'cdx-notification__input'),\n okBtn = editor.draw.node('SPAN', 'cdx-notification__ok-btn'),\n cancelBtn = editor.draw.node('SPAN', 'cdx-notification__cancel-btn');\n\n message.textContent = settings.message;\n okBtn.textContent = settings.okMsg || 'ОК';\n cancelBtn.textContent = settings.cancelMsg || 'Отмена';\n\n editor.listeners.add(okBtn, 'click', confirmHandler);\n editor.listeners.add(cancelBtn, 'click', cancelHandler);\n\n wrapper.appendChild(message);\n\n if (settings.type == 'prompt') {\n\n wrapper.appendChild(input);\n\n }\n\n wrapper.appendChild(okBtn);\n\n if (settings.type == 'prompt' || settings.type == 'confirm') {\n\n wrapper.appendChild(cancelBtn);\n\n }\n\n wrapper.classList.add('cdx-notification-' + settings.type);\n wrapper.dataset.type = settings.type;\n\n notification = wrapper;\n type = settings.type;\n confirm = settings.confirm;\n cancel = settings.cancel;\n inputField = input;\n\n if (settings.type != 'prompt' && settings.type != 'confirm') {\n\n window.setTimeout(close, settings.time);\n\n }\n\n };\n\n /**\n * Show notification block\n */\n function send() {\n\n editor.nodes.notifications.appendChild(notification);\n inputField.focus();\n\n editor.nodes.notifications.classList.add('cdx-notification__notification-appending');\n\n window.setTimeout(function () {\n\n editor.nodes.notifications.classList.remove('cdx-notification__notification-appending');\n\n }, 100);\n\n addToQueue({type: type, close: close});\n\n };\n\n /**\n * Remove notification block\n */\n function close() {\n\n notification.remove();\n\n };\n\n\n if (constructorSettings) {\n\n create(constructorSettings);\n send();\n\n }\n\n return {\n create: create,\n send: send,\n close: close\n };\n\n };\n\n notifications.clear = function () {\n\n editor.nodes.notifications.innerHTML = '';\n queue = [];\n\n };\n\n return notifications;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_notifications.js","/**\n * Codex Editor Parser Module\n *\n * @author Codex Team\n * @version 1.1\n */\n\nmodule.exports = (function (parser) {\n\n let editor = codex.editor;\n\n /** inserting text */\n parser.insertPastedContent = function (blockType, tag) {\n\n editor.content.insertBlock({\n type : blockType.type,\n block : blockType.render({\n text : tag.innerHTML\n })\n });\n\n };\n\n /**\n * Check DOM node for display style: separated block or child-view\n */\n parser.isFirstLevelBlock = function (node) {\n\n return node.nodeType == editor.core.nodeTypes.TAG &&\n node.classList.contains(editor.ui.className.BLOCK_CLASSNAME);\n\n };\n\n return parser;\n\n})({});\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_parser.js","/**\n * Codex Editor Paste module\n *\n * @author Codex Team\n * @version 1.1.1\n */\n\nmodule.exports = function (paste) {\n\n let editor = codex.editor;\n\n var patterns = [];\n\n paste.prepare = function () {\n\n var tools = editor.tools;\n\n for (var tool in tools) {\n\n if (!tools[tool].renderOnPastePatterns || !Array.isArray(tools[tool].renderOnPastePatterns)) {\n\n continue;\n\n }\n\n tools[tool].renderOnPastePatterns.map(function (pattern) {\n\n\n patterns.push(pattern);\n\n });\n\n }\n\n return Promise.resolve();\n\n };\n\n /**\n * Saves data\n * @param event\n */\n paste.pasted = function (event) {\n\n var clipBoardData = event.clipboardData || window.clipboardData,\n content = clipBoardData.getData('Text');\n\n var result = analize(content);\n\n if (result) {\n\n event.preventDefault();\n event.stopImmediatePropagation();\n\n }\n\n return result;\n\n };\n\n /**\n * Analizes pated string and calls necessary method\n */\n\n var analize = function (string) {\n\n var result = false,\n content = editor.content.currentNode,\n plugin = content.dataset.tool;\n\n patterns.map( function (pattern) {\n\n var execArray = pattern.regex.exec(string),\n match = execArray && execArray[0];\n\n if ( match && match === string.trim()) {\n\n /** current block is not empty */\n if ( content.textContent.trim() && plugin == editor.settings.initialBlockPlugin ) {\n\n pasteToNewBlock_();\n\n }\n\n pattern.callback(string, pattern);\n result = true;\n\n }\n\n });\n\n return result;\n\n };\n\n var pasteToNewBlock_ = function () {\n\n /** Create new initial block */\n editor.content.insertBlock({\n\n type : editor.settings.initialBlockPlugin,\n block : editor.tools[editor.settings.initialBlockPlugin].render({\n text : ''\n })\n\n }, false);\n\n };\n\n /**\n * This method prevents default behaviour.\n *\n * @param {Object} event\n * @protected\n *\n * @description We get from clipboard pasted data, sanitize, make a fragment that contains of this sanitized nodes.\n * Firstly, we need to memorize the caret position. We can do that by getting the range of selection.\n * After all, we insert clear fragment into caret placed position. Then, we should move the caret to the last node\n */\n paste.blockPasteCallback = function (event) {\n\n\n if (!needsToHandlePasteEvent(event.target)) {\n\n return;\n\n }\n\n /** Prevent default behaviour */\n event.preventDefault();\n\n /** get html pasted data - dirty data */\n var htmlData = event.clipboardData.getData('text/html'),\n plainData = event.clipboardData.getData('text/plain');\n\n /** Temporary DIV that is used to work with text's paragraphs as DOM-elements*/\n var paragraphs = editor.draw.node('DIV', '', {}),\n cleanData,\n wrappedData;\n\n /** Create fragment, that we paste to range after proccesing */\n cleanData = editor.sanitizer.clean(htmlData);\n\n /**\n * We wrap pasted text with tags to split it logically\n * @type {string}\n */\n wrappedData = editor.content.wrapTextWithParagraphs(cleanData, plainData);\n paragraphs.innerHTML = wrappedData;\n\n /**\n * If there only one paragraph, just insert in at the caret location\n */\n if (paragraphs.childNodes.length == 1) {\n\n emulateUserAgentBehaviour(paragraphs.firstChild);\n return;\n\n }\n\n insertPastedParagraphs(paragraphs.childNodes);\n\n };\n\n /**\n * Checks if we should handle paste event on block\n * @param block\n *\n * @return {boolean}\n */\n var needsToHandlePasteEvent = function (block) {\n\n /** If area is input or textarea then allow default behaviour */\n if ( editor.core.isNativeInput(block) ) {\n\n return false;\n\n }\n\n var editableParent = editor.content.getEditableParent(block);\n\n /** Allow paste when event target placed in Editable element */\n if (!editableParent) {\n\n return false;\n\n }\n\n return true;\n\n };\n\n /**\n * Inserts new initial plugin blocks with data in paragraphs\n *\n * @param {Array} paragraphs - array of paragraphs (
) whit content, that should be inserted\n */\n var insertPastedParagraphs = function (paragraphs) {\n\n var NEW_BLOCK_TYPE = editor.settings.initialBlockPlugin,\n currentNode = editor.content.currentNode;\n\n\n paragraphs.forEach(function (paragraph) {\n\n /** Don't allow empty paragraphs */\n if (editor.core.isBlockEmpty(paragraph)) {\n\n return;\n\n }\n\n editor.content.insertBlock({\n type : NEW_BLOCK_TYPE,\n block : editor.tools[NEW_BLOCK_TYPE].render({\n text : paragraph.innerHTML\n })\n });\n\n editor.caret.inputIndex++;\n\n });\n\n editor.caret.setToPreviousBlock(editor.caret.getCurrentInputIndex() + 1);\n\n\n /**\n * If there was no data in working node, remove it\n */\n if (editor.core.isBlockEmpty(currentNode)) {\n\n currentNode.remove();\n editor.ui.saveInputs();\n\n }\n\n\n };\n\n /**\n * Inserts node content at the caret position\n *\n * @param {Node} node - DOM node (could be DocumentFragment), that should be inserted at the caret location\n */\n var emulateUserAgentBehaviour = function (node) {\n\n var newNode;\n\n if (node.childElementCount) {\n\n newNode = document.createDocumentFragment();\n\n node.childNodes.forEach(function (current) {\n\n if (!editor.core.isDomNode(current) && current.data.trim() === '') {\n\n return;\n\n }\n\n newNode.appendChild(current.cloneNode(true));\n\n });\n\n } else {\n\n newNode = document.createTextNode(node.textContent);\n\n }\n\n editor.caret.insertNode(newNode);\n\n };\n\n\n return paste;\n\n}({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_paste.js","/**\n * Codex Editor Renderer Module\n *\n * @author Codex Team\n * @version 1.0\n */\n\nmodule.exports = (function (renderer) {\n\n let editor = codex.editor;\n\n /**\n * Asyncronously parses input JSON to redactor blocks\n */\n renderer.makeBlocksFromData = function () {\n\n /**\n * If redactor is empty, add first paragraph to start writing\n */\n if (editor.core.isEmpty(editor.state.blocks) || !editor.state.blocks.items.length) {\n\n editor.ui.addInitialBlock();\n return;\n\n }\n\n Promise.resolve()\n\n /** First, get JSON from state */\n .then(function () {\n\n return editor.state.blocks;\n\n })\n\n /** Then, start to iterate they */\n .then(editor.renderer.appendBlocks)\n\n /** Write log if something goes wrong */\n .catch(function (error) {\n\n editor.core.log('Error while parsing JSON: %o', 'error', error);\n\n });\n\n };\n\n /**\n * Parses JSON to blocks\n * @param {object} data\n * @return Primise -> nodeList\n */\n renderer.appendBlocks = function (data) {\n\n var blocks = data.items;\n\n /**\n * Sequence of one-by-one blocks appending\n * Uses to save blocks order after async-handler\n */\n var nodeSequence = Promise.resolve();\n\n for (var index = 0; index < blocks.length ; index++ ) {\n\n /** Add node to sequence at specified index */\n editor.renderer.appendNodeAtIndex(nodeSequence, blocks, index);\n\n }\n\n };\n\n /**\n * Append node at specified index\n */\n renderer.appendNodeAtIndex = function (nodeSequence, blocks, index) {\n\n /** We need to append node to sequence */\n nodeSequence\n\n /** first, get node async-aware */\n .then(function () {\n\n return editor.renderer.getNodeAsync(blocks, index);\n\n })\n\n /**\n * second, compose editor-block from JSON object\n */\n .then(editor.renderer.createBlockFromData)\n\n /**\n * now insert block to redactor\n */\n .then(function (blockData) {\n\n /**\n * blockData has 'block', 'type' and 'stretched' information\n */\n editor.content.insertBlock(blockData);\n\n /** Pass created block to next step */\n return blockData.block;\n\n })\n\n /** Log if something wrong with node */\n .catch(function (error) {\n\n editor.core.log('Node skipped while parsing because %o', 'error', error);\n\n });\n\n };\n\n /**\n * Asynchronously returns block data from blocksList by index\n * @return Promise to node\n */\n renderer.getNodeAsync = function (blocksList, index) {\n\n return Promise.resolve().then(function () {\n\n return {\n tool : blocksList[index],\n position : index\n };\n\n });\n\n };\n\n /**\n * Creates editor block by JSON-data\n *\n * @uses render method of each plugin\n *\n * @param {Object} toolData.tool\n * { header : {\n * text: '',\n * type: 'H3', ...\n * }\n * }\n * @param {Number} toolData.position - index in input-blocks array\n * @return {Object} with type and Element\n */\n renderer.createBlockFromData = function ( toolData ) {\n\n /** New parser */\n var block,\n tool = toolData.tool,\n pluginName = tool.type;\n\n /** Get first key of object that stores plugin name */\n // for (var pluginName in blockData) break;\n\n /** Check for plugin existance */\n if (!editor.tools[pluginName]) {\n\n throw Error(`Plugin «${pluginName}» not found`);\n\n }\n\n /** Check for plugin having render method */\n if (typeof editor.tools[pluginName].render != 'function') {\n\n throw Error(`Plugin «${pluginName}» must have «render» method`);\n\n }\n\n if ( editor.tools[pluginName].available === false ) {\n\n block = editor.draw.unavailableBlock();\n\n block.innerHTML = editor.tools[pluginName].loadingMessage;\n\n /**\n * Saver will extract data from initial block data by position in array\n */\n block.dataset.inputPosition = toolData.position;\n\n } else {\n\n /** New Parser */\n block = editor.tools[pluginName].render(tool.data);\n\n }\n\n /** is first-level block stretched */\n var stretched = editor.tools[pluginName].isStretched || false;\n\n /** Retrun type and block */\n return {\n type : pluginName,\n block : block,\n stretched : stretched\n };\n\n };\n\n return renderer;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_renderer.js","/**\n * Codex Sanitizer\n */\n\nmodule.exports = (function (sanitizer) {\n\n /** HTML Janitor library */\n let janitor = require('html-janitor');\n\n /** Codex Editor */\n let editor = codex.editor;\n\n sanitizer.prepare = function () {\n\n if (editor.settings.sanitizer && !editor.core.isEmpty(editor.settings.sanitizer)) {\n\n Config.CUSTOM = editor.settings.sanitizer;\n\n }\n\n };\n\n /**\n * Basic config\n */\n var Config = {\n\n /** User configuration */\n CUSTOM : null,\n\n BASIC : {\n\n tags: {\n p: {},\n a: {\n href: true,\n target: '_blank',\n rel: 'nofollow'\n }\n }\n }\n };\n\n sanitizer.Config = Config;\n\n /**\n *\n * @param userCustomConfig\n * @returns {*}\n * @private\n *\n * @description If developer uses editor's API, then he can customize sane restrictions.\n * Or, sane config can be defined globally in editors initialization. That config will be used everywhere\n * At least, if there is no config overrides, that API uses BASIC Default configation\n */\n let init_ = function (userCustomConfig) {\n\n let configuration = userCustomConfig || Config.CUSTOM || Config.BASIC;\n\n return new janitor(configuration);\n\n };\n\n /**\n * Cleans string from unwanted tags\n * @protected\n * @param {String} dirtyString - taint string\n * @param {Object} customConfig - allowed tags\n */\n sanitizer.clean = function (dirtyString, customConfig) {\n\n let janitorInstance = init_(customConfig);\n\n return janitorInstance.clean(dirtyString);\n\n };\n\n return sanitizer;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_sanitizer.js","(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n define('html-janitor', factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.HTMLJanitor = factory();\n }\n}(this, function () {\n\n /**\n * @param {Object} config.tags Dictionary of allowed tags.\n * @param {boolean} config.keepNestedBlockElements Default false.\n */\n function HTMLJanitor(config) {\n\n var tagDefinitions = config['tags'];\n var tags = Object.keys(tagDefinitions);\n\n var validConfigValues = tags\n .map(function(k) { return typeof tagDefinitions[k]; })\n .every(function(type) { return type === 'object' || type === 'boolean' || type === 'function'; });\n\n if(!validConfigValues) {\n throw new Error(\"The configuration was invalid\");\n }\n\n this.config = config;\n }\n\n // TODO: not exhaustive?\n var blockElementNames = ['P', 'LI', 'TD', 'TH', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'PRE'];\n function isBlockElement(node) {\n return blockElementNames.indexOf(node.nodeName) !== -1;\n }\n\n var inlineElementNames = ['A', 'B', 'STRONG', 'I', 'EM', 'SUB', 'SUP', 'U', 'STRIKE'];\n function isInlineElement(node) {\n return inlineElementNames.indexOf(node.nodeName) !== -1;\n }\n\n HTMLJanitor.prototype.clean = function (html) {\n var sandbox = document.createElement('div');\n sandbox.innerHTML = html;\n\n this._sanitize(sandbox);\n\n return sandbox.innerHTML;\n };\n\n HTMLJanitor.prototype._sanitize = function (parentNode) {\n var treeWalker = createTreeWalker(parentNode);\n var node = treeWalker.firstChild();\n if (!node) { return; }\n\n do {\n // Ignore nodes that have already been sanitized\n if (node._sanitized) {\n continue;\n }\n\n if (node.nodeType === Node.TEXT_NODE) {\n // If this text node is just whitespace and the previous or next element\n // sibling is a block element, remove it\n // N.B.: This heuristic could change. Very specific to a bug with\n // `contenteditable` in Firefox: http://jsbin.com/EyuKase/1/edit?js,output\n // FIXME: make this an option?\n if (node.data.trim() === ''\n && ((node.previousElementSibling && isBlockElement(node.previousElementSibling))\n || (node.nextElementSibling && isBlockElement(node.nextElementSibling)))) {\n parentNode.removeChild(node);\n this._sanitize(parentNode);\n break;\n } else {\n continue;\n }\n }\n\n // Remove all comments\n if (node.nodeType === Node.COMMENT_NODE) {\n parentNode.removeChild(node);\n this._sanitize(parentNode);\n break;\n }\n\n var isInline = isInlineElement(node);\n var containsBlockElement;\n if (isInline) {\n containsBlockElement = Array.prototype.some.call(node.childNodes, isBlockElement);\n }\n\n // Block elements should not be nested (e.g. ...); if\n // they are, we want to unwrap the inner block element.\n var isNotTopContainer = !! parentNode.parentNode;\n var isNestedBlockElement =\n isBlockElement(parentNode) &&\n isBlockElement(node) &&\n isNotTopContainer;\n\n var nodeName = node.nodeName.toLowerCase();\n\n var allowedAttrs = getAllowedAttrs(this.config, nodeName, node);\n\n var isInvalid = isInline && containsBlockElement;\n\n // Drop tag entirely according to the whitelist *and* if the markup\n // is invalid.\n if (isInvalid || shouldRejectNode(node, allowedAttrs)\n || (!this.config.keepNestedBlockElements && isNestedBlockElement)) {\n // Do not keep the inner text of SCRIPT/STYLE elements.\n if (! (node.nodeName === 'SCRIPT' || node.nodeName === 'STYLE')) {\n while (node.childNodes.length > 0) {\n parentNode.insertBefore(node.childNodes[0], node);\n }\n }\n parentNode.removeChild(node);\n\n this._sanitize(parentNode);\n break;\n }\n\n // Sanitize attributes\n for (var a = 0; a < node.attributes.length; a += 1) {\n var attr = node.attributes[a];\n\n if (shouldRejectAttr(attr, allowedAttrs, node)) {\n node.removeAttribute(attr.name);\n // Shift the array to continue looping.\n a = a - 1;\n }\n }\n\n // Sanitize children\n this._sanitize(node);\n\n // Mark node as sanitized so it's ignored in future runs\n node._sanitized = true;\n } while ((node = treeWalker.nextSibling()));\n };\n\n function createTreeWalker(node) {\n return document.createTreeWalker(node,\n NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT,\n null, false);\n }\n\n function getAllowedAttrs(config, nodeName, node){\n if (typeof config.tags[nodeName] === 'function') {\n return config.tags[nodeName](node);\n } else {\n return config.tags[nodeName];\n }\n }\n\n function shouldRejectNode(node, allowedAttrs){\n if (typeof allowedAttrs === 'undefined') {\n return true;\n } else if (typeof allowedAttrs === 'boolean') {\n return !allowedAttrs;\n }\n\n return false;\n }\n\n function shouldRejectAttr(attr, allowedAttrs, node){\n var attrName = attr.name.toLowerCase();\n\n if (allowedAttrs === true){\n return false;\n } else if (typeof allowedAttrs[attrName] === 'function'){\n return !allowedAttrs[attrName](attr.value, node);\n } else if (typeof allowedAttrs[attrName] === 'undefined'){\n return true;\n } else if (allowedAttrs[attrName] === false) {\n return true;\n } else if (typeof allowedAttrs[attrName] === 'string') {\n return (allowedAttrs[attrName] !== attr.value);\n }\n\n return false;\n }\n\n return HTMLJanitor;\n\n}));\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/html-janitor/src/html-janitor.js\n// module id = 13\n// module chunks = 0","/**\n * Codex Editor Saver\n *\n * @author Codex Team\n * @version 1.1.0\n */\n\nmodule.exports = (function (saver) {\n\n let editor = codex.editor;\n\n /**\n * @public\n * Save blocks\n */\n saver.save = function () {\n\n /** Save html content of redactor to memory */\n editor.state.html = editor.nodes.redactor.innerHTML;\n\n /** Clean jsonOutput state */\n editor.state.jsonOutput = [];\n\n return saveBlocks(editor.nodes.redactor.childNodes);\n\n };\n\n /**\n * @private\n * Save each block data\n *\n * @param blocks\n * @returns {Promise.}\n */\n let saveBlocks = function (blocks) {\n\n let data = [];\n\n for(let index = 0; index < blocks.length; index++) {\n\n data.push(getBlockData(blocks[index]));\n\n }\n\n return Promise.all(data)\n .then(makeOutput)\n .catch(editor.core.log);\n\n };\n\n /** Save and validate block data */\n let getBlockData = function (block) {\n\n return saveBlockData(block)\n .then(validateBlockData)\n .catch(editor.core.log);\n\n };\n\n /**\n * @private\n * Call block`s plugin save method and return saved data\n *\n * @param block\n * @returns {Object}\n */\n let saveBlockData = function (block) {\n\n let pluginName = block.dataset.tool;\n\n /** Check for plugin existence */\n if (!editor.tools[pluginName]) {\n\n editor.core.log(`Plugin «${pluginName}» not found`, 'error');\n return {data: null, pluginName: null};\n\n }\n\n /** Check for plugin having save method */\n if (typeof editor.tools[pluginName].save !== 'function') {\n\n editor.core.log(`Plugin «${pluginName}» must have save method`, 'error');\n return {data: null, pluginName: null};\n\n }\n\n /** Result saver */\n let blockContent = block.childNodes[0],\n pluginsContent = blockContent.childNodes[0],\n position = pluginsContent.dataset.inputPosition;\n\n /** If plugin wasn't available then return data from cache */\n if ( editor.tools[pluginName].available === false ) {\n\n return Promise.resolve({data: codex.editor.state.blocks.items[position].data, pluginName});\n\n }\n\n return Promise.resolve(pluginsContent)\n .then(editor.tools[pluginName].save)\n .then(data => Object({data, pluginName}));\n\n };\n\n /**\n * Call plugin`s validate method. Return false if validation failed\n *\n * @param data\n * @param pluginName\n * @returns {Object|Boolean}\n */\n let validateBlockData = function ({data, pluginName}) {\n\n if (!data || !pluginName) {\n\n return false;\n\n }\n\n if (editor.tools[pluginName].validate) {\n\n let result = editor.tools[pluginName].validate(data);\n\n /**\n * Do not allow invalid data\n */\n if (!result) {\n\n return false;\n\n }\n\n }\n\n return {data, pluginName};\n\n\n };\n\n /**\n * Compile article output\n *\n * @param savedData\n * @returns {{time: number, version, items: (*|Array)}}\n */\n let makeOutput = function (savedData) {\n\n savedData = savedData.filter(blockData => blockData);\n\n let items = savedData.map(blockData => Object({type: blockData.pluginName, data: blockData.data}));\n\n editor.state.jsonOutput = items;\n\n return {\n id: editor.state.blocks.id || null,\n time: +new Date(),\n version: editor.version,\n items\n };\n\n };\n\n return saver;\n\n})({});\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_saver.js","/**\n *\n * Codex.Editor Transport Module\n *\n * @copyright 2017 Codex-Team\n * @version 1.2.0\n */\n\nmodule.exports = (function (transport) {\n\n let editor = codex.editor;\n\n\n /**\n * @private {Object} current XmlHttpRequest instance\n */\n var currentRequest = null;\n\n\n /**\n * @type {null} | {DOMElement} input - keeps input element in memory\n */\n transport.input = null;\n\n /**\n * @property {Object} arguments - keep plugin settings and defined callbacks\n */\n transport.arguments = null;\n\n /**\n * Prepares input element where will be files\n */\n transport.prepare = function () {\n\n let input = editor.draw.node( 'INPUT', '', { type : 'file' } );\n\n editor.listeners.add(input, 'change', editor.transport.fileSelected);\n editor.transport.input = input;\n\n };\n\n /** Clear input when files is uploaded */\n transport.clearInput = function () {\n\n /** Remove old input */\n transport.input = null;\n\n /** Prepare new one */\n transport.prepare();\n\n };\n\n /**\n * Callback for file selection\n * @param {Event} event\n */\n transport.fileSelected = function () {\n\n var input = this,\n i,\n files = input.files,\n formData = new FormData();\n\n if (editor.transport.arguments.multiple === true) {\n\n for ( i = 0; i < files.length; i++) {\n\n formData.append('files[]', files[i], files[i].name);\n\n }\n\n } else {\n\n formData.append('files', files[0], files[0].name);\n\n }\n\n currentRequest = editor.core.ajax({\n type : 'POST',\n data : formData,\n url : editor.transport.arguments.url,\n beforeSend : editor.transport.arguments.beforeSend,\n success : editor.transport.arguments.success,\n error : editor.transport.arguments.error,\n progress : editor.transport.arguments.progress\n });\n\n /** Clear input */\n transport.clearInput();\n\n };\n\n /**\n * Use plugin callbacks\n * @protected\n *\n * @param {Object} args - can have :\n * @param {String} args.url - fetch URL\n * @param {Function} args.beforeSend - function calls before sending ajax\n * @param {Function} args.success - success callback\n * @param {Function} args.error - on error handler\n * @param {Function} args.progress - xhr onprogress handler\n * @param {Boolean} args.multiple - allow select several files\n * @param {String} args.accept - adds accept attribute\n */\n transport.selectAndUpload = function (args) {\n\n transport.arguments = args;\n\n if ( args.multiple === true) {\n\n transport.input.setAttribute('multiple', 'multiple');\n\n }\n\n if ( args.accept ) {\n\n transport.input.setAttribute('accept', args.accept);\n\n }\n\n transport.input.click();\n\n };\n\n transport.abort = function () {\n\n currentRequest.abort();\n\n currentRequest = null;\n\n };\n\n return transport;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/_transport.js","\nmodule.exports = class 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\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/eventDispatcher.js","/**\n * Inline toolbar\n *\n * Contains from tools:\n * Bold, Italic, Underline and Anchor\n *\n * @author Codex Team\n * @version 1.0\n */\n\nmodule.exports = (function (inline) {\n\n let editor = codex.editor;\n\n inline.buttonsOpened = null;\n inline.actionsOpened = null;\n inline.wrappersOffset = null;\n\n /**\n * saving selection that need for execCommand for styling\n *\n */\n inline.storedSelection = null;\n\n /**\n * @protected\n *\n * Open inline toobar\n */\n inline.show = function () {\n\n var currentNode = editor.content.currentNode,\n tool = currentNode.dataset.tool,\n plugin;\n\n /**\n * tool allowed to open inline toolbar\n */\n plugin = editor.tools[tool];\n\n if (!plugin.showInlineToolbar)\n return;\n\n var selectedText = inline.getSelectionText(),\n toolbar = editor.nodes.inlineToolbar.wrapper;\n\n if (selectedText.length > 0) {\n\n /** Move toolbar and open */\n editor.toolbar.inline.move();\n\n /** Open inline toolbar */\n toolbar.classList.add('opened');\n\n /** show buttons of inline toolbar */\n editor.toolbar.inline.showButtons();\n\n }\n\n };\n\n /**\n * @protected\n *\n * Closes inline toolbar\n */\n inline.close = function () {\n\n var toolbar = editor.nodes.inlineToolbar.wrapper;\n\n toolbar.classList.remove('opened');\n\n };\n\n /**\n * @private\n *\n * Moving toolbar\n */\n inline.move = function () {\n\n if (!this.wrappersOffset) {\n\n this.wrappersOffset = this.getWrappersOffset();\n\n }\n\n var coords = this.getSelectionCoords(),\n defaultOffset = 0,\n toolbar = editor.nodes.inlineToolbar.wrapper,\n newCoordinateX,\n newCoordinateY;\n\n if (toolbar.offsetHeight === 0) {\n\n defaultOffset = 40;\n\n }\n\n newCoordinateX = coords.x - this.wrappersOffset.left;\n newCoordinateY = coords.y + window.scrollY - this.wrappersOffset.top - defaultOffset - toolbar.offsetHeight;\n\n toolbar.style.transform = `translate3D(${Math.floor(newCoordinateX)}px, ${Math.floor(newCoordinateY)}px, 0)`;\n\n /** Close everything */\n editor.toolbar.inline.closeButtons();\n editor.toolbar.inline.closeAction();\n\n };\n\n /**\n * @private\n *\n * Tool Clicked\n */\n\n inline.toolClicked = function (event, type) {\n\n /**\n * For simple tools we use default browser function\n * For more complicated tools, we should write our own behavior\n */\n switch (type) {\n case 'createLink' : editor.toolbar.inline.createLinkAction(event, type); break;\n default : editor.toolbar.inline.defaultToolAction(type); break;\n }\n\n /**\n * highlight buttons\n * after making some action\n */\n editor.nodes.inlineToolbar.buttons.childNodes.forEach(editor.toolbar.inline.hightlight);\n\n };\n\n /**\n * @private\n *\n * Saving wrappers offset in DOM\n */\n inline.getWrappersOffset = function () {\n\n var wrapper = editor.nodes.wrapper,\n offset = this.getOffset(wrapper);\n\n this.wrappersOffset = offset;\n return offset;\n\n };\n\n /**\n * @private\n *\n * Calculates offset of DOM element\n *\n * @param el\n * @returns {{top: number, left: number}}\n */\n inline.getOffset = function ( el ) {\n\n var _x = 0;\n var _y = 0;\n\n while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {\n\n _x += (el.offsetLeft + el.clientLeft);\n _y += (el.offsetTop + el.clientTop);\n el = el.offsetParent;\n\n }\n return { top: _y, left: _x };\n\n };\n\n /**\n * @private\n *\n * Calculates position of selected text\n * @returns {{x: number, y: number}}\n */\n inline.getSelectionCoords = function () {\n\n var sel = document.selection, range;\n var x = 0, y = 0;\n\n if (sel) {\n\n if (sel.type != 'Control') {\n\n range = sel.createRange();\n range.collapse(true);\n x = range.boundingLeft;\n y = range.boundingTop;\n\n }\n\n } else if (window.getSelection) {\n\n sel = window.getSelection();\n\n if (sel.rangeCount) {\n\n range = sel.getRangeAt(0).cloneRange();\n if (range.getClientRects) {\n\n range.collapse(true);\n var rect = range.getClientRects()[0];\n\n if (!rect) {\n\n return;\n\n }\n\n x = rect.left;\n y = rect.top;\n\n }\n\n }\n\n }\n return { x: x, y: y };\n\n };\n\n /**\n * @private\n *\n * Returns selected text as String\n * @returns {string}\n */\n inline.getSelectionText = function () {\n\n var selectedText = '';\n\n // all modern browsers and IE9+\n if (window.getSelection) {\n\n selectedText = window.getSelection().toString();\n\n }\n\n return selectedText;\n\n };\n\n /** Opens buttons block */\n inline.showButtons = function () {\n\n var buttons = editor.nodes.inlineToolbar.buttons;\n\n buttons.classList.add('opened');\n\n editor.toolbar.inline.buttonsOpened = true;\n\n /** highlight buttons */\n editor.nodes.inlineToolbar.buttons.childNodes.forEach(editor.toolbar.inline.hightlight);\n\n };\n\n /** Makes buttons disappear */\n inline.closeButtons = function () {\n\n var buttons = editor.nodes.inlineToolbar.buttons;\n\n buttons.classList.remove('opened');\n\n editor.toolbar.inline.buttonsOpened = false;\n\n };\n\n /** Open buttons defined action if exist */\n inline.showActions = function () {\n\n var action = editor.nodes.inlineToolbar.actions;\n\n action.classList.add('opened');\n\n editor.toolbar.inline.actionsOpened = true;\n\n };\n\n /** Close actions block */\n inline.closeAction = function () {\n\n var action = editor.nodes.inlineToolbar.actions;\n\n action.innerHTML = '';\n action.classList.remove('opened');\n editor.toolbar.inline.actionsOpened = false;\n\n };\n\n\n /**\n * Callback for keydowns in inline toolbar \"Insert link...\" input\n */\n let inlineToolbarAnchorInputKeydown_ = function (event) {\n\n if (event.keyCode != editor.core.keys.ENTER) {\n\n return;\n\n }\n\n let editable = editor.content.currentNode,\n storedSelection = editor.toolbar.inline.storedSelection;\n\n editor.toolbar.inline.restoreSelection(editable, storedSelection);\n editor.toolbar.inline.setAnchor(this.value);\n\n /**\n * Preventing events that will be able to happen\n */\n event.preventDefault();\n event.stopImmediatePropagation();\n\n editor.toolbar.inline.clearRange();\n\n };\n\n /** Action for link creation or for setting anchor */\n inline.createLinkAction = function (event) {\n\n var isActive = this.isLinkActive();\n\n var editable = editor.content.currentNode,\n storedSelection = editor.toolbar.inline.saveSelection(editable);\n\n /** Save globally selection */\n editor.toolbar.inline.storedSelection = storedSelection;\n\n if (isActive) {\n\n\n /**\n * Changing stored selection. if we want to remove anchor from word\n * we should remove anchor from whole word, not only selected part.\n * The solution is than we get the length of current link\n * Change start position to - end of selection minus length of anchor\n */\n editor.toolbar.inline.restoreSelection(editable, storedSelection);\n\n editor.toolbar.inline.defaultToolAction('unlink');\n\n } else {\n\n /** Create input and close buttons */\n var action = editor.draw.inputForLink();\n\n editor.nodes.inlineToolbar.actions.appendChild(action);\n\n editor.toolbar.inline.closeButtons();\n editor.toolbar.inline.showActions();\n\n /**\n * focus to input\n * Solution: https://developer.mozilla.org/ru/docs/Web/API/HTMLElement/focus\n * Prevents event after showing input and when we need to focus an input which is in unexisted form\n */\n action.focus();\n event.preventDefault();\n\n /** Callback to link action */\n editor.listeners.add(action, 'keydown', inlineToolbarAnchorInputKeydown_, false);\n\n }\n\n };\n\n inline.isLinkActive = function () {\n\n var isActive = false;\n\n editor.nodes.inlineToolbar.buttons.childNodes.forEach(function (tool) {\n\n var dataType = tool.dataset.type;\n\n if (dataType == 'link' && tool.classList.contains('hightlighted')) {\n\n isActive = true;\n\n }\n\n });\n\n return isActive;\n\n };\n\n /** default action behavior of tool */\n inline.defaultToolAction = function (type) {\n\n document.execCommand(type, false, null);\n\n };\n\n /**\n * @private\n *\n * Sets URL\n *\n * @param {String} url - URL\n */\n inline.setAnchor = function (url) {\n\n document.execCommand('createLink', false, url);\n\n /** Close after URL inserting */\n editor.toolbar.inline.closeAction();\n\n };\n\n /**\n * @private\n *\n * Saves selection\n */\n inline.saveSelection = function (containerEl) {\n\n var range = window.getSelection().getRangeAt(0),\n preSelectionRange = range.cloneRange(),\n start;\n\n preSelectionRange.selectNodeContents(containerEl);\n preSelectionRange.setEnd(range.startContainer, range.startOffset);\n\n start = preSelectionRange.toString().length;\n\n return {\n start: start,\n end: start + range.toString().length\n };\n\n };\n\n /**\n * @private\n *\n * Sets to previous selection (Range)\n *\n * @param {Element} containerEl - editable element where we restore range\n * @param {Object} savedSel - range basic information to restore\n */\n inline.restoreSelection = function (containerEl, savedSel) {\n\n var range = document.createRange(),\n charIndex = 0;\n\n range.setStart(containerEl, 0);\n range.collapse(true);\n\n var nodeStack = [ containerEl ],\n node,\n foundStart = false,\n stop = false,\n nextCharIndex;\n\n while (!stop && (node = nodeStack.pop())) {\n\n if (node.nodeType == 3) {\n\n nextCharIndex = charIndex + node.length;\n\n if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {\n\n range.setStart(node, savedSel.start - charIndex);\n foundStart = true;\n\n }\n if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {\n\n range.setEnd(node, savedSel.end - charIndex);\n stop = true;\n\n }\n charIndex = nextCharIndex;\n\n } else {\n\n var i = node.childNodes.length;\n\n while (i--) {\n\n nodeStack.push(node.childNodes[i]);\n\n }\n\n }\n\n }\n\n var sel = window.getSelection();\n\n sel.removeAllRanges();\n sel.addRange(range);\n\n };\n\n /**\n * @private\n *\n * Removes all ranges from window selection\n */\n inline.clearRange = function () {\n\n var selection = window.getSelection();\n\n selection.removeAllRanges();\n\n };\n\n /**\n * @private\n *\n * sets or removes hightlight\n */\n inline.hightlight = function (tool) {\n\n var dataType = tool.dataset.type;\n\n if (document.queryCommandState(dataType)) {\n\n editor.toolbar.inline.setButtonHighlighted(tool);\n\n } else {\n\n editor.toolbar.inline.removeButtonsHighLight(tool);\n\n }\n\n /**\n *\n * hightlight for anchors\n */\n var selection = window.getSelection(),\n tag = selection.anchorNode.parentNode;\n\n if (tag.tagName == 'A' && dataType == 'link') {\n\n editor.toolbar.inline.setButtonHighlighted(tool);\n\n }\n\n };\n\n /**\n * @private\n *\n * Mark button if text is already executed\n */\n inline.setButtonHighlighted = function (button) {\n\n button.classList.add('hightlighted');\n\n /** At link tool we also change icon */\n if (button.dataset.type == 'link') {\n\n var icon = button.childNodes[0];\n\n icon.classList.remove('ce-icon-link');\n icon.classList.add('ce-icon-unlink');\n\n }\n\n };\n\n /**\n * @private\n *\n * Removes hightlight\n */\n inline.removeButtonsHighLight = function (button) {\n\n button.classList.remove('hightlighted');\n\n /** At link tool we also change icon */\n if (button.dataset.type == 'link') {\n\n var icon = button.childNodes[0];\n\n icon.classList.remove('ce-icon-unlink');\n icon.classList.add('ce-icon-link');\n\n }\n\n };\n\n\n return inline;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/toolbar/inline.js","/**\n * Toolbar settings\n *\n * @version 1.0.5\n */\n\nmodule.exports = (function (settings) {\n\n let editor = codex.editor;\n\n settings.opened = false;\n\n settings.setting = null;\n settings.actions = null;\n\n /**\n * Append and open settings\n */\n settings.open = function (toolType) {\n\n /**\n * Append settings content\n * It's stored in tool.settings\n */\n if ( !editor.tools[toolType] || !editor.tools[toolType].makeSettings ) {\n\n return;\n\n }\n\n /**\n * Draw settings block\n */\n var settingsBlock = editor.tools[toolType].makeSettings();\n\n editor.nodes.pluginSettings.appendChild(settingsBlock);\n\n\n /** Open settings block */\n editor.nodes.blockSettings.classList.add('opened');\n this.opened = true;\n\n };\n\n /**\n * Close and clear settings\n */\n settings.close = function () {\n\n editor.nodes.blockSettings.classList.remove('opened');\n editor.nodes.pluginSettings.innerHTML = '';\n\n this.opened = false;\n\n };\n\n /**\n * @param {string} toolType - plugin type\n */\n settings.toggle = function ( toolType ) {\n\n if ( !this.opened ) {\n\n this.open(toolType);\n\n } else {\n\n this.close();\n\n }\n\n };\n\n /**\n * Here we will draw buttons and add listeners to components\n */\n settings.makeRemoveBlockButton = function () {\n\n var removeBlockWrapper = editor.draw.node('SPAN', 'ce-toolbar__remove-btn', {}),\n settingButton = editor.draw.node('SPAN', 'ce-toolbar__remove-setting', { innerHTML : '' }),\n actionWrapper = editor.draw.node('DIV', 'ce-toolbar__remove-confirmation', {}),\n confirmAction = editor.draw.node('DIV', 'ce-toolbar__remove-confirm', { textContent : 'Удалить блок' }),\n cancelAction = editor.draw.node('DIV', 'ce-toolbar__remove-cancel', { textContent : 'Отмена' });\n\n editor.listeners.add(settingButton, 'click', editor.toolbar.settings.removeButtonClicked, false);\n\n editor.listeners.add(confirmAction, 'click', editor.toolbar.settings.confirmRemovingRequest, false);\n\n editor.listeners.add(cancelAction, 'click', editor.toolbar.settings.cancelRemovingRequest, false);\n\n actionWrapper.appendChild(confirmAction);\n actionWrapper.appendChild(cancelAction);\n\n removeBlockWrapper.appendChild(settingButton);\n removeBlockWrapper.appendChild(actionWrapper);\n\n /** Save setting */\n editor.toolbar.settings.setting = settingButton;\n editor.toolbar.settings.actions = actionWrapper;\n\n return removeBlockWrapper;\n\n };\n\n settings.removeButtonClicked = function () {\n\n var action = editor.toolbar.settings.actions;\n\n if (action.classList.contains('opened')) {\n\n editor.toolbar.settings.hideRemoveActions();\n\n } else {\n\n editor.toolbar.settings.showRemoveActions();\n\n }\n\n editor.toolbar.toolbox.close();\n editor.toolbar.settings.close();\n\n };\n\n settings.cancelRemovingRequest = function () {\n\n editor.toolbar.settings.actions.classList.remove('opened');\n\n };\n\n settings.confirmRemovingRequest = function () {\n\n var currentBlock = editor.content.currentNode,\n firstLevelBlocksCount;\n\n currentBlock.remove();\n\n firstLevelBlocksCount = editor.nodes.redactor.childNodes.length;\n\n /**\n * If all blocks are removed\n */\n if (firstLevelBlocksCount === 0) {\n\n /** update currentNode variable */\n editor.content.currentNode = null;\n\n /** Inserting new empty initial block */\n editor.ui.addInitialBlock();\n\n }\n\n editor.ui.saveInputs();\n\n editor.toolbar.close();\n\n };\n\n settings.showRemoveActions = function () {\n\n editor.toolbar.settings.actions.classList.add('opened');\n\n };\n\n settings.hideRemoveActions = function () {\n\n editor.toolbar.settings.actions.classList.remove('opened');\n\n };\n\n return settings;\n\n})({});\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/toolbar/settings.js","/**\n * Codex Editor toolbar module\n *\n * Contains:\n * - Inline toolbox\n * - Toolbox within plus button\n * - Settings section\n *\n * @author Codex Team\n * @version 1.0\n */\n\nmodule.exports = (function (toolbar) {\n\n let editor = codex.editor;\n\n toolbar.settings = require('./settings');\n toolbar.inline = require('./inline');\n toolbar.toolbox = require('./toolbox');\n\n /**\n * Margin between focused node and toolbar\n */\n toolbar.defaultToolbarHeight = 49;\n\n toolbar.defaultOffset = 34;\n\n toolbar.opened = false;\n\n toolbar.current = null;\n\n /**\n * @protected\n */\n toolbar.open = function () {\n\n if (editor.hideToolbar) {\n\n return;\n\n }\n\n let toolType = editor.content.currentNode.dataset.tool;\n\n if (!editor.tools[toolType] || !editor.tools[toolType].makeSettings ) {\n\n editor.nodes.showSettingsButton.classList.add('hide');\n\n } else {\n\n editor.nodes.showSettingsButton.classList.remove('hide');\n\n }\n\n editor.nodes.toolbar.classList.add('opened');\n this.opened = true;\n\n };\n\n /**\n * @protected\n */\n toolbar.close = function () {\n\n editor.nodes.toolbar.classList.remove('opened');\n\n toolbar.opened = false;\n toolbar.current = null;\n\n for (var button in editor.nodes.toolbarButtons) {\n\n editor.nodes.toolbarButtons[button].classList.remove('selected');\n\n }\n\n /** Close toolbox when toolbar is not displayed */\n editor.toolbar.toolbox.close();\n editor.toolbar.settings.close();\n\n };\n\n toolbar.toggle = function () {\n\n if ( !this.opened ) {\n\n this.open();\n\n } else {\n\n this.close();\n\n }\n\n };\n\n toolbar.hidePlusButton = function () {\n\n editor.nodes.plusButton.classList.add('hide');\n\n };\n\n toolbar.showPlusButton = function () {\n\n editor.nodes.plusButton.classList.remove('hide');\n\n };\n\n /**\n * Moving toolbar to the specified node\n */\n toolbar.move = function () {\n\n /** Close Toolbox when we move toolbar */\n editor.toolbar.toolbox.close();\n\n if (!editor.content.currentNode) {\n\n return;\n\n }\n\n var newYCoordinate = editor.content.currentNode.offsetTop - (editor.toolbar.defaultToolbarHeight / 2) + editor.toolbar.defaultOffset;\n\n editor.nodes.toolbar.style.transform = `translate3D(0, ${Math.floor(newYCoordinate)}px, 0)`;\n\n /** Close trash actions */\n editor.toolbar.settings.hideRemoveActions();\n\n };\n\n return toolbar;\n\n})({});\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/toolbar/toolbar.js","/**\n * Codex Editor toolbox\n *\n * All tools be able to appended here\n *\n * @author Codex Team\n * @version 1.0\n */\n\nmodule.exports = (function (toolbox) {\n\n let editor = codex.editor;\n\n toolbox.opened = false;\n toolbox.openedOnBlock = null;\n\n /** Shows toolbox */\n toolbox.open = function () {\n\n /** Close setting if toolbox is opened */\n if (editor.toolbar.settings.opened) {\n\n editor.toolbar.settings.close();\n\n }\n\n /** Add 'toolbar-opened' class for current block **/\n toolbox.openedOnBlock = editor.content.currentNode;\n toolbox.openedOnBlock.classList.add('toolbar-opened');\n\n /** display toolbox */\n editor.nodes.toolbox.classList.add('opened');\n\n /** Animate plus button */\n editor.nodes.plusButton.classList.add('clicked');\n\n /** toolbox state */\n editor.toolbar.toolbox.opened = true;\n\n };\n\n /** Closes toolbox */\n toolbox.close = function () {\n\n /** Remove 'toolbar-opened' class from current block **/\n if (toolbox.openedOnBlock) toolbox.openedOnBlock.classList.remove('toolbar-opened');\n toolbox.openedOnBlock = null;\n\n /** Makes toolbox disappear */\n editor.nodes.toolbox.classList.remove('opened');\n\n /** Rotate plus button */\n editor.nodes.plusButton.classList.remove('clicked');\n\n /** toolbox state */\n editor.toolbar.toolbox.opened = false;\n\n editor.toolbar.current = null;\n\n };\n\n toolbox.leaf = function () {\n\n let currentTool = editor.toolbar.current,\n tools = Object.keys(editor.tools),\n barButtons = editor.nodes.toolbarButtons,\n nextToolIndex = 0,\n toolToSelect,\n visibleTool,\n tool;\n\n if ( !currentTool ) {\n\n /** Get first tool from object*/\n for(tool in editor.tools) {\n\n if (editor.tools[tool].displayInToolbox) {\n\n break;\n\n }\n\n nextToolIndex ++;\n\n }\n\n } else {\n\n nextToolIndex = (tools.indexOf(currentTool) + 1) % tools.length;\n visibleTool = tools[nextToolIndex];\n\n while (!editor.tools[visibleTool].displayInToolbox) {\n\n nextToolIndex = (nextToolIndex + 1) % tools.length;\n visibleTool = tools[nextToolIndex];\n\n }\n\n }\n\n toolToSelect = tools[nextToolIndex];\n\n for ( var button in barButtons ) {\n\n barButtons[button].classList.remove('selected');\n\n }\n\n barButtons[toolToSelect].classList.add('selected');\n editor.toolbar.current = toolToSelect;\n\n };\n\n /**\n * Transforming selected node type into selected toolbar element type\n * @param {event} event\n */\n toolbox.toolClicked = function (event) {\n\n /**\n * UNREPLACEBLE_TOOLS this types of tools are forbidden to replace even they are empty\n */\n var UNREPLACEBLE_TOOLS = ['image', 'link', 'list', 'instagram', 'twitter', 'embed'],\n tool = editor.tools[editor.toolbar.current],\n workingNode = editor.content.currentNode,\n currentInputIndex = editor.caret.inputIndex,\n newBlockContent,\n appendCallback,\n blockData;\n\n /** Make block from plugin */\n newBlockContent = tool.render();\n\n /** information about block */\n blockData = {\n block : newBlockContent,\n type : tool.type,\n stretched : false\n };\n\n if (\n workingNode &&\n UNREPLACEBLE_TOOLS.indexOf(workingNode.dataset.tool) === -1 &&\n workingNode.textContent.trim() === ''\n ) {\n\n /** Replace current block */\n editor.content.switchBlock(workingNode, newBlockContent, tool.type);\n\n } else {\n\n /** Insert new Block from plugin */\n editor.content.insertBlock(blockData);\n\n /** increase input index */\n currentInputIndex++;\n\n }\n\n /** Fire tool append callback */\n appendCallback = tool.appendCallback;\n\n if (appendCallback && typeof appendCallback == 'function') {\n\n appendCallback.call(event);\n\n }\n\n window.setTimeout(function () {\n\n /** Set caret to current block */\n editor.caret.setToBlock(currentInputIndex);\n\n }, 10);\n\n\n /**\n * Changing current Node\n */\n editor.content.workingNodeChanged();\n\n /**\n * Move toolbar when node is changed\n */\n editor.toolbar.move();\n\n };\n\n return toolbox;\n\n})({});\n\n\n// WEBPACK FOOTER //\n// ./src/components/modules/toolbar/toolbox.js","/**\n * @module Codex Editor Tools Submodule\n *\n * Creates Instances from Plugins and binds external config to the instances\n */\n\n/**\n * Load user defined tools\n * Tools must contain the following important objects:\n *\n * @typedef {Object} ToolsConfig\n * @property {String} iconClassname - this a icon in toolbar\n * @property {Boolean} displayInToolbox - will be displayed in toolbox. Default value is TRUE\n * @property {Boolean} enableLineBreaks - inserts new block or break lines. Default value is FALSE\n */\n\n/**\n * Class properties:\n *\n * @property {String} this.name - name of this module\n * @property {Array} this.toolInstances - list of tool instances\n *\n */\nmodule.exports = class Tools {\n\n static get name() {\n\n return 'tools';\n\n }\n\n /**\n * @param Editor\n * @param Editor.modules {@link CodexEditor#moduleInstances}\n * @param Editor.config {@link CodexEditor#configuration}\n */\n set state(Editor) {\n\n this.Editor = Editor;\n\n }\n\n /**\n * If config wasn't passed by user\n * @return {ToolsConfig}\n */\n get defaultConfig() {\n\n return {\n iconClassName : 'default-icon',\n displayInToolbox : false,\n enableLineBreaks : false\n };\n\n }\n\n /**\n * @constructor\n *\n * @param {ToolsConfig} config\n */\n constructor(config) {\n\n this.config = config;\n\n this.availabPlugins = {};\n this.toolInstances = [];\n\n }\n\n /**\n * Creates instances via passed or default configuration\n * @return {boolean}\n */\n prepare() {\n\n let toolConfig = this.defaultConfig;\n\n if (!this.config.hasOwnProperty('tools')) {\n\n return false;\n\n }\n\n /**\n * Preparation Decorator\n *\n * @param toolBindedPreparationFunction\n * @return {Promise}\n */\n function waitNextToolPreparation(toolBindedPreparationFunction) {\n\n return new Promise(function (resolve, reject) {\n\n toolBindedPreparationFunction()\n .then(resolve)\n .catch(function (error) {\n\n console.log('Plugin is not available because of ', error);\n\n // anyway, go ahead even plugin is not available\n resolve();\n\n });\n\n });\n\n }\n\n return new Promise(function (resolvePreparation, rejectPreparation) {\n\n let toolPreparationList = [];\n\n for(let tool of this.config.tools) {\n\n let toolName = tool.name;\n\n if (toolName in this.config.toolsConfig) {\n\n toolConfig = this.config.toolsConfig[toolName];\n\n }\n\n if (tool.prepare && typeof tool.prepare === 'function') {\n\n toolPreparationList.push(tool.prepare.bind(toolConfig));\n\n }\n\n }\n\n // continue editor initialization if non of tools doesn't need preparation\n if (toolPreparationList.length === 0) {\n\n resolvePreparation();\n\n } else {\n\n toolPreparationList.reduce(function (previousToolPrepared, currentToolReadyToPreparation, iteration) {\n\n return previousToolPrepared\n .then(() => waitNextToolPreparation(currentToolReadyToPreparation))\n .then(() => {\n\n if (iteration == toolPreparationList.length - 1) {\n\n resolvePreparation();\n\n }\n\n });\n\n }, Promise.resolve());\n\n }\n\n });\n\n /**\n * - getting class and config\n * - push to the toolinstnaces property created instances\n */\n // for(let tool in this.config.tools) {\n // let toolClass = this.config.tools[tool],\n // toolConfig;\n //\n // if (tool in this.config.toolConfig) {\n // toolConfig = this.config.toolConfig[tool];\n // } else {\n // toolConfig = this.defaultConfig;\n // }\n //\n // this.toolInstances.push(new toolClass(toolConfig));\n // }\n\n }\n\n /**\n * Returns all tools\n * @return {Array}\n */\n getTools() {\n\n return this.toolInstances;\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/components/modules/tools.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\n\n/**\n * @class\n *\n * @classdesc Makes CodeX Editor UI:\n * \n * \n * \n * \n * \n *\n * @property {EditorConfig} config - editor configuration {@link CodexEditor#configuration}\n * @property {Object} Editor - available editor modules {@link CodexEditor#moduleInstances}\n */\nmodule.exports = class UI {\n\n /**\n * Module key name\n * @returns {string}\n */\n static get name() {\n\n return 'ui';\n\n }\n\n /**\n * @constructor\n *\n * @param {EditorConfig} config\n */\n constructor( config ) {\n\n this.config = config;\n this.Editor = null;\n\n }\n\n\n /**\n * Editor modules setter\n * @param {object} Editor - available editor modules\n */\n set state(Editor) {\n\n this.Editor = Editor;\n\n }\n\n /**\n * @protected\n *\n * Making main interface\n */\n prepare() {\n\n console.log('ui prepare fired');\n\n return;\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/components/modules/ui.js"],"sourceRoot":""}
\ No newline at end of file
diff --git a/src/codex.js b/src/codex.js
index 8085ff07..bad0ac40 100644
--- a/src/codex.js
+++ b/src/codex.js
@@ -17,15 +17,16 @@
* ...
*/
+'use strict';
+
/**
- * All Editor components
+ * Require Editor modules places in components/modules dir
*/
-const modules = [
- require('./src/modules/dom'),
- require('./src/modules/core'),
- require('./src/modules/ui'),
- require('./src/modules/tools')
-];
+let modules = editorModules.map( module => {
+
+ return require('./components/modules/' + module );
+
+});
/**
* @class
@@ -52,8 +53,6 @@ module.exports = class CodexEditor {
*/
constructor(config) {
- 'use strict';
-
/**
* Configuration object
*/
@@ -139,9 +138,17 @@ module.exports = class CodexEditor {
modules.forEach( Module => {
- this.moduleInstances[Module.name] = new Module({
- config : this.configuration
- });
+ try {
+
+ this.moduleInstances[Module.name] = new Module({
+ config : this.configuration
+ });
+
+ } catch ( e ) {
+
+ console.log('Module %o skipped because %o', Module, e);
+
+ }
});
@@ -200,7 +207,6 @@ module.exports = class CodexEditor {
let prepareDecorator = module => module.prepare();
return Promise.resolve()
- .then(prepareDecorator(this.moduleInstances['core']))
.then(prepareDecorator(this.moduleInstances['ui']))
.then(prepareDecorator(this.moduleInstances['tools']))
.catch(function (error) {
diff --git a/src/modules/core.js b/src/components/core.js
similarity index 100%
rename from src/modules/core.js
rename to src/components/core.js
diff --git a/src/modules/dom.js b/src/components/dom.js
similarity index 100%
rename from src/modules/dom.js
rename to src/components/dom.js
diff --git a/src/modules/draw.js b/src/components/draw.js
similarity index 100%
rename from src/modules/draw.js
rename to src/components/draw.js
diff --git a/src/modules/anchors.js b/src/components/modules/_anchors.js
similarity index 100%
rename from src/modules/anchors.js
rename to src/components/modules/_anchors.js
diff --git a/src/modules/callbacks.js b/src/components/modules/_callbacks.js
similarity index 100%
rename from src/modules/callbacks.js
rename to src/components/modules/_callbacks.js
diff --git a/src/modules/caret.js b/src/components/modules/_caret.js
similarity index 100%
rename from src/modules/caret.js
rename to src/components/modules/_caret.js
diff --git a/src/modules/content.js b/src/components/modules/_content.js
similarity index 100%
rename from src/modules/content.js
rename to src/components/modules/_content.js
diff --git a/src/modules/destroyer.js b/src/components/modules/_destroyer.js
similarity index 100%
rename from src/modules/destroyer.js
rename to src/components/modules/_destroyer.js
diff --git a/src/modules/listeners.js b/src/components/modules/_listeners.js
similarity index 100%
rename from src/modules/listeners.js
rename to src/components/modules/_listeners.js
diff --git a/src/modules/notifications.js b/src/components/modules/_notifications.js
similarity index 100%
rename from src/modules/notifications.js
rename to src/components/modules/_notifications.js
diff --git a/src/modules/parser.js b/src/components/modules/_parser.js
similarity index 100%
rename from src/modules/parser.js
rename to src/components/modules/_parser.js
diff --git a/src/modules/paste.js b/src/components/modules/_paste.js
similarity index 100%
rename from src/modules/paste.js
rename to src/components/modules/_paste.js
diff --git a/src/modules/renderer.js b/src/components/modules/_renderer.js
similarity index 100%
rename from src/modules/renderer.js
rename to src/components/modules/_renderer.js
diff --git a/src/modules/sanitizer.js b/src/components/modules/_sanitizer.js
similarity index 100%
rename from src/modules/sanitizer.js
rename to src/components/modules/_sanitizer.js
diff --git a/src/modules/saver.js b/src/components/modules/_saver.js
similarity index 100%
rename from src/modules/saver.js
rename to src/components/modules/_saver.js
diff --git a/src/modules/transport.js b/src/components/modules/_transport.js
similarity index 100%
rename from src/modules/transport.js
rename to src/components/modules/_transport.js
diff --git a/src/modules/eventDispatcher.js b/src/components/modules/eventDispatcher.js
similarity index 93%
rename from src/modules/eventDispatcher.js
rename to src/components/modules/eventDispatcher.js
index 9a61ca5a..d8551641 100644
--- a/src/modules/eventDispatcher.js
+++ b/src/components/modules/eventDispatcher.js
@@ -1,5 +1,5 @@
-class Events {
+module.exports = class Events {
constructor() {
@@ -32,4 +32,4 @@ class Events {
}
-}
+};
diff --git a/src/modules/toolbar/inline.js b/src/components/modules/toolbar/inline.js
similarity index 100%
rename from src/modules/toolbar/inline.js
rename to src/components/modules/toolbar/inline.js
diff --git a/src/modules/toolbar/settings.js b/src/components/modules/toolbar/settings.js
similarity index 100%
rename from src/modules/toolbar/settings.js
rename to src/components/modules/toolbar/settings.js
diff --git a/src/modules/toolbar/toolbar.js b/src/components/modules/toolbar/toolbar.js
similarity index 100%
rename from src/modules/toolbar/toolbar.js
rename to src/components/modules/toolbar/toolbar.js
diff --git a/src/modules/toolbar/toolbox.js b/src/components/modules/toolbar/toolbox.js
similarity index 100%
rename from src/modules/toolbar/toolbox.js
rename to src/components/modules/toolbar/toolbox.js
diff --git a/src/modules/tools.js b/src/components/modules/tools.js
similarity index 96%
rename from src/modules/tools.js
rename to src/components/modules/tools.js
index 16ae89be..22acd0db 100644
--- a/src/modules/tools.js
+++ b/src/components/modules/tools.js
@@ -24,7 +24,9 @@
module.exports = class Tools {
static get name() {
+
return 'tools';
+
}
/**
@@ -33,7 +35,9 @@ module.exports = class Tools {
* @param Editor.config {@link CodexEditor#configuration}
*/
set state(Editor) {
+
this.Editor = Editor;
+
}
/**
@@ -41,11 +45,13 @@ module.exports = class Tools {
* @return {ToolsConfig}
*/
get defaultConfig() {
+
return {
iconClassName : 'default-icon',
displayInToolbox : false,
enableLineBreaks : false
- }
+ };
+
}
/**
@@ -54,10 +60,12 @@ module.exports = class Tools {
* @param {ToolsConfig} config
*/
constructor(config) {
+
this.config = config;
this.availabPlugins = {};
this.toolInstances = [];
+
}
/**
@@ -69,7 +77,9 @@ module.exports = class Tools {
let toolConfig = this.defaultConfig;
if (!this.config.hasOwnProperty('tools')) {
+
return false;
+
}
/**
@@ -80,32 +90,41 @@ module.exports = class Tools {
*/
function waitNextToolPreparation(toolBindedPreparationFunction) {
- return new Promise(function(resolve, reject) {
+ return new Promise(function (resolve, reject) {
+
toolBindedPreparationFunction()
.then(resolve)
- .catch(function(error) {
+ .catch(function (error) {
+
console.log('Plugin is not available because of ', error);
// anyway, go ahead even plugin is not available
resolve();
+
});
+
});
}
- return new Promise(function(resolvePreparation, rejectPreparation) {
+ return new Promise(function (resolvePreparation, rejectPreparation) {
let toolPreparationList = [];
+
for(let tool of this.config.tools) {
let toolName = tool.name;
if (toolName in this.config.toolsConfig) {
+
toolConfig = this.config.toolsConfig[toolName];
+
}
if (tool.prepare && typeof tool.prepare === 'function') {
+
toolPreparationList.push(tool.prepare.bind(toolConfig));
+
}
}
@@ -117,14 +136,16 @@ module.exports = class Tools {
} else {
- toolPreparationList.reduce(function(previousToolPrepared, currentToolReadyToPreparation, iteration) {
+ toolPreparationList.reduce(function (previousToolPrepared, currentToolReadyToPreparation, iteration) {
return previousToolPrepared
.then(() => waitNextToolPreparation(currentToolReadyToPreparation))
.then(() => {
if (iteration == toolPreparationList.length - 1) {
+
resolvePreparation();
+
}
});
@@ -159,7 +180,9 @@ module.exports = class Tools {
* @return {Array}
*/
getTools() {
+
return this.toolInstances;
+
}
};
diff --git a/src/modules/ui.js b/src/components/modules/ui.js
similarity index 94%
rename from src/modules/ui.js
rename to src/components/modules/ui.js
index 9159967f..41bcc5b8 100644
--- a/src/modules/ui.js
+++ b/src/components/modules/ui.js
@@ -1,4 +1,4 @@
-/**
+ /**
* Module UI
*
* @type {UI}
@@ -36,6 +36,20 @@ let CSS_ = {
editorZone : 'ce-redactor'
};
+
+/**
+ * @class
+ *
+ * @classdesc Makes CodeX Editor UI:
+ *
+ *
+ *
+ *
+ *
+ *
+ * @property {EditorConfig} config - editor configuration {@link CodexEditor#configuration}
+ * @property {Object} Editor - available editor modules {@link CodexEditor#moduleInstances}
+ */
module.exports = class UI {
/**
@@ -46,26 +60,24 @@ module.exports = class UI {
return 'ui';
- };
-
- constructor(Editor) {
-
- this.wrapper = null;
-
- // this.Editor = Editor;
- //
- // this.modules = this.Editor.modules;
+ }
+ /**
+ * @constructor
+ *
+ * @param {EditorConfig} config
+ */
+ constructor( config ) {
+ this.config = config;
+ this.Editor = null;
}
/**
- * @param Editor
- * @param Editor.modules {@link Tools#list}
- * @param Editor.config {@link CodexEditor#configuration}
- * @param Editor
+ * Editor modules setter
+ * @param {object} Editor - available editor modules
*/
set state(Editor) {
@@ -80,12 +92,8 @@ module.exports = class UI {
*/
prepare() {
-
-
console.log('ui prepare fired');
- this.wrapper = document.createElement('div');
-
return;
return new Promise(function (resolve, reject) {
diff --git a/webpack.config.js b/webpack.config.js
index 805431d1..38b8b226 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -23,12 +23,28 @@ const VERSION = process.env.VERSION || pkg.version;
var webpack = require('webpack');
var ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
+var fs = require('fs');
+
+/**
+ * Available CodeX Editor modules placed in components/modules folder
+ * They will required automatically.
+ * Folders and files starting with '_' will be skipped
+ * @type {Array}
+ */
+var editorModules = fs.readdirSync('./src/components/modules').filter( name => /.js$/.test(name) && name.substring(0,1) !== '_' );
+
+editorModules.forEach( name => {
+ console.log('Require modules/' + name);
+});
+
+
module.exports = {
entry: {
- 'codex-editor': './codex'
+ 'codex-editor': './src/codex'
},
output: {
+ path: path.resolve(__dirname, 'build'),
filename: '[name].js',
library: [ 'CodexEditor' ]
},
@@ -58,7 +74,8 @@ module.exports = {
/** Pass variables into modules */
new webpack.DefinePlugin({
NODE_ENV: JSON.stringify(NODE_ENV),
- VERSION: JSON.stringify(VERSION)
+ VERSION: JSON.stringify(VERSION),
+ editorModules: JSON.stringify(editorModules)
}),
/** Минифицируем CSS и JS */