changed parsing method. Now data parses data like sample.json (#84)

* changed parsing method. Now data parses data like sample.json

* saver module (#86)
This commit is contained in:
khaydarov 2016-07-15 18:29:54 +03:00 committed by Peter Savchenko
parent f5c8dc82e3
commit b0d3907793
8 changed files with 236 additions and 92 deletions

View file

@ -30,9 +30,9 @@ var cEditor = (function (cEditor) {
// Current editor state
cEditor.state = {
html : '',
blocks : [],
inputs : [],
jsonOutput : [],
blocks : [],
inputs : [],
};
/**
@ -171,7 +171,8 @@ cEditor.renderer = {
/**
* Asyncronously parses input JSON to redactor blocks
*/
makeBlocksFromData : function (argument) {
makeBlocksFromData : function () {
Promise.resolve()
@ -285,8 +286,11 @@ cEditor.renderer = {
*/
createBlockFromData : function (blockData) {
/** New parser */
var pluginName = blockData.type;
/** Get first key of object that stores plugin name */
for (var pluginName in blockData) break;
// for (var pluginName in blockData) break;
/** Check for plugin existance */
if (!cEditor.tools[pluginName]) {
@ -299,8 +303,11 @@ cEditor.renderer = {
throw Error(`Plugin «${pluginName}» must have «render» method`);
}
/** New Parser */
var block = cEditor.tools[pluginName].render(blockData.data);
/** Fire the render method with data */
var block = cEditor.tools[pluginName].render(blockData[pluginName]);
// var block = cEditor.tools[pluginName].render(blockData[pluginName]);
/** Retrun type and block */
return {
@ -320,10 +327,82 @@ cEditor.saver = {
/**
* Saves blocks
*/
saveBlocks : function (argument) {
saveBlocks : function () {
console.info('saver saveBlocks');
/** Save html content of redactor to memory */
// cEditor.state.html = cEditor.nodes.redactor.innerHTML;
Promise.resolve()
.then(function() {
return cEditor.nodes.redactor.childNodes;
})
/** Making a sequence from separate blocks */
.then(cEditor.saver.makeQueue)
.catch( function(error) {
console.log('Something happend');
});
},
makeQueue : function(blocks) {
var queue = Promise.resolve();
for(var index = 0; index < blocks.length; index++) {
/** Add node to sequence at specified index */
cEditor.saver.getBlockData(queue, blocks, index);
}
},
/** Gets every block and makes From Data */
getBlockData : function(queue, blocks, index) {
queue.then(function() {
return cEditor.saver.getNodeAsync(blocks, index);
})
.then(cEditor.saver.makeFormDataFromBlocks);
},
/**
* Asynchronously returns block data from blocksList by index
* @return Promise to node
*/
getNodeAsync : function (blocksList, index) {
return Promise.resolve().then(function() {
return blocksList[index];
});
},
makeFormDataFromBlocks : function(block) {
var pluginName = block.dataset.type;
/** 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].save != 'function') {
throw Error(`Plugin «${pluginName}» must have save method`);
}
/** Result saver */
var blockContent = block.childNodes,
savedData = cEditor.tools[pluginName].save(blockContent);
cEditor.state.jsonOutput.push(savedData);
}
};

View file

@ -90,22 +90,26 @@ var INPUT = {
/** Fill with example data */
INPUT.items = [
{
paragraph : {
type : 'paragraph',
data : {
text : '<p>Ladies and gentlemen, prepare yourself for a pivotal moment in the history of web development…</p>'
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : '<p><i>[Drumroll begins]</i></p><p>Promises have arrived natively in JavaScript!</p><p><i>[Fireworks explode, glittery paper rains from above, the crowd goes wild]</i></p>'
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : 'At this point you fall into one of these categories:'
}
},
{
list : {
type : 'list',
data : {
type : 'unordered',
items : [
`People are cheering around you, but you're not sure what all the fuss is about. Maybe you're not even sure what a "promise" is. You'd shrug, but the weight of glittery paper is weighing down on your shoulders. If so, don't worry about it, it took me ages to work out why I should care about this stuff. You probably want to begin here`,
@ -116,18 +120,21 @@ INPUT.items = [
},
{
header : {
type : 'header',
data : {
type : 'H2',
text : 'What\'s all the fuss about?',
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : 'JavaScript is single threaded, meaning that two bits of script cannot run at the same time, they have to run one after another. In browsers, JavaScript shares a thread with a load of other stuff. What that stuff is differs from browser to browser, but typically JavaScript is in the same queue as painting, updating styles, and handling user actions (such as highlighting text and interacting with form controls). Activity in one of these things delays the others.'
}
},
{
link : {
type : 'link',
data : {
'linkUrl' : 'http://yandex.ru',
'linkText' : 'yandex.ru',
'image' : 'https://yastatic.net/morda-logo/i/apple-touch-icon/ru-76x76.png',
@ -136,18 +143,21 @@ INPUT.items = [
}
},
{
header : {
type : 'header',
data : {
type : 'H3',
text : 'Promises arrive in JavaScript!',
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : 'Promises have been around for a while in the form of libraries, such as:',
}
},
{
list : {
type : 'list',
data : {
type : 'unordered',
items : [
'Q',
@ -159,17 +169,20 @@ INPUT.items = [
},
{
paragraph : {
type : 'paragraph',
data : {
text : "The above and JavaScript promises share a common, standardised behaviour called Promises/A+. If you're a jQuery user, they have something similar called Deferreds. However, Deferreds aren't compliant, which makes them subtly different and less useful, so beware. jQuery also has a Promise type, but this is just a subset of Deferred and has the same issues. Although promise implementations follow a standardised behaviour, their overall APIs differ. JavaScript promises are similar in API to RSVP.js. Here's how you create a promise:",
}
},
{
code : {
type : 'code',
data : {
text : "var promise = new Promise(function(resolve, reject) { // do a thing, possibly async, then… if (/* everything turned out fine */) { resolve('Stuff worked!''); } else reject(Error('It broke')); } });",
}
},
{
quote : {
type : 'quote',
data : {
type : 'withCaption',
text : "But what does this mean for promises? Well, you can use this return/resume behaviour to write async code that looks like (and is as easy to follow as) synchronous code. Don't worry too much about understanding it line-for-line, but here's a helper function that lets us use 'yield' to wait for promises to settle:",
photo : '',
@ -178,23 +191,27 @@ INPUT.items = [
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : "The promise constructor takes one argument, a callback with two parameters, resolve and reject. Do something within the callback, perhaps async, then call resolve if everything worked, otherwise call reject.Like 'throw' in plain old JavaScript, it's customary, but not required, to reject with an Error object. The benefit of Error objects is they capture a stack trace, making debugging tools more helpful. Here's how you use that promise:",
}
},
{
header : {
type : 'header',
data : {
type : 'H2',
text : 'Browser support & polyfill',
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : "There are already implementations of promises in browsers today. As of Chrome 32, Opera 19, Firefox 29, Safari 8 & Microsoft Edge, promises are enabled by default. To bring browsers that lack a complete promises implementation up to spec compliance, or add promises to other browsers and Node.js, check out the polyfill (2k gzipped).",
}
},
{
link : {
type : 'link',
data : {
'linkUrl' : 'http://google.com',
'linkText' : 'google.com',
'image' : 'https://2.bp.blogspot.com/-7bZ5EziliZQ/VynIS9F7OAI/AAAAAAAASQ0/BJFntXCAntstZe6hQuo5KTrhi5Dyz9yHgCK4B/s1600/googlelogo_color_200x200.png',
@ -203,34 +220,40 @@ INPUT.items = [
}
},
{
header : {
type : 'header',
data : {
type : 'H2',
text : 'Compatibility with other libraries',
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : "The JavaScript promises API will treat anything with a then method as promise-like (or thenable in promise-speak *sigh*), so if you use a library that returns a Q promise, that's fine, it'll play nice with the new JavaScript promises. Although, as I mentioned, jQuery's Deferreds are a bit… unhelpful. Thankfully you can cast them to standard promises, which is worth doing as soon as possible:",
}
},
{
code : {
type : 'code',
data : {
text : "var jsPromise = Promise.resolve($.ajax('/whatever.json'));",
}
},
{
header : {
type : 'header',
data : {
type : 'H2',
text : "Complex async code made easier",
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : "Right, let's code some things. Say we want to:",
}
},
{
list : {
type : 'list',
data : {
type : 'ordered',
items : [
'Start a spinner to indicate loading',
@ -243,112 +266,132 @@ INPUT.items = [
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : "…but also tell the user if something went wrong along the way. We'll want to stop the spinner at that point too, else it'll keep on spinning, get dizzy, and crash into some other UI. Of course, you wouldn't use JavaScript to deliver a story, serving as HTML is faster, but this pattern is pretty common when dealing with APIs: Multiple data fetches, then do something when it's all done.",
}
},
{
header : {
type : 'header',
data : {
type : 'H2',
text : "Queuing asynchronous actions",
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : "You can also chain 'thens' to run async actions in sequence.When you return something from a 'then' callback, it's a bit magic. If you return a value, the next 'then' is called with that value. However, if you return something promise-like, the next 'then' waits on it, and is only called when that promise settles (succeeds/fails). For example:",
}
},
{
quote : {
type : 'quote',
data : {
type : 'simple',
text : "This is the first time we've seen Promise.resolve, which creates a promise that resolves to whatever value you give it. If you pass it an instance of Promise it'll simply return it (note: this is a change to the spec that some implementations don't yet follow). If you pass it something promise-like (has a 'then' method), it creates a genuine Promise that fulfills/rejects in the same way. If you pass in any other value, eg Promise.resolve('Hello'), it creates a promise that fulfills with that value. If you call it with no value, as above, it fulfills with 'ndefined'",
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : "There's also Promise.reject(val), which creates a promise that rejects with the value you give it (or undefined). We can tidy up the above code using array.reduce:",
}
},
{
header : {
type : 'header',
data : {
type : 'H2',
text : "Promise API Reference",
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : "All methods work in Chrome, Opera, Firefox, Microsoft Edge, and Safari unless otherwise noted. The polyfill provides the below for all browers.",
}
},
{
header : {
type : 'header',
data : {
type : 'H2',
text : "Static Methods",
}
},
{
header : {
type : 'header',
data : {
type : 'H3',
text : 'Promise.resolve(promise);',
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : "Returns promise (only if promise.constructor == Promise)",
}
},
{
header : {
type : 'header',
data : {
type : 'H3',
text : 'Promise.resolve(thenable);',
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : "Make a new promise from the thenable. A thenable is promise-like in as far as it has a 'then' method.",
}
},
{
header : {
type : 'header',
data : {
type : 'H3',
text : 'Promise.resolve(obj);',
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : "Make a promise that fulfills to obj. in this situation.",
}
},
{
header : {
type : 'header',
data : {
type : 'H3',
text : 'Promise.all(array);',
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : "Make a promise that rejects to obj. For consistency and debugging (e.g. stack traces), obj should be an instanceof Error.",
}
},
{
header : {
type : 'header',
data : {
type : 'H3',
text : 'Promise.race(array);',
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : "Make a Promise that fulfills as soon as any item fulfills, or rejects as soon as any item rejects, whichever happens first.",
}
},
{
header : {
type : 'header',
data : {
type : 'H2',
text : 'Conclution',
}
},
{
paragraph : {
type : 'paragraph',
data : {
text : "promise.then(onFulfilled, onRejected)'onFulfilled is called when/if 'promise' resolves. onRejected is called when/if 'promise' rejects. Both are optional, if either/both are omitted the next <b>onFulfilled/onRejected</b> in the chain is called. Both callbacks have a single parameter, the fulfillment value or rejection reason. 'then' returns a new promise equivalent to the value you return from <b>onFulfilled/onRejected</b> after being passed through Promise.resolve. If an error is thrown in the callback, the returned promise rejects with that <b>error.promise.catch(onRejected)</b> Sugar for promise.then(undefined, onRejected). Many thanks to Anne van Kesteren, Domenic Denicola, Tom Ashworth, Remy Sharp, Addy Osmani, Arthur Evans, and Yutaka Hirano who proofread this and made <b>corrections/recommendations</b>. Also, thanks to Mathias Bynens for updating various parts of the article.",
}
}

View file

@ -41,13 +41,16 @@ var codeTool = {
*/
save : function (block){
var data = {
text : null
var json = {
type : 'code',
data : {
text : null,
}
};
data.text = blockData.textContent;
json.data.text = block.innerHTML;
return data;
return json;
},
@ -67,4 +70,4 @@ cEditor.tools.code = {
render : codeTool.render,
save : codeTool.save
};
};

View file

@ -54,15 +54,18 @@ var headerTool = {
*/
save : function (block){
var data = {
type : null,
text : null
var json = {
type : 'header',
data : {
type : null,
text : null,
}
};
data.type = blockData.dataset.headerData;
data.text = blockData.textContent;
json.data.type = block.dataset.headerData;
json.data.text = block.textContent;
return data;
return json;
},

View file

@ -68,15 +68,18 @@ var linkTool = {
var linkElement = linkTool.elementClasses.link;
var data = {
fullLink : block.querySelector("." + linkElement).href,
shortLink : block.querySelector("." + linkElement).textContent,
image : block.querySelector("." + linkTool.elementClasses.image).src,
title : block.querySelector("." + linkTool.elementClasses.title).textContent,
description : block.querySelector("." + linkTool.elementClasses.description).textContent
var json = {
type : 'link',
data : {
fullLink : block.querySelector("." + linkElement).href,
shortLink : block.querySelector("." + linkElement).textContent,
image : block.querySelector("." + linkTool.elementClasses.image).src,
title : block.querySelector("." + linkTool.elementClasses.title).textContent,
description : block.querySelector("." + linkTool.elementClasses.description).textContent
}
};
return data;
return json;
},
@ -202,7 +205,7 @@ var linkTool = {
};
linkTool.ui = {
make : function (json) {
var wrapper = this.wrapper(),
@ -253,7 +256,7 @@ linkTool.ui = {
return wrapper;
},
image : function (imageSrc, imageClass) {
var imageTag = document.createElement('img');
@ -263,7 +266,7 @@ linkTool.ui = {
imageTag.setAttribute('src', imageSrc);
return imageTag;
},
link : function (linkUrl, linkText) {
@ -312,8 +315,8 @@ cEditor.tools.link = {
iconClassname : 'ce-icon-link',
make : linkTool.makeNewBlock,
appendCallback : linkTool.appendCallback,
render : linkTool.render
render : linkTool.render,
// settings : linkTool.makeSettings(),
// save : linkTool.save
save : linkTool.save
};
};

View file

@ -42,6 +42,7 @@ var listTool = {
newLi.innerHTML = element;
tag.dataset.type = data.type;
tag.appendChild(newLi);
});
@ -55,13 +56,20 @@ var listTool = {
*/
save : function (block){
var data = {
text : null
var json = {
type : 'list',
data : {
type : null,
items : [],
}
};
data.text = blockData.textContent;
for(var index = 0; index < block.childNodes.length; index++)
json.data.items[index] = block.childNodes[index].textContent;
return data;
json.data.type = block.dataset.type;
return json;
},
@ -105,6 +113,7 @@ var listTool = {
newEditable = listTool.ui.make(blockType),
oldEditable = currentBlock.querySelector("[contenteditable]");
newEditable.dataset.type = blockType;
newEditable.innerHTML = oldEditable.innerHTML;
currentBlock.appendChild(newEditable);

View file

@ -37,13 +37,15 @@ var paragraphTool = {
*/
save : function (block){
var data = {
text : null
var json = {
type : 'paragraph',
data : {
text : null,
}
};
data.text = blockData.textContent;
return data;
json.data.text = block.innerHTML;
return json;
},

View file

@ -53,16 +53,18 @@ var quoteTools = {
*/
parsedblock = quoteTools.parseBlockQuote(block);
var data = {
type : 'quote',
style : parsedblock.style,
text : parsedblock.quote,
author : parsedblock.author,
job : parsedblock.job,
photo : parsedblock.photo,
var json = {
type : 'quote',
data : {
style : parsedblock.style,
text : parsedblock.text,
author : parsedblock.author,
job : parsedblock.job,
photo : parsedblock.photo,
}
};
return data;
return json;
},
makeSettings : function(data) {