Renderer sequence, Render and Save example, (#53)

* Renderer sequence,  Render and Save example,

* move render method close to the save

* fixed bugs and parapraph plugin added

* result JSON example

* upd

* upd

* cEditor tools cleared default methods

* upd
This commit is contained in:
Peter Savchenko 2016-06-29 18:54:20 +03:00 committed by GitHub
parent 34eb871bb0
commit b93942a820
3 changed files with 389 additions and 98 deletions

View file

@ -8,7 +8,7 @@ var cEditor = (function (cEditor) {
// Default settings
cEditor.settings = {
tools : ['header', 'picture', 'list', 'quote', 'code', 'twitter', 'instagram', 'smile'],
tools : ['paragraph', 'header', 'picture', 'list', 'quote', 'code', 'twitter', 'instagram', 'smile'],
textareaId : 'codex-editor',
// First-level tags viewing as separated blocks. Other'll be inserted as child
@ -27,7 +27,7 @@ var cEditor = (function (cEditor) {
}
// Current editor state
cEditor.state = {
cEditor.state = {
html : '',
blocks : []
}
@ -166,8 +166,6 @@ cEditor.renderer = {
*/
makeBlocksFromData : function (argument) {
console.info('renderer makeBlocksFromData');
Promise.resolve()
/** First, get JSON from state */
@ -177,12 +175,12 @@ cEditor.renderer = {
/** Then, start to iterate they */
.then(cEditor.renderer.appendBlocks)
/** Write log if something goes wrong */
.catch(function(error) {
cEditor.core.log('Error while parsing JSON: %o', 'warn', error);
cEditor.core.log('Error while parsing JSON: %o', 'error', error);
});
},
/**
@ -192,12 +190,120 @@ cEditor.renderer = {
*/
appendBlocks : function (data) {
console.info('renderer appendBlocks %o', data);
var blocks = data.items;
/**
* Тут надо создать очередь по аналогии с parser.appendNodesToRedactor,
* которая будет асинхронно парсить блоки с помощью метода render у каждого плагина
* 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 */
cEditor.renderer.appendNodeAtIndex(nodeSequence, blocks, index);
}
},
/**
* Append node at specified index
*/
appendNodeAtIndex : function (nodeSequence, blocks, index) {
/** We need to append node to sequence */
nodeSequence
/** first, get node async-aware */
.then(function() {
return cEditor.renderer.getNodeAsync(blocks , index);
})
/**
* second, compose editor-block from JSON object
*/
.then(cEditor.renderer.createBlockFromData)
/**
* now insert block to redactor
*/
.then(function(blockData){
/**
* blockData has 'block' and 'type' information
*/
cEditor.content.insertBlock(blockData.block, blockData.type);
/** Pass created block to next step */
return blockData.block;
})
/**
* add handlers to new block
*/
.then(cEditor.ui.addBlockHandlers)
/** Log if something wrong with node */
.catch(function(error) {
cEditor.core.log('Node skipped while parsing because %o', 'error', error);
});
},
/**
* Asynchronously returns block data from blocksList by index
* @return Promise to node
*/
getNodeAsync : function (blocksList, index) {
return Promise.resolve().then(function() {
return blocksList[index];
});
},
/**
* Creates editor block by JSON-data
*
* @uses render method of each plugin
*
* @param {object} blockData looks like
* { header : {
* text: '',
* type: 'H3', ...
* }
* }
* @return {object} with type and Element
*/
createBlockFromData : function (blockData) {
/** Get first key of object that stores plugin name */
for (var pluginName in blockData) break;
/** Check for plugin existance */
if (!cEditor.tools[pluginName]) {
throw Error(`Plugin «${pluginName}» not found`);
}
/** Check for plugin having render method */
if (typeof cEditor.tools[pluginName].render != 'function') {
throw Error(`Plugin «${pluginName}» must have «render» method`);
}
/** Fire the render method with data */
var block = cEditor.tools[pluginName].render(blockData[pluginName]);
/** Retrun type and block */
return {
type : pluginName,
block : block
}
},
@ -214,7 +320,7 @@ cEditor.saver = {
saveBlocks : function (argument) {
console.info('saver saveBlocks');
}
}
@ -808,10 +914,28 @@ cEditor.content = {
var workingNode = cEditor.content.currentNode;
el.classList.add(cEditor.ui.BLOCK_CLASSNAME);
newBlock.classList.add(cEditor.ui.BLOCK_CLASSNAME);
newBlock.dataset.type = blockType;
cEditor.core.insertAfter(workingNode, newBlock);
if (workingNode) {
cEditor.core.insertAfter(workingNode, newBlock);
} else {
/**
* If redactor is empty, append as first child
*/
cEditor.nodes.redactor.appendChild(newBlock);
/**
* Set new node as current
*/
cEditor.content.workingNodeChanged(newBlock);
}
},
/**
@ -1169,11 +1293,13 @@ cEditor.toolbar = {
leaf : function(){
var currentTool = this.current,
tools = cEditor.settings.tools,
// 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*/
@ -1544,75 +1670,9 @@ cEditor.parser = {
cEditor.tools = {
paragraph : {
type : 'paragraph',
iconClassname : 'ce-icon-paragraph',
append : document.createElement('P'),
appendCallback : function () {
console.log('paragraph added');
},
settings : null,
},
/*quote : {
type : 'quote',
iconClassname : 'ce-icon-quote',
append : document.createElement('BLOCKQUOTE'),
appendCallback : function () {
console.log('quote added');
},
settings : null,
},*/
code : {
type : 'code',
iconClassname : 'ce-icon-code',
append : document.createElement('CODE'),
appendCallback : function () {
console.log('code added');
},
settings : null,
},
list : {
type : 'list',
iconClassname : 'ce-icon-list-bullet',
append : document.createElement('LI'),
appendCallback : function () {
console.log('code added');
},
settings : null,
}
};
/**
* Creates HTML elements
*/
@ -1747,6 +1807,72 @@ cEditor.draw = {
/**
* Paragraph Plugin\
* Creates P tag and adds content to this tag
*/
var paragraphTool = {
/**
* Make initial header block
* @param {object} JSON to with block data
* @return {Element} element to append
*/
makeBlockToAppend : function (data) {
var tag = document.createElement('P');
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.makeBlockToAppend(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',
append : paragraphTool.makeBlockToAppend(),
appendCallback : null,
settings : null,
render : paragraphTool.render,
save : paragraphTool.save
};
/**
* Example of making plugin
@ -1756,17 +1882,63 @@ var headerTool = {
/**
* Make initial header block
* @param {object} JSON to with block data
* @return {Element} element to append
*/
makeBlockToAppend : function () {
makeBlockToAppend : function (data) {
var el = document.createElement('H2');
var availableTypes = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'],
tag;
el.contentEditable = 'true';
if (data && data.type && availableTypes.includes(data.type)) {
cEditor.ui.addBlockHandlers(el);
tag = document.createElement( data.type );
return el;
/**
* 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.makeBlockToAppend(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;
},
@ -1863,7 +2035,6 @@ var headerTool = {
},
};
/**
@ -1877,5 +2048,7 @@ cEditor.tools.header = {
append : headerTool.makeBlockToAppend(),
appendCallback : headerTool.appendCallback,
settings : headerTool.makeSettings(),
render : headerTool.render,
save : headerTool.save
};

File diff suppressed because one or more lines are too long

116
result-sample.json Normal file
View file

@ -0,0 +1,116 @@
{
"data":[
{
"type":"text",
"data":{
"text":"<p>It's a text. It can be with <a href=\"http:\/\/tj.local\/redirect?url=http%3A%2F%2Fya.ru\" target=\"_blank\">link<\/a>. And <b>bold<\/b> and <i>italic.<\/i><\/p><p>We can use br here.<\/p><p>and paragraphs<\/p>",
"format":"html",
"introText":"<<<same>>>"
}
},
{
"type":"heading_styled",
"data":{
"text":"Header",
"format":"html",
"heading-styles":"h2"
}
},
{
"type":"heading_styled",
"data":{
"text":"little header",
"format":"html",
"heading-styles":"h4"
}
},
{
"type":"link_embed",
"data":{
"title":"",
"description":"",
"image":"",
"url":"https:\/\/new.vk.com\/feed"
}
},
{
"type":"image_extended",
"data":{
"background":false,
"border":false,
"isstretch":false,
"file":{
"url":"https:\/\/static39.cmtt.ru\/club\/66\/13\/cb\/3165d72648b97e.jpg",
"bigUrl":"https:\/\/static35.cmtt.ru\/club\/66\/88\/1b\/d990e3f617eb9b.jpg",
"width":1200,
"height":750,
"additionalData":"null"
},
"caption":"It's a caption. It will have b, i and a tags in future",
"cover":false
}
},
{
"type":"gallery",
"data":{
"background":false,
"border":false,
"isstretch":false,
"files":[
{
"url":"https:\/\/static39.cmtt.ru\/club\/7c\/f1\/ed\/6b139e871d1bce.jpg",
"bigUrl":"https:\/\/static36.cmtt.ru\/club\/4b\/40\/e8\/8c7e9d6941948c.jpg",
"width":1080,
"height":1080,
"caption":"caption1"
},
{
"url":"https:\/\/static35.cmtt.ru\/club\/e7\/ec\/6b\/c43f8f0f694341.jpg",
"bigUrl":"https:\/\/static35.cmtt.ru\/club\/53\/b2\/d2\/a633e11246a1bb.jpg",
"width":1200,
"height":1200,
"caption":"caption2"
}
]
}
},
{
"type":"video_extended",
"data":{
"source":"youtube",
"remote_id":"SqmAjcAPBpA",
"thumbnailUrl":"http:\/\/tj.local\/preview\/youtube\/SqmAjcAPBpA",
"time":0,
"width":800,
"height":450
}
},
{
"type":"quote_styled",
"data":{
"text":"<p>Quote <a href=\"http:\/\/tj.local\/redirect?url=http%3A%2F%2Fya.ru\" target=\"_blank\">text<\/a><\/p><p>Bold <i>etc<\/i><\/p>",
"format":"html",
"cite":"Author",
"size":"small"
}
},
{
"type":"tweet",
"data":{
"media":true,
"conversation":false,
"user":{
"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/1817165982\/nikita-likhachev-512_normal.jpg",
"profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/1817165982\/nikita-likhachev-512_normal.jpg",
"screen_name":"Niketas",
"name":"Никита Лихачёв"
},
"id":747793978511101953,
"text":"ВНИМАНИЕ ЧИТАТЬ ВСЕМ НЕ ДАЙ БОГ ПРОПУСТИТЕ НУ ИЛИ ХОТЯ БЫ КЛИКНИ И ПОДОЖДИ 15 СЕКУНД https:\/\/t.co\/iWyOHf4xr2",
"created_at":"Tue Jun 28 14:09:12 +0000 2016",
"status_url":"https:\/\/twitter.com\/Niketas\/status\/747793978511101953",
"caption":"Caption"
}
}
]
}