diff --git a/codex-editor.js b/codex-editor.js
index 8ea60238..86c6aef9 100644
--- a/codex-editor.js
+++ b/codex-editor.js
@@ -30,7 +30,8 @@ var cEditor = (function (cEditor) {
// Current editor state
cEditor.state = {
html : '',
- blocks : []
+ blocks : [],
+ inputs : [],
};
/**
@@ -53,6 +54,7 @@ var cEditor = (function (cEditor) {
.then(this.transport.prepare)
// .then(this.parser.parseTextareaContent)
.then(this.renderer.makeBlocksFromData)
+ .then(this.ui.getAllInputs)
.catch(function (error) {
cEditor.core.log('Initialization failed with error: %o', 'warn', error);
});
@@ -247,7 +249,7 @@ cEditor.renderer = {
/**
* add handlers to new block
*/
- .then(cEditor.ui.addBlockHandlers)
+ // .then(cEditor.ui.addBlockHandlers)
/** Log if something wrong with node */
.catch(function(error) {
@@ -430,8 +432,6 @@ cEditor.ui = {
cEditor.callback.redactorClicked(event);
- cEditor.caret.save();
-
}, false );
/** Clicks to SETTINGS button in toolbar */
@@ -447,9 +447,6 @@ cEditor.ui = {
*/
cEditor.nodes.redactor.addEventListener('input', function (event) {
- /** Saving caret in every modifications */
- cEditor.caret.save();
-
cEditor.callback.redactorInputEvent(event);
}, false );
@@ -477,6 +474,34 @@ cEditor.ui = {
cEditor.callback.blockPaste(event, block);
}, false);
+ },
+
+ /** getting all contenteditable elements */
+ getAllInputs : function() {
+
+ var redactor = cEditor.nodes.redactor,
+ elements = [];
+
+ setTimeout(function () {
+
+ var inputs = redactor.querySelectorAll('[contenteditable]');
+
+ for (var key in inputs) {
+
+ /**
+ * querySelectorAll('[contenteditable]') returns object methods like length, keys and so on.
+ * We need to get only DOM elements
+ */
+ if (cEditor.core.isDomNode(inputs[key])) {
+ elements[key] = inputs[key];
+ }
+ }
+
+ /** Save all inputs in global variable state */
+ cEditor.state.inputs = elements;
+
+ }, 10);
+
}
};
@@ -643,6 +668,7 @@ cEditor.callback = {
blockRightOrDownArrowPressed : function (block) {
var selection = window.getSelection(),
+ inputs = cEditor.state.inputs,
focusedNode = selection.anchorNode,
focusedNodeHolder;
@@ -651,20 +677,26 @@ cEditor.callback = {
return false;
}
- /** Saving caret after keydown event happend */
- cEditor.caret.save();
-
/** Looking for closest (parent) contentEditable element of focused node */
- while (focusedNode.className != cEditor.ui.BLOCK_CLASSNAME) {
+ while (focusedNode.contentEditable != 'true') {
focusedNodeHolder = focusedNode.parentNode;
focusedNode = focusedNodeHolder;
}
- /** Founded contentEditable element doesn't have childs */
- if (focusedNode.childNodes.length === 0)
+ /** Input index in DOM level */
+ var index = 0;
+ while (focusedNode != inputs[index]) {
+ index ++;
+ }
+
+ /**
+ * Founded contentEditable element doesn't have childs
+ * Or maybe New created block
+ */
+ if (!focusedNode.textContent)
{
- cEditor.caret.setToNextBlock(focusedNode);
+ cEditor.caret.setToNextBlock(index);
return;
}
@@ -674,16 +706,10 @@ cEditor.callback = {
var caretInLastChild = false,
caretAtTheEndOfText = false;
- var editableElement = focusedNode.querySelector('[contenteditable]'),
- lastChild,
+ var lastChild,
deepestTextnode;
- if (!editableElement) {
- cEditor.core.log('Can not find editable element in current block: %o', 'warn', focusedNode);
- return;
- }
-
- lastChild = editableElement.childNodes[editableElement.childNodes.length - 1 ];
+ lastChild = focusedNode.childNodes[focusedNode.childNodes.length - 1 ];
if (cEditor.core.isDomNode(lastChild)) {
@@ -706,7 +732,7 @@ cEditor.callback = {
return false;
}
- cEditor.caret.setToNextBlock(focusedNode);
+ cEditor.caret.setToNextBlock(index);
},
@@ -716,6 +742,7 @@ cEditor.callback = {
blockLeftOrUpArrowPressed : function (block) {
var selection = window.getSelection(),
+ inputs = cEditor.state.inputs,
focusedNode = selection.anchorNode,
focusedNodeHolder;
@@ -731,31 +758,37 @@ cEditor.callback = {
return false;
}
- /** Saving caret after keydown event happend */
- cEditor.caret.save();
-
/** Looking for parent contentEditable block */
- while (focusedNode.className != cEditor.ui.BLOCK_CLASSNAME) {
+ while (focusedNode.contentEditable != 'true') {
focusedNodeHolder = focusedNode.parentNode;
focusedNode = focusedNodeHolder;
}
+ /** Input index in DOM level */
+ var index = 0;
+ while (focusedNode != inputs[index]) {
+ index ++;
+ }
+
/**
* Do nothing if caret is not at the beginning of first child
*/
var caretInFirstChild = false,
caretAtTheBeginning = false;
- var editableElement = focusedNode.querySelector('[contenteditable]'),
- firstChild,
+ var firstChild,
deepestTextnode;
- if (!editableElement) {
- cEditor.core.log('Can not find editable element in current block: %o', 'warn', focusedNode);
+ /**
+ * Founded contentEditable element doesn't have childs
+ * Or maybe New created block
+ */
+ if (!focusedNode.textContent) {
+ cEditor.caret.setToPreviousBlock(index);
return;
}
- firstChild = editableElement.childNodes[0];
+ firstChild = focusedNode.childNodes[0];
if (cEditor.core.isDomNode(firstChild)) {
@@ -768,14 +801,14 @@ cEditor.callback = {
}
caretInFirstChild = selection.anchorNode == deepestTextnode;
- caretAtTheBeginning = cEditor.caret.offset === 0;
+ caretAtTheBeginning = selection.anchorOffset === 0;
console.log("каретка в первом узле: %o", caretInFirstChild);
console.log("каретка в начале первого узла: %o", caretAtTheBeginning);
if ( caretInFirstChild && caretAtTheBeginning ) {
- cEditor.caret.setToPreviousBlock(focusedNode);
+ cEditor.caret.setToPreviousBlock(index);
}
@@ -818,12 +851,13 @@ cEditor.callback = {
backspacePressed: function (block) {
- if (block.textContent.trim()) return;
+ cEditor.ui.getAllInputs();
- cEditor.caret.setToPreviousBlock(block);
+ if (block.textContent.trim()) return;
block.remove();
+ cEditor.toolbar.close();
cEditor.toolbar.move();
event.preventDefault();
@@ -966,10 +1000,14 @@ cEditor.content = {
cEditor.content.workingNodeChanged(newBlock);
/**
- * Setting caret
- * @todo is it necessary?
+ * Add block handlers
*/
- cEditor.caret.set(newBlock);
+ cEditor.ui.addBlockHandlers(newBlock);
+
+ /**
+ * Save changes
+ */
+ cEditor.ui.getAllInputs();
},
@@ -995,6 +1033,15 @@ cEditor.content = {
cEditor.nodes.redactor.appendChild(newBlock);
}
+ /**
+ * Save changes
+ */
+ cEditor.ui.getAllInputs();
+
+ /**
+ * Block handler
+ */
+ cEditor.ui.addBlockHandlers(newBlock);
/**
* Set new node as current
@@ -1078,7 +1125,7 @@ cEditor.content = {
*/
cEditor.content.workingNodeChanged(nodeCreated);
- cEditor.caret.set(nodeCreated);
+ //cEditor.caret.set(nodeCreated);
},
/**
@@ -1099,8 +1146,11 @@ cEditor.content = {
/** Replacing */
cEditor.content.replaceBlock(blockToReplace, newBlockComposed, blockType);
+ /** Save new Inputs when block is changed */
+ cEditor.ui.getAllInputs();
+
/** Add event listeners */
- cEditor.ui.addBlockHandlers(newBlock);
+ //cEditor.ui.addBlockHandlers(newBlockComposed);
},
@@ -1198,6 +1248,11 @@ cEditor.content = {
cEditor.caret = {
+ /**
+ * @var {int} InputIndex - editable element in DOM
+ */
+ InputIndex : null,
+
/**
* @var {int} offset - caret position in a text node.
*/
@@ -1261,8 +1316,6 @@ cEditor.caret = {
* Creates Document Range and sets caret to the element.
* @uses caret.save — if you need to save caret position
* @param {Element} el - Changed Node.
- * @todo remove saving positon
- * @todo - Check nodeToSet for type: if TAG -> look for nearest TextNode
*/
set : function( el , index, offset) {
@@ -1282,6 +1335,11 @@ cEditor.caret = {
}
+ if (cEditor.core.isDomNode(nodeToSet)) {
+
+ nodeToSet = cEditor.content.getDeepestTextNodeFromPosition(nodeToSet, nodeToSet.childNodes.length);
+ }
+
var range = document.createRange(),
selection = window.getSelection();
@@ -1293,7 +1351,7 @@ cEditor.caret = {
selection.removeAllRanges();
selection.addRange(range);
- }, 50);
+ }, 20);
},
/**
@@ -1306,58 +1364,41 @@ cEditor.caret = {
/**
* @param {Element} block - element from which we take next block
*/
- setToNextBlock : function(block) {
+ setToNextBlock : function(index) {
- cEditor.caret.offset = 0;
- cEditor.caret.focusedNodeIndex = 0;
+ var inputs = cEditor.state.inputs,
+ nextInput = inputs[index + 1];
- var nextBlock = block.nextSibling,
- nextBlockEditableElement;
-
- console.log("nextBlock: %o", nextBlock);
-
- nextBlockEditableElement = nextBlock.querySelector('[contenteditable]');
-
- console.log("nextBlockEditableElement: %o", nextBlockEditableElement);
-
-
- if ( !block.nextSibling ) {
- return false;
+ if (nextInput.childNodes.length === 0) {
+ var emptyTextElement = document.createTextNode('');
+ nextInput.appendChild(emptyTextElement);
}
+ cEditor.caret.InputIndex = nextInput;
+ cEditor.caret.set(nextInput, 0, 0);
+ cEditor.content.workingNodeChanged(nextInput);
- cEditor.caret.set(nextBlockEditableElement, 0, 0);
- cEditor.content.workingNodeChanged(block.nextSibling);
},
/**
* @todo передалать на prevBlock.querySelector('[contenteditable]') по аналогии с setToNextBlock
*/
- setToPreviousBlock : function(block) {
+ setToPreviousBlock : function(index) {
- if ( !block.previousSibling ) {
- return false;
+ var inputs = cEditor.state.inputs,
+ previousInput = inputs[index - 1];
+
+ lastChildNode = cEditor.content.getDeepestTextNodeFromPosition(previousInput, previousInput.childNodes.length);
+ lengthOfLastChildNode = lastChildNode.length;
+
+ if (previousInput.childNodes.length === 0) {
+ var emptyTextElement = document.createTextNode('');
+ previousInput.appendChild(emptyTextElement);
}
- var lastChildOfPreiviousBlockIndex = block.previousSibling.childNodes.length,
- previousBlock = block.previousSibling,
- theEndOfPreviousBlockLastNode = 0;
-
- /** Index in childs Array */
- if (block.previousSibling.childNodes.length !== 0) {
-
- previousBlock = cEditor.content.getDeepestTextNodeFromPosition(block.previousSibling, lastChildOfPreiviousBlockIndex);
- theEndOfPreviousBlockLastNode = previousBlock.length;
- lastChildOfPreiviousBlockIndex = 0;
-
- }
-
- cEditor.caret.offset = theEndOfPreviousBlockLastNode;
- cEditor.caret.focusedNodeIndex = lastChildOfPreiviousBlockIndex;
-
- cEditor.caret.set(previousBlock, lastChildOfPreiviousBlockIndex, theEndOfPreviousBlockLastNode);
-
- cEditor.content.workingNodeChanged(block.previousSibling);
+ cEditor.caret.InputIndex = previousInput;
+ cEditor.caret.set(previousInput, previousInput.childNodes.length - 1, lengthOfLastChildNode);
+ cEditor.content.workingNodeChanged(inputs[index - 1]);
},
};
@@ -1414,13 +1455,11 @@ cEditor.toolbar = {
leaf : function(){
var currentTool = this.current,
- // tools = cEditor.settings.tools,
tools = Object.keys(cEditor.tools),
barButtons = cEditor.nodes.toolbarButtons,
nextToolIndex,
toolToSelect;
- // console.log(tools);
if ( !currentTool ) {
/** Get first tool from object*/
@@ -1479,6 +1518,8 @@ cEditor.toolbar = {
appendCallback.call();
}
+ /** Save new changes */
+ cEditor.ui.getAllInputs();
},
@@ -1771,6 +1812,7 @@ cEditor.parser = {
}
return null;
})
+
.then(cEditor.ui.addBlockHandlers)
/** Log if something wrong with node */
@@ -1877,11 +1919,6 @@ cEditor.parser = {
};
-cEditor.tools = {
-
-};
-
-
/**
* Creates HTML elements
*/
@@ -1979,285 +2016,13 @@ cEditor.draw = {
}
-
};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/**
-* Paragraph Plugin\
-* Creates P tag and adds content to this tag
+* Developer plugins
*/
-var paragraphTool = {
- /**
- * Make initial header block
- * @param {object} JSON with block data
- * @return {Element} element to append
- */
- make : function (data) {
-
- var tag = document.createElement('DIV');
-
- if (data && data.text) {
- tag.innerHTML = data.text;
- }
-
- tag.contentEditable = true;
-
- return tag;
-
- },
-
- /**
- * Method to render HTML block from JSON
- */
- render : function (data) {
-
- return paragraphTool.make(data);
-
- },
-
- /**
- * Method to extract JSON data from HTML block
- */
- save : function (block){
-
- var data = {
- text : null
- };
-
- data.text = blockData.textContent;
-
- return data;
-
- },
-
-};
-
-/**
-* Now plugin is ready.
-* Add it to redactor tools
-*/
-cEditor.tools.paragraph = {
-
- type : 'paragraph',
- iconClassname : 'ce-icon-paragraph',
- make : paragraphTool.make,
- appendCallback : null,
- settings : null,
- render : paragraphTool.render,
- save : paragraphTool.save
-
-};
-
-/**
-* Example of making plugin
-* H e a d e r
-*/
-var headerTool = {
-
- /**
- * Make initial header block
- * @param {object} JSON with block data
- * @return {Element} element to append
- */
- make : function (data) {
-
- var availableTypes = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'],
- tag;
-
- if (data && data.type && availableTypes.includes(data.type)) {
-
- tag = document.createElement( data.type );
-
- /**
- * Save header type in data-attr.
- * We need it in save method to extract type from HTML to JSON
- */
- tag.dataset.headerData = data.type;
-
- } else {
-
- tag = document.createElement( 'H2' );
-
- }
-
- if (data && data.text) {
- tag.textContent = data.text;
- }
-
- tag.contentEditable = true;
-
- return tag;
-
- },
-
- /**
- * Method to render HTML block from JSON
- */
- render : function (data) {
-
- return headerTool.make(data);
-
- },
-
- /**
- * Method to extract JSON data from HTML block
- */
- save : function (block){
-
- var data = {
- type : null,
- text : null
- };
-
- data.type = blockData.dataset.headerData;
- data.text = blockData.textContent;
-
- return data;
-
- },
-
- /**
- * Block appending callback
- */
- appendCallback : function (argument) {
-
- console.log('header appended...');
-
- },
-
- /**
- * Settings panel content
- * - - - - - - - - - - - - -
- * | настройки H1 H2 H3 |
- * - - - - - - - - - - - - -
- * @return {Element} element contains all settings
- */
- makeSettings : function () {
-
- var holder = document.createElement('DIV'),
- caption = document.createElement('SPAN'),
- types = {
- H2: 'Заголовок раздела',
- H3: 'Подзаголовок',
- H4: 'Заголовок 3-его уровня'
- },
- selectTypeButton;
-
- /** Add holder classname */
- holder.className = 'ce_plugin_header--settings';
-
- /** Add settings helper caption */
- caption.textContent = 'Настройки заголовка';
- caption.className = 'ce_plugin_header--caption';
-
- holder.appendChild(caption);
-
- /** Now add type selectors */
- for (var type in types){
-
- selectTypeButton = document.createElement('SPAN');
-
- selectTypeButton.textContent = types[type];
- selectTypeButton.className = 'ce_plugin_header--select_button';
-
- this.addSelectTypeClickListener(selectTypeButton, type);
-
- holder.appendChild(selectTypeButton);
-
- }
-
- return holder;
-
- },
-
- /**
- * Binds click event to passed button
- */
- addSelectTypeClickListener : function (el, type) {
-
- el.addEventListener('click', function () {
-
- headerTool.selectTypeClicked(type);
-
- }, false);
- },
-
- /**
- * Replaces old header with new type
- * @params {string} type - new header tagName: H1—H6
- */
- selectTypeClicked : function (type) {
-
- var old_header, new_header;
-
- /** Now current header stored as a currentNode */
- old_header = cEditor.content.currentNode;
-
- /** Making new header */
- new_header = document.createElement(type);
-
- new_header.innerHTML = old_header.innerHTML;
- new_header.contentEditable = true;
-
- cEditor.content.replaceBlock(old_header, new_header, 'header');
-
- /** Add listeners for Arrow keys*/
- cEditor.ui.addBlockHandlers(new_header);
-
- /** Close settings after replacing */
- cEditor.toolbar.settings.close();
-
- },
-
-};
-
-/**
-* Now plugin is ready.
-* Add it to redactor tools
-*/
-cEditor.tools.header = {
-
- type : 'header',
- iconClassname : 'ce-icon-header',
- make : headerTool.make,
- appendCallback : headerTool.appendCallback,
- settings : headerTool.makeSettings(),
- render : headerTool.render,
- save : headerTool.save
+cEditor.tools = {
};
diff --git a/editor.css b/editor.css
index 19643e52..d39925d5 100644
--- a/editor.css
+++ b/editor.css
@@ -181,39 +181,6 @@
border-radius: 3px;
}
-
-
-
-
-
-
-
-/**
-* Plugin styles
-*/
-
-
-/** H e a d e r - settings */
-.ce_plugin_header--settings{
- white-space: nowrap;
- /*padding-right: 10px; */
-}
-.ce_plugin_header--caption{
- color: #b9c2c2;
-}
-.ce_plugin_header--select_button{
- display: inline-block;
- margin-left: 40px;
- border-bottom: 1px solid #c3d5ed;
- padding-bottom: 2px;
- color: #5399d4;
- cursor: pointer;
-}
- .ce_plugin_header--select_button:hover{
- border-bottom-color: #f6d8da;
- color: #cc7d74;
- }
-
/*
@-webkit-keyframes bounceIn {
0% { opacity: 0; -webkit-transform: scale(.3);}
diff --git a/example.html b/example.html
index 69483bfb..25dce745 100644
--- a/example.html
+++ b/example.html
@@ -269,16 +269,22 @@
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
diff --git a/plugins/ceditor-tool-code/ceditor-tool-code.css b/plugins/code/code.css
similarity index 100%
rename from plugins/ceditor-tool-code/ceditor-tool-code.css
rename to plugins/code/code.css
diff --git a/plugins/ceditor-tool-code/ceditor-tool-code.js b/plugins/code/code.js
similarity index 100%
rename from plugins/ceditor-tool-code/ceditor-tool-code.js
rename to plugins/code/code.js
diff --git a/plugins/header/header.css b/plugins/header/header.css
new file mode 100644
index 00000000..ffc21f06
--- /dev/null
+++ b/plugins/header/header.css
@@ -0,0 +1,23 @@
+/**
+* Plugin styles
+*/
+/** H e a d e r - settings */
+.ce_plugin_header--settings{
+ white-space: nowrap;
+ /*padding-right: 10px; */
+}
+.ce_plugin_header--caption{
+ color: #b9c2c2;
+}
+.ce_plugin_header--select_button{
+ display: inline-block;
+ margin-left: 40px;
+ border-bottom: 1px solid #c3d5ed;
+ padding-bottom: 2px;
+ color: #5399d4;
+ cursor: pointer;
+}
+ .ce_plugin_header--select_button:hover{
+ border-bottom-color: #f6d8da;
+ color: #cc7d74;
+ }
diff --git a/plugins/header/header.js b/plugins/header/header.js
new file mode 100644
index 00000000..e1fdab35
--- /dev/null
+++ b/plugins/header/header.js
@@ -0,0 +1,178 @@
+/**
+* Example of making plugin
+* H e a d e r
+*/
+var headerTool = {
+
+ /**
+ * Make initial header block
+ * @param {object} JSON with block data
+ * @return {Element} element to append
+ */
+ make : function (data) {
+
+ var availableTypes = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'],
+ tag;
+
+ if (data && data.type && availableTypes.includes(data.type)) {
+
+ tag = document.createElement( data.type );
+
+ /**
+ * Save header type in data-attr.
+ * We need it in save method to extract type from HTML to JSON
+ */
+ tag.dataset.headerData = data.type;
+
+ } else {
+
+ tag = document.createElement( 'H2' );
+
+ }
+
+ if (data && data.text) {
+ tag.textContent = data.text;
+ }
+
+ tag.contentEditable = true;
+
+ return tag;
+
+ },
+
+ /**
+ * Method to render HTML block from JSON
+ */
+ render : function (data) {
+
+ return headerTool.make(data);
+
+ },
+
+ /**
+ * Method to extract JSON data from HTML block
+ */
+ save : function (block){
+
+ var data = {
+ type : null,
+ text : null
+ };
+
+ data.type = blockData.dataset.headerData;
+ data.text = blockData.textContent;
+
+ return data;
+
+ },
+
+ /**
+ * Block appending callback
+ */
+ appendCallback : function (argument) {
+
+ console.log('header appended...');
+
+ },
+
+ /**
+ * Settings panel content
+ * - - - - - - - - - - - - -
+ * | настройки H1 H2 H3 |
+ * - - - - - - - - - - - - -
+ * @return {Element} element contains all settings
+ */
+ makeSettings : function () {
+
+ var holder = document.createElement('DIV'),
+ caption = document.createElement('SPAN'),
+ types = {
+ H2: 'Заголовок раздела',
+ H3: 'Подзаголовок',
+ H4: 'Заголовок 3-его уровня'
+ },
+ selectTypeButton;
+
+ /** Add holder classname */
+ holder.className = 'ce_plugin_header--settings';
+
+ /** Add settings helper caption */
+ caption.textContent = 'Настройки заголовка';
+ caption.className = 'ce_plugin_header--caption';
+
+ holder.appendChild(caption);
+
+ /** Now add type selectors */
+ for (var type in types){
+
+ selectTypeButton = document.createElement('SPAN');
+
+ selectTypeButton.textContent = types[type];
+ selectTypeButton.className = 'ce_plugin_header--select_button';
+
+ this.addSelectTypeClickListener(selectTypeButton, type);
+
+ holder.appendChild(selectTypeButton);
+
+ }
+
+ return holder;
+
+ },
+
+ /**
+ * Binds click event to passed button
+ */
+ addSelectTypeClickListener : function (el, type) {
+
+ el.addEventListener('click', function () {
+
+ headerTool.selectTypeClicked(type);
+
+ }, false);
+ },
+
+ /**
+ * Replaces old header with new type
+ * @params {string} type - new header tagName: H1—H6
+ */
+ selectTypeClicked : function (type) {
+
+ var old_header, new_header;
+
+ /** Now current header stored as a currentNode */
+ old_header = cEditor.content.currentNode;
+
+ /** Making new header */
+ new_header = document.createElement(type);
+
+ new_header.innerHTML = old_header.innerHTML;
+ new_header.contentEditable = true;
+
+ cEditor.content.replaceBlock(old_header, new_header, 'header');
+
+ /** Add listeners for Arrow keys*/
+ cEditor.ui.addBlockHandlers(new_header);
+
+ /** Close settings after replacing */
+ cEditor.toolbar.settings.close();
+
+ },
+
+};
+
+/**
+* Now plugin is ready.
+* Add it to redactor tools
+*/
+cEditor.tools.header = {
+
+ type : 'header',
+ iconClassname : 'ce-icon-header',
+ make : headerTool.make,
+ appendCallback : headerTool.appendCallback,
+ settings : headerTool.makeSettings(),
+ render : headerTool.render,
+ save : headerTool.save
+
+};
diff --git a/plugins/ceditor-tool-link/ceditor-tool-link.css b/plugins/link/link.css
similarity index 100%
rename from plugins/ceditor-tool-link/ceditor-tool-link.css
rename to plugins/link/link.css
diff --git a/plugins/ceditor-tool-link/ceditor-tool-link.js b/plugins/link/link.js
similarity index 100%
rename from plugins/ceditor-tool-link/ceditor-tool-link.js
rename to plugins/link/link.js
diff --git a/plugins/ceditor-tool-link/loading.gif b/plugins/link/loading.gif
similarity index 100%
rename from plugins/ceditor-tool-link/loading.gif
rename to plugins/link/loading.gif
diff --git a/plugins/ceditor-tool-list/ceditor-tool-list.css b/plugins/list/list.css
similarity index 100%
rename from plugins/ceditor-tool-list/ceditor-tool-list.css
rename to plugins/list/list.css
diff --git a/plugins/ceditor-tool-list/ceditor-tool-list.js b/plugins/list/list.js
similarity index 100%
rename from plugins/ceditor-tool-list/ceditor-tool-list.js
rename to plugins/list/list.js
diff --git a/plugins/paragraph/paragraph.css b/plugins/paragraph/paragraph.css
new file mode 100644
index 00000000..e69de29b
diff --git a/plugins/paragraph/paragraph.js b/plugins/paragraph/paragraph.js
new file mode 100644
index 00000000..28e49282
--- /dev/null
+++ b/plugins/paragraph/paragraph.js
@@ -0,0 +1,66 @@
+/**
+* Paragraph Plugin\
+* Creates P tag and adds content to this tag
+*/
+var paragraphTool = {
+
+ /**
+ * Make initial header block
+ * @param {object} JSON with block data
+ * @return {Element} element to append
+ */
+ make : function (data) {
+
+ var tag = document.createElement('DIV');
+
+ if (data && data.text) {
+ tag.innerHTML = data.text;
+ }
+
+ tag.contentEditable = true;
+
+ return tag;
+
+ },
+
+ /**
+ * Method to render HTML block from JSON
+ */
+ render : function (data) {
+
+ return paragraphTool.make(data);
+
+ },
+
+ /**
+ * Method to extract JSON data from HTML block
+ */
+ save : function (block){
+
+ var data = {
+ text : null
+ };
+
+ data.text = blockData.textContent;
+
+ return data;
+
+ },
+
+};
+
+/**
+* Now plugin is ready.
+* Add it to redactor tools
+*/
+cEditor.tools.paragraph = {
+
+ type : 'paragraph',
+ iconClassname : 'ce-icon-paragraph',
+ make : paragraphTool.make,
+ appendCallback : null,
+ settings : null,
+ render : paragraphTool.render,
+ save : paragraphTool.save
+
+};
diff --git a/plugins/ceditor-tool-quote/img/01.jpg b/plugins/quote/img/01.jpg
similarity index 100%
rename from plugins/ceditor-tool-quote/img/01.jpg
rename to plugins/quote/img/01.jpg
diff --git a/plugins/ceditor-tool-quote/img/codex.png b/plugins/quote/img/codex.png
similarity index 100%
rename from plugins/ceditor-tool-quote/img/codex.png
rename to plugins/quote/img/codex.png
diff --git a/plugins/ceditor-tool-quote/img/upload.png b/plugins/quote/img/upload.png
similarity index 100%
rename from plugins/ceditor-tool-quote/img/upload.png
rename to plugins/quote/img/upload.png
diff --git a/plugins/ceditor-tool-quote/ceditor-tool-quote.css b/plugins/quote/quote.css
similarity index 100%
rename from plugins/ceditor-tool-quote/ceditor-tool-quote.css
rename to plugins/quote/quote.css
diff --git a/plugins/ceditor-tool-quote/ceditor-tool-quote.js b/plugins/quote/quote.js
similarity index 100%
rename from plugins/ceditor-tool-quote/ceditor-tool-quote.js
rename to plugins/quote/quote.js