updated youtube plugin

This commit is contained in:
khaydarov 2017-01-10 20:12:32 +03:00
parent 065540a782
commit fbbccaa350
25 changed files with 998 additions and 716 deletions

49
.eslintrc Normal file
View file

@ -0,0 +1,49 @@
{
"rules": {
"arrow-spacing": [2, { "before": true, "after": true }],
/** Variables */
"no-catch-shadow": 2,
"no-delete-var": 2,
"no-label-var": 2,
"no-shadow-restricted-names": 2,
"no-shadow": 2,
"no-undef-init": 2,
"no-undef": 2,
"no-unused-vars": 2,
/** Style */
"array-bracket-spacing": [2, "never", {
"singleValue": true,
"objectsInArrays": true,
"arraysInArrays": true
}],
"quotes": [2, "single", "avoid-escape"],
"eqeqeq": 0,
"brace-style": [2, "stroustrup"],
"comma-spacing": [2, { "before": false, "after": true }],
"comma-style": [2, "last"],
"eol-last": 0,
"no-nested-ternary": 1,
"no-trailing-spaces": 2,
"no-mixed-spaces-and-tabs": 2,
"padded-blocks": [2, "never"],
"space-before-blocks": 2,
"space-before-function-paren": [2, { "anonymous": "always", "named": "never" }],
"spaced-comment": [2, "always", {
"exceptions": ["-", "+"],
"markers": ["=", "!"]
}],
"semi": [2, "always"],
"indent": [2, 4, { "SwitchCase": 1 }],
"camelcase": [2, { "properties": "always" }],
"newline-after-var": [1, "always"]
},
"globals":{
"document": true,
"require": true,
"module": true,
"codex": true
}
}

View file

