event dispatchers

This commit is contained in:
Murod Khaydarov 2017-11-09 20:37:36 +03:00
commit 440de55824
26 changed files with 979 additions and 5614 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

124
codex.js
View file

@ -1,8 +1,10 @@
/**
*
* Codex Editor
*
* @author Codex Team
*
*
*
* @author CodeX Team
*/
module.exports = class CodexEditor {
@ -24,36 +26,18 @@ module.exports = class CodexEditor {
* @param config
*
* @property this.configuration - editor instance configuration
* @property this.instances - editor module instances
* @property this.moduleInstances - editor module instances
*/
constructor(config) {
'use strict';
this.configuration = config;
this.instances = [];
this.moduleInstances = [];
let modules = [
'core',
'tools',
'transport',
'renderer',
'saver',
'content',
'toolbar/toolbar',
'callbacks',
'draw',
'caret',
'notifications',
'parser',
'sanitizer',
'listeners',
'destroyer',
'paste'
],
modulePath = './modules/';
this.eventsDispatcher = new Events();
this.init(modulePath);
this.init();
}
@ -61,39 +45,81 @@ module.exports = class CodexEditor {
* Initializes modules:
* First: requiring modules from path
* Second: memorizing the instances
*
* @param {String} module name
* @param {String} module path
*/
init(path) {
init() {
let core = require('./modules/core'),
tools = require('./modules/tools'),
transport = require('./modules/transport'),
renderer = require('./modules/renderer'),
saver = require('./modules/saver'),
content = require('./modules/content'),
toolbar = require('./modules/toolbar/toolbar'),
callbacks = require('./modules/callbacks'),
draw = require('./modules/draw'),
caret = require('./modules/caret'),
notifications = require('./modules/notifications'),
parser = require('./modules/parser'),
sanitizer = require('./modules/sanitizer'),
listeners = require('./modules/listeners'),
destroyer = require('./modules/destroyer'),
paste = require('./modules/paste');
let core = require('./src/modules/core');
// tools = require('./src/modules/tools'),
// transport = require('./src/modules/transport'),
// renderer = require('./src/modules/renderer'),
// saver = require('./src/modules/saver'),
// content = require('./src/modules/content'),
// toolbar = require('./src/modules/toolbar/toolbar'),
// callbacks = require('./src/modules/callbacks'),
// draw = require('./src/modules/draw'),
// caret = require('./src/modules/caret'),
// notifications = require('./src/modules/notifications'),
// parser = require('./src/modules/parser'),
// sanitizer = require('./src/modules/sanitizer'),
// listeners = require('./src/modules/listeners'),
// destroyer = require('./src/modules/destroyer'),
// paste = require('./src/modules/paste');
this.instances['core'] = core;
this.instances['tools'] = tools;
console.log('Class', this);
this.moduleInstances['core'] = new core({ eventDispatcher : this.eventsDispatcher});
// this.moduleInstances['tools'] = tools;
// this.moduleInstances['transport'] = transport;
// this.moduleInstances['renderer'] = renderer;
// this.moduleInstances['saver'] = saver;
// this.moduleInstances['content'] = content;
// this.moduleInstances['toolbar'] = toolbar;
// this.moduleInstances['callbacks'] = callbacks;
// this.moduleInstances['draw'] = draw;
// this.moduleInstances['caret'] = caret;
// this.moduleInstances['notifications'] = notifications;
// this.moduleInstances['parser'] = parser;
// this.moduleInstances['sanitizer'] = sanitizer;
// this.moduleInstances['listeners'] = listeners;
// this.moduleInstances['destroyer'] = destroyer;
// this.moduleInstances['paste'] = paste;
}
};
class Events {
constructor() {
this.subscribers = {};
}
on(eventName, callback) {
if (!(eventName in this.subscribers)) {
this.subscribers[eventName] = [];
}
// group by events
this.subscribers[eventName].push(callback);
}
emit(eventName, data) {
this.subscribers[eventName].reduce(function (previousData, currentHandler) {
currentHandler(previousData);
return previousData;
}, data);
}
}
// module.exports = (function (editor) {
//
// 'use strict';

View file

@ -64,10 +64,10 @@
inittialBlock : 'paragraph'
});
var editor2 = new CodexEditor({
holderId : 'cdx',
initialBlock: 'header'
});
// var editor2 = new CodexEditor({
// holderId : 'cdx',
// initialBlock: 'header'
// });
// codex.editor.start({
// holderId : "codex-editor",
// initialBlockPlugin : 'paragraph',

View file

@ -1,389 +0,0 @@
/**
* Codex Editor Core
*
* @author Codex Team
* @version 1.1.3
*/
module.exports = (function (core) {
let editor = codex.editor;
/**
* @public
*
* Editor preparing method
* @return Promise
*/
core.prepare = function (userSettings) {
return new Promise(function (resolve, reject) {
if ( userSettings ) {
editor.settings.tools = userSettings.tools || editor.settings.tools;
}
if (userSettings.data) {
editor.state.blocks = userSettings.data;
}
if (userSettings.initialBlockPlugin) {
editor.settings.initialBlockPlugin = userSettings.initialBlockPlugin;
}
if (userSettings.sanitizer) {
editor.settings.sanitizer = userSettings.sanitizer;
}
editor.hideToolbar = userSettings.hideToolbar;
editor.settings.placeholder = userSettings.placeholder || '';
editor.nodes.holder = document.getElementById(userSettings.holderId || editor.settings.holderId);
if (typeof editor.nodes.holder === undefined || editor.nodes.holder === null) {
reject(Error("Holder wasn't found by ID: #" + userSettings.holderId));
} else {
resolve();
}
});
};
/**
* Logging method
* @param type = ['log', 'info', 'warn']
*/
core.log = function (msg, type, arg) {
type = type || 'log';
if (!arg) {
arg = msg || 'undefined';
msg = '[codex-editor]: %o';
} else {
msg = '[codex-editor]: ' + msg;
}
try{
if ( 'console' in window && window.console[ type ] ) {
if ( arg ) window.console[ type ]( msg, arg );
else window.console[ type ]( msg );
}
}catch(e) {}
};
/**
* @protected
*
* Helper for insert one element after another
*/
core.insertAfter = function (target, element) {
target.parentNode.insertBefore(element, target.nextSibling);
};
/**
* @const
*
* Readable DOM-node types map
*/
core.nodeTypes = {
TAG : 1,
TEXT : 3,
COMMENT : 8,
DOCUMENT_FRAGMENT: 11
};
/**
* @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 };
/**
* @protected
*
* Check object for DOM node
*/
core.isDomNode = function (el) {
return el && typeof el === 'object' && el.nodeType && el.nodeType == this.nodeTypes.TAG;
};
/**
* Checks passed object for emptiness
* @require ES5 - Object.keys
* @param {object}
*/
core.isEmpty = function ( obj ) {
return Object.keys(obj).length === 0;
};
/**
* Native Ajax
* @param {String} settings.url - request URL
* @param {function} settings.beforeSend - returned value will be passed as context to the Success, Error and Progress callbacks
* @param {function} settings.success
* @param {function} settings.progress
*/
core.ajax = function (settings) {
if (!settings || !settings.url) {
return;
}
var XMLHTTP = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'),
encodedString,
isFormData,
prop;
settings.async = true;
settings.type = settings.type || 'GET';
settings.data = settings.data || '';
settings['content-type'] = settings['content-type'] || 'application/json; charset=utf-8';
if (settings.type == 'GET' && settings.data) {
settings.url = /\?/.test(settings.url) ? settings.url + '&' + settings.data : settings.url + '?' + settings.data;
} else {
encodedString = '';
for(prop in settings.data) {
encodedString += (prop + '=' + encodeURIComponent(settings.data[prop]) + '&');
}
}
if (settings.withCredentials) {
XMLHTTP.withCredentials = true;
}
/**
* Value returned in beforeSend funtion will be passed as context to the other response callbacks
* If beforeSend returns false, AJAX will be blocked
*/
let responseContext,
beforeSendResult;
if (typeof settings.beforeSend === 'function') {
beforeSendResult = settings.beforeSend.call();
if (beforeSendResult === false) {
return;
}
}
XMLHTTP.open( settings.type, settings.url, settings.async );
/**
* If we send FormData, we need no content-type header
*/
isFormData = isFormData_(settings.data);
if (!isFormData) {
if (settings.type !== 'POST') {
XMLHTTP.setRequestHeader('Content-type', settings['content-type']);
} else {
XMLHTTP.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
}
}
XMLHTTP.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
responseContext = beforeSendResult || XMLHTTP;
if (typeof settings.progress === 'function') {
XMLHTTP.upload.onprogress = settings.progress.bind(responseContext);
}
XMLHTTP.onreadystatechange = function () {
if (XMLHTTP.readyState === 4) {
if (XMLHTTP.status === 200) {
if (typeof settings.success === 'function') {
settings.success.call(responseContext, XMLHTTP.responseText);
}
} else {
if (typeof settings.error === 'function') {
settings.error.call(responseContext, XMLHTTP.responseText, XMLHTTP.status);
}
}
}
};
if (isFormData) {
// Sending FormData
XMLHTTP.send(settings.data);
} else {
// POST requests
XMLHTTP.send(encodedString);
}
return XMLHTTP;
};
/**
* Appends script to head of document
* @return Promise
*/
core.importScript = function (scriptPath, instanceName) {
return new Promise(function (resolve, reject) {
let script;
/** Script is already loaded */
if ( !instanceName ) {
reject('Instance name is missed');
} else if ( document.getElementById(editor.scriptPrefix + instanceName) ) {
resolve(scriptPath);
}
script = document.createElement('SCRIPT');
script.async = true;
script.defer = true;
script.id = editor.scriptPrefix + instanceName;
script.onload = function () {
resolve(scriptPath);
};
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) {
return object instanceof FormData;
};
/**
* Check block
* @param target
* @description Checks target is it native input
*/
core.isNativeInput = function (target) {
var nativeInputAreas = ['INPUT', 'TEXTAREA'];
return nativeInputAreas.indexOf(target.tagName) != -1;
};
/**
* 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) {
const EXCEPTION_TAGS = ['IMG', 'IFRAME'];
var nativeInputs = block.querySelectorAll('textarea, input'),
nativeInputsAreEmpty = true,
textContentIsEmpty = !block.textContent.trim();
Array.prototype.forEach.call(nativeInputs, function (input) {
if (input.type == 'textarea' || input.type == 'text') {
nativeInputsAreEmpty = nativeInputsAreEmpty && !input.value.trim();
}
});
return textContentIsEmpty && nativeInputsAreEmpty && !EXCEPTION_TAGS.includes(block.tagName);
};
return core;
})({});

412
src/modules/core.js Normal file
View file

@ -0,0 +1,412 @@
/**
* Codex Editor Core
*
* @author Codex Team
* @version 1.1.3
*/
module.exports = class Core {
constructor({ eventDispatcher}) {
this.eventDispatcher = eventDispatcher;
this.data = [1, 2, 3];
this.init();
}
init() {
this.eventDispatcher.on('Editor proccessing...', function (data) {
console.log('Function fired when editor started proccess');
});
this.eventDispatcher.emit('Editor proccessing...', this.data);
}
};
// module.exports = (function (core) {
//
// let editor = codex.editor;
//
// /**
// * @public
// *
// * Editor preparing method
// * @return Promise
// */
// core.prepare = function (userSettings) {
//
// return new Promise(function (resolve, reject) {
//
// if ( userSettings ) {
//
// editor.settings.tools = userSettings.tools || editor.settings.tools;
//
// }
//
// if (userSettings.data) {
//
// editor.state.blocks = userSettings.data;
//
// }
//
// if (userSettings.initialBlockPlugin) {
//
// editor.settings.initialBlockPlugin = userSettings.initialBlockPlugin;
//
// }
//
// if (userSettings.sanitizer) {
//
// editor.settings.sanitizer = userSettings.sanitizer;
//
// }
//
// editor.hideToolbar = userSettings.hideToolbar;
//
// editor.settings.placeholder = userSettings.placeholder || '';
//
// editor.nodes.holder = document.getElementById(userSettings.holderId || editor.settings.holderId);
//
// if (typeof editor.nodes.holder === undefined || editor.nodes.holder === null) {
//
// reject(Error("Holder wasn't found by ID: #" + userSettings.holderId));
//
// } else {
//
// resolve();
//
// }
//
// });
//
// };
//
// /**
// * Logging method
// * @param type = ['log', 'info', 'warn']
// */
// core.log = function (msg, type, arg) {
//
// type = type || 'log';
//
// if (!arg) {
//
// arg = msg || 'undefined';
// msg = '[codex-editor]: %o';
//
// } else {
//
// msg = '[codex-editor]: ' + msg;
//
// }
//
// try{
//
// if ( 'console' in window && window.console[ type ] ) {
//
// if ( arg ) window.console[ type ]( msg, arg );
// else window.console[ type ]( msg );
//
// }
//
// }catch(e) {}
//
// };
//
// /**
// * @protected
// *
// * Helper for insert one element after another
// */
// core.insertAfter = function (target, element) {
//
// target.parentNode.insertBefore(element, target.nextSibling);
//
// };
//
// /**
// * @const
// *
// * Readable DOM-node types map
// */
// core.nodeTypes = {
// TAG : 1,
// TEXT : 3,
// COMMENT : 8,
// DOCUMENT_FRAGMENT: 11
// };
//
// /**
// * @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 };
//
// /**
// * @protected
// *
// * Check object for DOM node
// */
// core.isDomNode = function (el) {
//
// return el && typeof el === 'object' && el.nodeType && el.nodeType == this.nodeTypes.TAG;
//
// };
//
// /**
// * Checks passed object for emptiness
// * @require ES5 - Object.keys
// * @param {object}
// */
// core.isEmpty = function ( obj ) {
//
// return Object.keys(obj).length === 0;
//
// };
//
// /**
// * Native Ajax
// * @param {String} settings.url - request URL
// * @param {function} settings.beforeSend - returned value will be passed as context to the Success, Error and Progress callbacks
// * @param {function} settings.success
// * @param {function} settings.progress
// */
// core.ajax = function (settings) {
//
// if (!settings || !settings.url) {
//
// return;
//
// }
//
// var XMLHTTP = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'),
// encodedString,
// isFormData,
// prop;
//
//
// settings.async = true;
// settings.type = settings.type || 'GET';
// settings.data = settings.data || '';
// settings['content-type'] = settings['content-type'] || 'application/json; charset=utf-8';
//
// if (settings.type == 'GET' && settings.data) {
//
// settings.url = /\?/.test(settings.url) ? settings.url + '&' + settings.data : settings.url + '?' + settings.data;
//
// } else {
//
// encodedString = '';
// for(prop in settings.data) {
//
// encodedString += (prop + '=' + encodeURIComponent(settings.data[prop]) + '&');
//
// }
//
// }
//
// if (settings.withCredentials) {
//
// XMLHTTP.withCredentials = true;
//
// }
//
// /**
// * Value returned in beforeSend funtion will be passed as context to the other response callbacks
// * If beforeSend returns false, AJAX will be blocked
// */
// let responseContext,
// beforeSendResult;
//
// if (typeof settings.beforeSend === 'function') {
//
// beforeSendResult = settings.beforeSend.call();
//
// if (beforeSendResult === false) {
//
// return;
//
// }
//
// }
//
// XMLHTTP.open( settings.type, settings.url, settings.async );
//
// /**
// * If we send FormData, we need no content-type header
// */
// isFormData = isFormData_(settings.data);
//
// if (!isFormData) {
//
// if (settings.type !== 'POST') {
//
// XMLHTTP.setRequestHeader('Content-type', settings['content-type']);
//
// } else {
//
// XMLHTTP.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
//
// }
//
// }
//
// XMLHTTP.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
//
// responseContext = beforeSendResult || XMLHTTP;
//
// if (typeof settings.progress === 'function') {
//
// XMLHTTP.upload.onprogress = settings.progress.bind(responseContext);
//
// }
//
// XMLHTTP.onreadystatechange = function () {
//
// if (XMLHTTP.readyState === 4) {
//
// if (XMLHTTP.status === 200) {
//
// if (typeof settings.success === 'function') {
//
// settings.success.call(responseContext, XMLHTTP.responseText);
//
// }
//
// } else {
//
// if (typeof settings.error === 'function') {
//
// settings.error.call(responseContext, XMLHTTP.responseText, XMLHTTP.status);
//
// }
//
// }
//
// }
//
// };
//
// if (isFormData) {
//
// // Sending FormData
// XMLHTTP.send(settings.data);
//
// } else {
//
// // POST requests
// XMLHTTP.send(encodedString);
//
// }
//
// return XMLHTTP;
//
// };
//
// /**
// * Appends script to head of document
// * @return Promise
// */
// core.importScript = function (scriptPath, instanceName) {
//
// return new Promise(function (resolve, reject) {
//
// let script;
//
// /** Script is already loaded */
// if ( !instanceName ) {
//
// reject('Instance name is missed');
//
// } else if ( document.getElementById(editor.scriptPrefix + instanceName) ) {
//
// resolve(scriptPath);
//
// }
//
// script = document.createElement('SCRIPT');
// script.async = true;
// script.defer = true;
// script.id = editor.scriptPrefix + instanceName;
//
// script.onload = function () {
//
// resolve(scriptPath);
//
// };
//
// 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) {
//
// return object instanceof FormData;
//
// };
//
// /**
// * Check block
// * @param target
// * @description Checks target is it native input
// */
// core.isNativeInput = function (target) {
//
// var nativeInputAreas = ['INPUT', 'TEXTAREA'];
//
// return nativeInputAreas.indexOf(target.tagName) != -1;
//
// };
//
// /**
// * 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) {
//
// const EXCEPTION_TAGS = ['IMG', 'IFRAME'];
//
// var nativeInputs = block.querySelectorAll('textarea, input'),
// nativeInputsAreEmpty = true,
// textContentIsEmpty = !block.textContent.trim();
//
// Array.prototype.forEach.call(nativeInputs, function (input) {
//
// if (input.type == 'textarea' || input.type == 'text') {
//
// nativeInputsAreEmpty = nativeInputsAreEmpty && !input.value.trim();
//
// }
//
// });
//
// return textContentIsEmpty && nativeInputsAreEmpty && !EXCEPTION_TAGS.includes(block.tagName);
//
// };
//
//
// return core;
//
// })({});