@ -16,6 +16,10 @@
position: relative;
}
.codex-editor .hide {
display: none;
}
/**
* Working zone - redactor
*/

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -1,12 +1,14 @@
/**
*
* Codex Editor
*
* @author Codex Team
* @version 1.0.6
* @version 1.2.5
*/
var codex = (function(codex){
var init = function() {
codex.core = require('./modules/core');
codex.ui = require('./modules/ui');
codex.transport = require('./modules/transport');
@ -22,6 +24,8 @@ var codex = (function(codex){
codex.parser = require('./modules/parser');
};
codex.version = VERSION;
/**
* @public
*

View file

@ -10,8 +10,8 @@
</body>
<script src="./codex-editor.js?v=11"></script>
<link rel="stylesheet" href="./codex-editor.css?v=11">
<script src="./codex-editor.js?v=108"></script>
<link rel="stylesheet" href="./codex-editor.css?v=11000">
<link rel="stylesheet" href="codex-editor.css">
@ -51,6 +51,8 @@
<script>
codex.start({
textareaId : "codex_area",
initialBlockPlugin : 'paragraph',
uploadImagesUrl : '/hull',
tools : {
paragraph: {
type: 'paragraph',
@ -61,7 +63,8 @@
render: paragraphTool.render,
save: paragraphTool.save,
enableLineBreaks: false,
allowedToPaste: true
allowedToPaste: true,
handleTagOnPaste : ['P']
},
paste: {
type: 'paste',
@ -84,7 +87,8 @@
settings: headerTool.makeSettings(),
render: headerTool.render,
save: headerTool.save,
displayInToolbox: true
displayInToolbox: true,
handleTagOnPaste : ['H1', 'H2', 'H3', 'H4', 'H5', 'H6']
},
code: {
type: 'code',
@ -151,7 +155,6 @@
settings: null,
render: instagramTool.reneder,
save: instagramTool.save,
displayInToolbox: false,
enableLineBreaks: false,
allowedToPaste: false
},
@ -164,7 +167,6 @@
settings: null,
render: twitterTool.render,
save: twitterTool.save,
displayInToolbox: false,
enableLineBreaks: false,
allowedToPaste: false
},

View file

@ -1,13 +1,26 @@
/**
* Codex Editor callbacks module
*
* @author Codex Team
* @version 1.2.5
*/
var callbacks = (function(callbacks) {
callbacks.redactorSyncTimeout = null;
callbacks.globalKeydown = function(event){
switch (event.keyCode){
case codex.core.keys.TAB : codex.callback.tabKeyPressed(event); break;
case codex.core.keys.ENTER : codex.callback.enterKeyPressed(event); break;
case codex.core.keys.ESC : codex.callback.escapeKeyPressed(event); break;
default : codex.callback.defaultKeyPressed(event); break;
}
};
callbacks.redactorKeyDown = function(event) {
switch (event.keyCode){
case codex.core.keys.TAB : codex.callback.tabKeyPressed(event); break;
case codex.core.keys.ENTER : codex.callback.enterKeyPressedOnRedactorZone(event); break;
case codex.core.keys.ESC : codex.callback.escapeKeyPressed(event); break;
default : codex.callback.defaultKeyPressed(event); break;
}
};
@ -35,17 +48,9 @@ var callbacks = (function(callbacks) {
event.preventDefault();
};
/**
* ENTER key handler
* Makes new paragraph block
*/
callbacks.enterKeyPressed = function(event){
callbacks.enterKeyPressed = function(event) {
/** Set current node */
var firstLevelBlocksArea = codex.callback.clickedOnFirstLevelBlockArea();
if (firstLevelBlocksArea) {
event.preventDefault();
if (codex.content.editorAreaHightlighted) {
/**
* it means that we lose input index, saved index before is not correct
@ -54,8 +59,14 @@ var callbacks = (function(callbacks) {
codex.caret.inputIndex = -1;
codex.callback.enterPressedOnBlock();
return;
}
};
/**
* ENTER key handler
* Makes new paragraph block
*/
callbacks.enterKeyPressedOnRedactorZone = function(event){
if (event.target.contentEditable == 'true') {
@ -83,7 +94,7 @@ var callbacks = (function(callbacks) {
var enableLineBreaks = codex.tools[tool].enableLineBreaks;
/** This type of block creates when enter is pressed */
var NEW_BLOCK_TYPE = 'paragraph';
var NEW_BLOCK_TYPE = codex.settings.initialBlockPlugin;
/**
* When toolbar is opened, select tool instead of making new paragraph
@ -96,6 +107,12 @@ var callbacks = (function(callbacks) {
codex.toolbar.close();
/**
* Stop other listeners callback executions
*/
event.stopPropagation();
event.stopImmediatePropagation();
return;
}
@ -217,6 +234,8 @@ var callbacks = (function(callbacks) {
callbacks.redactorClicked = function (event) {
callbacks.markWhenClickedOnFirstLevelBlockArea();
codex.content.workingNodeChanged(event.target);
codex.ui.saveInputs();
@ -252,14 +271,14 @@ var callbacks = (function(callbacks) {
}
/** If input is empty, then we set caret to the last input */
if (codex.state.inputs.length && codex.state.inputs[indexOfLastInput].textContent === '' && firstLevelBlock.dataset.tool == 'paragraph') {
if (codex.state.inputs.length && codex.state.inputs[indexOfLastInput].textContent === '' && firstLevelBlock.dataset.tool == codex.settings.initialBlockPlugin) {
codex.caret.setToBlock(indexOfLastInput);
} else {
/** Create new input when caret clicked in redactors area */
var NEW_BLOCK_TYPE = 'paragraph';
var NEW_BLOCK_TYPE = codex.settings.initialBlockPlugin;
codex.content.insertBlock({
type : NEW_BLOCK_TYPE,
@ -318,7 +337,7 @@ var callbacks = (function(callbacks) {
var currentNodeType = codex.content.currentNode.dataset.tool;
/** Mark current block*/
if (currentNodeType != 'paragraph' || !inputIsEmpty) {
if (currentNodeType != codex.settings.initialBlockPlugin || !inputIsEmpty) {
codex.content.markBlock();
@ -333,16 +352,15 @@ var callbacks = (function(callbacks) {
* 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.
*/
callbacks.clickedOnFirstLevelBlockArea = function() {
callbacks.markWhenClickedOnFirstLevelBlockArea = function() {
var selection = window.getSelection(),
anchorNode = selection.anchorNode,
flag = false;
if (selection.rangeCount == 0) {
return true;
codex.content.editorAreaHightlighted = true;
} else {
@ -368,7 +386,7 @@ var callbacks = (function(callbacks) {
}
/** If editable element founded, flag is "TRUE", Therefore we return "FALSE" */
return flag ? false : true;
codex.content.editorAreaHightlighted = flag ? false : true;
}
};
@ -597,7 +615,7 @@ var callbacks = (function(callbacks) {
*/
callbacks.enterPressedOnBlock = function (event) {
var NEW_BLOCK_TYPE = 'paragraph';
var NEW_BLOCK_TYPE = codex.settings.initialBlockPlugin;
codex.content.insertBlock({
type : NEW_BLOCK_TYPE,
@ -690,6 +708,11 @@ var callbacks = (function(callbacks) {
};
/**
* @deprecated
*
* @param event
*/
callbacks.blockPaste = function(event) {
var currentInputIndex = codex.caret.getCurrentInputIndex(),
@ -699,11 +722,15 @@ var callbacks = (function(callbacks) {
codex.content.sanitize(node);
event.preventDefault();
}, 10);
event.stopImmediatePropagation();
};
callbacks._blockPaste = function(event) {
callbacks.blockPasteViaSanitize = function(event) {
var currentInputIndex = codex.caret.getCurrentInputIndex();
@ -715,7 +742,12 @@ var callbacks = (function(callbacks) {
/**
* configuration of the observer:
*/
var config = { attributes: true, childList: true, characterData: false };
var config = {
attributes: true,
childList: true,
characterData: false,
subtree : true
};
// pass in the target node, as well as the observer options
observer.observe(codex.state.inputs[currentInputIndex], config);
@ -725,7 +757,19 @@ var callbacks = (function(callbacks) {
* Sends all mutations to paste handler
*/
callbacks.handlePasteEvents = function(mutations) {
mutations.forEach(codex.content.paste);
var self = this;
/**
* Calling function with context of this function.
* Also, we should sanitize pasted or changed data one time and ignore
* changings which makes sanitize method.
* For that, we need to send Context, MutationObserver.__proto__ that contains
* observer disconnect method.
*/
mutations.forEach(function(mutation) {
codex.content.paste.call(self, mutation);
});
};
/**

View file

@ -1,3 +1,10 @@
/**
* Codex Editor Caret Module
*
* @author Codex Team
* @version 1.0
*/
var caret = (function(caret) {
/**

View file

@ -1,7 +1,49 @@
/**
* Codex Editor Content Module
* Works with DOM
*
* @author Codex Team
* @version 1.3.1
*/
var janitor = require('html-janitor');
/**
* Default settings for sane.
* @uses html-janitor
*/
var Config = {
tags: {
p: {},
a: {
href: true,
target: '_blank',
rel: 'nofollow'
},
i: {},
b: {},
strong: {},
em: {},
span: {}
}
};
var content = (function(content) {
/**
* Links to current active block
* @type {null | Element}
*/
content.currentNode = null;
/**
* clicked in redactor area
* @type {null | Boolean}
*/
content.editorAreaHightlighted = null;
/**
* Synchronizes redactor with original textarea
*/
@ -251,6 +293,12 @@ var content = (function(content) {
}
/**
* Block is inserted, wait for new click that defined focusing on editors area
* @type {boolean}
*/
content.editorAreaHightlighted = false;
};
/**
@ -456,7 +504,7 @@ var content = (function(content) {
newNode = newNode.innerHTML;
/** This type of block creates when enter is pressed */
var NEW_BLOCK_TYPE = 'paragraph';
var NEW_BLOCK_TYPE = codex.settings.initialBlockPlugin;
/**
* Make new paragraph with text after caret
@ -509,7 +557,7 @@ var content = (function(content) {
tool = workingNode.dataset.tool;
if (codex.tools[tool].allowedToPaste) {
codex.content.sanitize(mutation.addedNodes);
codex.content.sanitize.call(this, mutation.addedNodes);
} else {
codex.content.pasteTextContent(mutation.addedNodes);
}
@ -524,8 +572,18 @@ var content = (function(content) {
*/
content.pasteTextContent = function(nodes) {
var node = nodes[0],
var node = nodes[0],
textNode;
if (!node) {
return;
}
if (node.nodeType == codex.core.nodeTypes.TEXT) {
textNode = document.createTextNode(node);
} else {
textNode = document.createTextNode(node.textContent);
}
if (codex.core.isDomNode(node)) {
node.parentNode.replaceChild(textNode, node);
@ -537,7 +595,7 @@ var content = (function(content) {
*
* Sanitizes HTML content
* @param {Element} target - inserted element
* @uses DFS function for deep searching
* @uses Sanitize library html-janitor
*/
content.sanitize = function(target) {
@ -545,85 +603,60 @@ var content = (function(content) {
return;
}
for (var i = 0; i < target.childNodes.length; i++) {
this.dfs(target.childNodes[i]);
}
};
var node = target[0];
/**
* Clears styles
* @param {Element|Text}
*/
content.clearStyles = function(target) {
var href,
newNode = null,
blockTags = ['P', 'BLOCKQUOTE', 'UL', 'CODE', 'OL', 'LI', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'DIV', 'PRE', 'HEADER', 'SECTION'],
allowedTags = ['P', 'B', 'I', 'A', 'U', 'BR'],
needReplace = !allowedTags.includes(target.tagName),
isDisplayedAsBlock = blockTags.includes(target.tagName);
if (!codex.core.isDomNode(target)){
return target;
}
if (!target.parentNode){
return target;
}
if (needReplace) {
if (isDisplayedAsBlock) {
newNode = document.createElement('P');
newNode.innerHTML = target.innerHTML;
target.parentNode.replaceChild(newNode, target);
target = newNode;
} else {
newNode = document.createTextNode(` ${target.textContent} `);
newNode.textContent = newNode.textContent.replace(/\s{2,}/g, ' ');
target.parentNode.replaceChild(newNode, target);
}
}
/** keep href attributes of tag A */
if (target.tagName == 'A') {
href = target.getAttribute('href');
}
/** Remove all tags */
while(target.attributes.length > 0) {
target.removeAttribute(target.attributes[0].name);
}
/** return href */
if (href) {
target.setAttribute('href', href);
}
return target;
};
/**
* Depth-first search Algorithm
* returns all childs
* @param {Element}
*/
content.dfs = function(el) {
if (!codex.core.isDomNode(el))
if (!node) {
return;
var sanitized = this.clearStyles(el);
for(var i = 0; i < sanitized.childNodes.length; i++) {
this.dfs(sanitized.childNodes[i]);
}
/**
* Disconnect Observer
* hierarchy of function calls inherits context of observer
*/
this.disconnect();
/**
* Don't sanitize text node
*/
if (node.nodeType == codex.core.nodeTypes.TEXT) {
return;
}
/**
* Clear dirty content
*/
var sanitizer = new janitor(Config),
clear = sanitizer.clean(node.outerHTML);
var div = codex.draw.node('DIV', [], { innerHTML: clear });
node.replaceWith(div.childNodes[0]);
// for (i = 0; i < clearHTML.childNodes.length; i++) {
//
// var tag = clearHTML.childNodes[i],
// blockType = null;
//
// for (tool in codex.tools) {
//
// var handleTags = codex.tools[tool].handleTagOnPaste;
//
// if (!handleTags) {
// continue;
// }
//
// if (handleTags.indexOf(tag.tagName) !== -1) {
// blockType = codex.tools[tool];
// break;
// }
//
// }
//
// if (blockType) {
// codex.parser.insertPastedContent(blockType, tag);
// }
//
// }
};
return content;

View file

@ -1,3 +1,10 @@
/**
* Codex Editor Core
*
* @author Codex Team
* @version 1.1.2
*/
var core = (function(core) {
/**
@ -20,6 +27,14 @@ var core = (function(core) {
codex.state.blocks = userSettings.data;
}
if (userSettings.initialBlockPlugin) {
codex.settings.initialBlockPlugin = userSettings.initialBlockPlugin;
}
if (userSettings.uploadImagesUrl) {
codex.settings.uploadImagesUrl = userSettings.uploadImagesUrl;
}
codex.nodes.textarea = document.getElementById(userSettings.textareaId || codex.settings.textareaId);
if (typeof codex.nodes.textarea === undefined || codex.nodes.textarea === null) {

View file

@ -1,3 +1,10 @@
/**
* Codex Editor Draw module
*
* @author Codex Team
* @version 1.0.
*/
var draw = (function(draw) {
/**
@ -153,7 +160,7 @@ var draw = (function(draw) {
div.classList.add('ce-settings_default');
return div;
},
};
draw.pluginsSettings = function() {

View file

@ -1,3 +1,10 @@
/**
* Codex Editor Notification Module
*
* @author Codex Team
* @version 1.0
*/
var notifications = (function(notifications) {
/**

View file

@ -1,237 +1,21 @@
/**
* Codex Editor Parser Module
*
* @author Codex Team
* @version 1.1
*/
var parser = (function(parser) {
/**
* Splits content by `\n` and returns blocks
*/
parser.getSeparatedTextFromContent = function(content) {
return content.split('\n');
};
/** inserting text */
parser.insertPastedContent = function(content) {
var blocks = this.getSeparatedTextFromContent(content),
i,
inputIndex = cEditor.caret.getCurrentInputIndex(),
textNode,
parsedTextContent;
for(i = 0; i < blocks.length; i++) {
blocks[i].trim();
if (blocks[i]) {
var data = cEditor.draw.pluginsRender('paragraph', blocks[i]);
cEditor.content.insertBlock(data);
}
}
};
/**
* Asynchronously parses textarea input string to HTML editor blocks
*/
parser.parseTextareaContent = function () {
var initialContent = cEditor.nodes.textarea.value;
if ( initialContent.trim().length === 0 ) return true;
cEditor.parser
/** Get child nodes async-aware */
.getNodesFromString(initialContent)
/** Then append nodes to the redactor */
.then(cEditor.parser.appendNodesToRedactor)
/** Write log if something goes wrong */
.catch(function(error) {
cEditor.core.log('Error while parsing content: %o', 'warn', error);
});
};
/**
* Parses string to nodeList
* @param string inputString
* @return Primise -> nodeList
*/
parser.getNodesFromString = function (inputString) {
return Promise.resolve().then(function() {
var contentHolder = document.createElement('div');
contentHolder.innerHTML = inputString;
/**
* Returning childNodes will include:
* - Elements (html-tags),
* - Texts (empty-spaces or non-wrapped strings )
* - Comments and other
*/
return contentHolder.childNodes;
});
};
/**
* Appends nodes to the redactor
* @param nodeList nodes - list for nodes to append
*/
parser.appendNodesToRedactor = function(nodes) {
/**
* Sequence of one-by-one nodes appending
* Uses to save blocks order after async-handler
*/
var nodeSequence = Promise.resolve();
for (var index = 0; index < nodes.length ; index++ ) {
/** Add node to sequence at specified index */
cEditor.parser.appendNodeAtIndex(nodeSequence, nodes, index);
}
};
/**
* Append node at specified index
*/
parser.appendNodeAtIndex = function (nodeSequence, nodes, index) {
/** We need to append node to sequence */
nodeSequence
/** first, get node async-aware */
.then(function() {
return cEditor.parser.getNodeAsync(nodes , index);
parser.insertPastedContent = function(blockType, tag) {
codex.content.insertBlock({
type : blockType.type,
block : blockType.render({
text : tag.innerHTML
})
/**
* second, compose editor-block from node
* and append it to redactor
*/
.then(function(node){
var block = cEditor.parser.createBlockByDomNode(node);
if ( cEditor.core.isDomNode(block) ) {
block.contentEditable = "true";
/** Mark node as redactor block*/
block.classList.add('ce-block');
/** Append block to the redactor */
cEditor.nodes.redactor.appendChild(block);
/** Save block to the cEditor.state array */
cEditor.state.blocks.push(block);
return block;
}
return null;
})
.then(cEditor.ui.addBlockHandlers)
/** Log if something wrong with node */
.catch(function(error) {
cEditor.core.log('Node skipped while parsing because %o', 'warn', error);
});
};
/**
* Asynchronously returns node from nodeList by index
* @return Promise to node
*/
parser.getNodeAsync = function (nodeList, index) {
return Promise.resolve().then(function() {
return nodeList.item(index);
});
};
/**
* Creates editor block by DOM node
*
* First-level blocks (see cEditor.settings.blockTags) saves as-is,
* other wrapps with <p>-tag
*
* @param DOMnode node
* @return First-level node (paragraph)
*/
parser.createBlockByDomNode = function (node) {
/** First level nodes already appears as blocks */
if ( cEditor.parser.isFirstLevelBlock(node) ){
/** Save plugin type in data-type */
node = this.storeBlockType(node);
return node;
}
/** Other nodes wraps into parent block (paragraph-tag) */
var parentBlock,
nodeContent = node.textContent.trim(),
isPlainTextNode = node.nodeType != cEditor.core.nodeTypes.TAG;
/** Skip empty textNodes with space-symbols */
if (isPlainTextNode && !nodeContent.length) return null;
/** Make <p> tag */
parentBlock = cEditor.draw.block('P');
if (isPlainTextNode){
parentBlock.textContent = nodeContent.replace(/(\s){2,}/, '$1'); // remove double spaces
} else {
parentBlock.appendChild(node);
}
/** Save plugin type in data-type */
parentBlock = this.storeBlockType(parentBlock);
return parentBlock;
};
/**
* It's a crutch
* - - - - - - -
* We need block type stored as data-attr
* Now supports only simple blocks : P, HEADER, QUOTE, CODE
* Remove it after updating parser module for the block-oriented structure:
* - each block must have stored type
* @param {Element} node
*/
parser.storeBlockType = function (node) {
switch (node.tagName) {
case 'P' : node.dataset.tool = 'paragraph'; break;
case 'H1':
case 'H2':
case 'H3':
case 'H4':
case 'H5':
case 'H6': node.dataset.tool = 'header'; break;
case 'BLOCKQUOTE': node.dataset.tool = 'quote'; break;
case 'CODE': node.dataset.tool = 'code'; break;
}
return node;
};

View file

@ -1,3 +1,10 @@
/**
* Codex Editor Renderer Module
*
* @author Codex Team
* @version 1.0
*/
var renderer = (function(renderer) {
/**

View file

@ -1,3 +1,10 @@
/**
* Codex Editor Saver
*
* @author Codex Team
* @version 1.0
*/
var saver = (function(saver) {
/**

View file

@ -1,3 +1,12 @@
/**
* Inline toolbar
*
* Contains from tools:
* Bold, Italic, Underline and Anchor
*
* @author Codex Team
* @version 1.0
*/
var inline = (function(inline) {
inline.init = function() {

View file

@ -1,3 +1,14 @@
/**
* Codex Editor toolbar module
*
* Contains:
* - Inline toolbox
* - Toolbox within plus button
* - Settings section
*
* @author Codex Team
* @version 1.0
*/
var toolbar = (function(toolbar) {
toolbar.init = function() {

View file

@ -1,7 +1,17 @@
/**
* Codex Editor toolbox
*
* All tools be able to appended here
*
* @author Codex Team
* @version 1.0
*/
var toolbox = (function(toolbox) {
toolbox.init = function() {
toolbox.init = function () {
require('./toolbar');
};
toolbox.opened = false;
@ -11,7 +21,9 @@ var toolbox = (function(toolbox) {
/** Close setting if toolbox is opened */
if (codex.toolbar.settings.opened) {
codex.toolbar.settings.close();
}
/** display toolbox */
@ -50,8 +62,14 @@ var toolbox = (function(toolbox) {
/** Count toolbox hidden tools */
for( var tool in codex.tools ) {
if (!codex.tools[tool].displayInToolbox)
if (!codex.tools[tool].displayInToolbox) {
hiddenToolsAmount ++;
}
}
if ( !currentTool ) {
@ -73,7 +91,9 @@ var toolbox = (function(toolbox) {
for( var tool in codex.tools ) {
if (codex.tools[tool].displayInToolbox){
break;
}
nextToolIndex ++;
@ -123,6 +143,7 @@ var toolbox = (function(toolbox) {
UNREPLACEBLE_TOOLS.indexOf(workingNode.dataset.tool) === -1 &&
workingNode.textContent.trim() === ''
){
/** Replace current block */
codex.content.switchBlock(workingNode, newBlockContent, tool.type);
@ -140,7 +161,9 @@ var toolbox = (function(toolbox) {
appendCallback = tool.appendCallback;
if (appendCallback && typeof appendCallback == 'function') {
appendCallback.call(event);
}
setTimeout(function() {

View file

@ -1,3 +1,10 @@
/**
* Codex Editor tools
* This tools will be appended in toolbox
*
* @author Codex Team
* @version 1.0
*/
var tools = (function(tools) {
return tools;

View file

@ -3,7 +3,7 @@
* Codex.Editor Transport Module
*
* @author Codex Team
* @version 1.0.0
* @version 1.0
*/
var transport = (function(transport){

View file

@ -1,3 +1,10 @@
/**
* Codex Editor UI module
*
* @author Codex Team
* @version 1.1
*/
var ui = (function(ui){
/**
@ -10,30 +17,30 @@ var ui = (function(ui){
*/
BLOCK_CLASSNAME : 'ce-block',
/**
* @const {String} wrapper for plugins content
*/
BLOCK_CONTENT : 'ce-block__content',
/**
* @const {String} wrapper for plugins content
*/
BLOCK_CONTENT : 'ce-block__content',
/**
* @const {String} BLOCK_STRETCHED - makes block stretched
*/
BLOCK_STRETCHED : 'ce-block--stretched',
/**
* @const {String} BLOCK_STRETCHED - makes block stretched
*/
BLOCK_STRETCHED : 'ce-block--stretched',
/**
* @const {String} BLOCK_HIGHLIGHTED - adds background
*/
BLOCK_HIGHLIGHTED : 'ce-block--focused',
/**
* @const {String} BLOCK_HIGHLIGHTED - adds background
*/
BLOCK_HIGHLIGHTED : 'ce-block--focused',
/**
* @const {String} - highlights covered blocks
*/
BLOCK_IN_FEED_MODE : 'ce-block--feed-mode',
/**
* @const {String} - highlights covered blocks
*/
BLOCK_IN_FEED_MODE : 'ce-block--feed-mode',
/**
* @const {String} - for all default settings
*/
SETTINGS_ITEM : 'ce-settings__item'
/**
* @const {String} - for all default settings
*/
SETTINGS_ITEM : 'ce-settings__item'
};
@ -257,7 +264,10 @@ var ui = (function(ui){
}, false );
/** All keydowns on Document */
codex.nodes.redactor.addEventListener('keydown', codex.callback.globalKeydown, false );
document.addEventListener('keydown', codex.callback.globalKeydown, false );
/** All keydowns on Redactor zone */
codex.nodes.redactor.addEventListener('keydown', codex.callback.redactorKeyDown, false);
/** All keydowns on Document */
document.addEventListener('keyup', codex.callback.globalKeyup, false );
@ -302,7 +312,7 @@ var ui = (function(ui){
codex.tools[tool].prepare();
}
},
};
ui.addBlockHandlers = function(block) {
@ -317,9 +327,25 @@ var ui = (function(ui){
/**
* 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 codex.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 codex.callback.blockPasteViaSanitize(event)
*
* @uses html-janitor
* @example codex.callback.blockPasteViaSanitize(event), the second method.
*
*/
block.addEventListener('paste', function (event) {
codex.callback.blockPaste(event);
codex.callback.blockPasteViaSanitize(event);
}, false);
block.addEventListener('mouseup', function(){

View file

@ -1,6 +1,6 @@
{
"name": "codex.editor",
"version": "1.0.0",
"version": "1.2.8",
"description": "Codex Editor. Native JS, based on API and Open Source",
"main": "index.js",
"scripts": {
@ -17,7 +17,11 @@
"babel-polyfill": "^6.20.0",
"babel-runtime": "^6.20.0",
"css-loader": "^0.26.1",
"eslint": "^3.12.2",
"eslint-loader": "^1.6.1",
"extract-text-webpack-plugin": "^1.0.1",
"html-janitor": "^2.0.2",
"path": "^0.12.7",
"webpack": "^1.14.0"
}
}

View file

@ -35,6 +35,10 @@ var headerTool = {
tag.textContent = data.text;
}
if (!tag.dataset.headerData) {
tag.dataset.headerData = 'H2';
}
tag.classList.add('ce-header');
tag.setAttribute('data-placeholder', 'Heading');
tag.contentEditable = true;

View file

@ -6,9 +6,24 @@
*/
'use strict';
var pkg = require('./package.json');
var path = require('path');
/**
* Environment
* @type {any}
*/
const NODE_ENV = process.env.NODE_ENV || 'development';
var webpack = require('webpack');
var ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
const VERSION = process.env.VERSION || pkg.version;
var versioning = VERSION.split('.');
/**
* Plugins for bundle
* @type {webpack}
*/
var webpack = require('webpack');
var ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
module.exports = {
@ -30,8 +45,9 @@ module.exports = {
devtool: NODE_ENV == 'development' ? "source-map" : null,
resolve : {
fallback: path.join(__dirname, "node_modules"),
modulesDirectories : ['./node_modules', './modules'],
extensions : ['', '.js']
extensions : ['', '.js', '.json']
},
resolveLoader : {
@ -42,9 +58,15 @@ module.exports = {
plugins: [
new webpack.DefinePlugin({
NODE_ENV: JSON.stringify(NODE_ENV)
NODE_ENV: JSON.stringify(NODE_ENV),
VERSION: JSON.stringify(VERSION),
MAJOR: parseInt(versioning[0]),
MINOR: versioning[1],
BUILD: versioning[2]
}),
new webpack.EnvironmentPlugin('VERSION', pkg.version),
new webpack.ProvidePlugin({
_ : 'lodash'
})
@ -60,6 +82,16 @@ module.exports = {
presets: [__dirname + '/node_modules/babel-preset-es2015']
}
},
{
test : /\.js$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
},
{
test: /node_modules\/entities\/.*\.json$/,
include : /(node_modules)/,
loader: 'json'
},
{
test : /\.css$/,
exclude: /(node_modules)/,

File diff suppressed because one or more lines are too long