Browse Source

Refactor Editor and update on Components

pull/36/head
Artur Arseniev 11 years ago
parent
commit
a1774f5591
  1. 43
      src/dom_components/main.js
  2. 11
      src/dom_components/model/Components.js
  3. 7
      src/editor/config/config.js
  4. 101
      src/editor/model/Editor.js
  5. 16
      src/parser/model/ParserHtml.js
  6. 9
      styles/css/main.css
  7. 7
      styles/scss/main.scss
  8. 2
      test/specs/dom_components/main.js
  9. 24
      test/specs/parser/model/ParserHtml.js

43
src/dom_components/main.js

@ -59,21 +59,21 @@ define(function(require) {
if (!(name in c)) if (!(name in c))
c[name] = defaults[name]; c[name] = defaults[name];
} }
/*
if(!c.wrapper.attributes)
c.wrapper.attributes = {};
c.wrapper.attributes.id = 'wrapper';
// If there is no components try to append defaults // If there is no components try to append defaults
if(!c.wrapper.components.length && c.defaults.length){ if(!c.wrapper.components.length && c.defaults.length){
c.wrapper.components = c.defaults; c.wrapper.components = c.defaults;
} }
*/
//c.wrapper.style.position = 'relative';
var component = new Component(c.wrapper, { sm: c.em });
if(!c.wrapper.style) component.set({
c.wrapper.style = {}; attributes: {id: 'wrapper'}
});
c.wrapper.style.position = 'relative'; if(c.components)
var component = new Component(c.wrapper, { sm: c.em }); component.get('components').add(c.components);
var obj = { var obj = {
model: component, model: component,
@ -178,9 +178,32 @@ define(function(require) {
* updated immediately * updated immediately
* @return {HTMLElement} * @return {HTMLElement}
*/ */
render : function(){ render: function(){
return componentView.render().el; return componentView.render().el;
}, },
/**
* Clear all components
* @return {this}
* @private
*/
clear: function(){
var c = this.getComponents();
for(var i = 0, len = c.length; i < len; i++)
c.pop();
return this;
},
/**
* Set components
* @param {Object|string} components HTML string or components model
* @return {this}
* @private
*/
setComponents: function(components){
this.clear().addComponent(components);
},
}; };
}; };

11
src/dom_components/model/Components.js

@ -5,6 +5,10 @@ define([ 'backbone', 'require'],
initialize: function(models, opt){ initialize: function(models, opt){
// Inject editor
if(opt && opt.sm)
this.editor = opt.sm;
this.model = function(attrs, options) { this.model = function(attrs, options) {
var model; var model;
@ -37,5 +41,12 @@ define([ 'backbone', 'require'],
}, },
add: function(models, opt){
if(typeof models === 'string')
models = this.editor.Parser.parseHtml(models);
return Backbone.Collection.prototype.add.apply(this, [models, opt]);
},
}); });
}); });

7
src/editor/config/config.js

@ -1,6 +1,9 @@
define(function () { define(function () {
var config = { var config = {
//TEMP
components: '',
// Style prefix // Style prefix
stylePrefix: 'wte-', stylePrefix: 'wte-',
@ -46,8 +49,8 @@ define(function () {
//Configurations for Rich Text Editor //Configurations for Rich Text Editor
rte : {}, rte : {},
//Configurations for Components //Configurations for DomComponents
components : {}, domComponents : {},
//Configurations for Modal Dialog //Configurations for Modal Dialog
modal : {}, modal : {},

101
src/editor/model/Editor.js

@ -49,6 +49,7 @@ define([
this.rulesName = this.pfx + 'rules' + this.config.id; this.rulesName = this.pfx + 'rules' + this.config.id;
this.set('Config', c); this.set('Config', c);
this.initParser();
this.initStorage(); this.initStorage();
this.initClassManager(); this.initClassManager();
this.initModal(); this.initModal();
@ -62,7 +63,6 @@ define([
this.initUndoManager(); this.initUndoManager();
this.initCssComposer(); this.initCssComposer();
this.initUtils(); this.initUtils();
this.initParser();
this.on('change:selectedComponent', this.componentSelected, this); this.on('change:selectedComponent', this.componentSelected, this);
}, },
@ -71,8 +71,8 @@ define([
* Initialize Parser * Initialize Parser
* */ * */
initParser: function() { initParser: function() {
this.parser = new Parser(); this.Parser = new Parser();
this.set('parser', this.parser); this.set('parser', this.Parser);
}, },
/** /**
@ -161,30 +161,31 @@ define([
* @private * @private
* */ * */
initComponents: function() { initComponents: function() {
var cfg = this.config.components, var cfg = this.config.domComponents,
comp = this.loadComponents(), comp = this.loadComponents(),
cmpStylePfx = cfg.stylePrefix || 'comp-'; cmpStylePfx = cfg.stylePrefix || 'comp-';
cfg.stylePrefix = this.config.stylePrefix + cmpStylePfx; cfg.stylePrefix = this.config.stylePrefix + cmpStylePfx;
if(comp) if(comp)
cfg.wrapper = comp; cfg.components = comp;
if(this.rte) if(this.rte)
cfg.rte = this.rte; cfg.rte = this.rte;
if(this.modal) if(this.modal)
cfg.modal = this.modal; cfg.modal = this.modal;
if(this.am) if(this.am)
cfg.am = this.am; cfg.am = this.am;
cfg.em = this; cfg.em = this;
this.cmp = new DomComponents(cfg); this.cmp = new DomComponents(cfg);
this.Components = this.cmp; this.Components = this.cmp;
if(this.stm.isAutosave()){ if(this.stm.isAutosave()){
var md = this.cmp.getComponent(); var md = this.cmp.getComponent();
this.updateComponents( md, null, { avoidStore : 1 }); this.updateComponents( md, null, { avoidStore : 1 });
// Call UndoManager here so it's possible to call it also for children inside // Call UndoManager here so it's possible to call it also for children inside
@ -398,15 +399,20 @@ define([
* @return {Object} * @return {Object}
* */ * */
loadComponents: function() { loadComponents: function() {
var result = null; var comps = '';
try{ var result = this.getCacheLoad();
var r = this.stm.load(this.compName);
if(r) if(result.components){
result = JSON.parse(r); try{
}catch(err){ comps = JSON.parse(result.components);
//console.warn("Error encountered while parsing JSON response"); }catch(err){}
}else if(result.html){
comps = result.html;
} }
return result;
console.log('loadComponents');
console.log(comps);
return comps;
}, },
/** /**
@ -415,11 +421,12 @@ define([
* @return void * @return void
* */ * */
storeComponents: function() { storeComponents: function() {
var wrp = this.cmp.getComponent(); /*var wrp = this.cmp.getComponent();
if(wrp && this.cm){ if(wrp && this.cm){
var res = this.cm.getCode(wrp, 'json'); var res = this.cm.getCode(wrp, 'json');
this.stm.store(this.compName, JSON.stringify(res)); this.stm.store(this.compName, JSON.stringify(res));
} }*/
this.store();
}, },
/** /**
@ -518,7 +525,7 @@ define([
* @return {this} * @return {this}
*/ */
setComponents: function(components){ setComponents: function(components){
return this; return this.Components.setComponents(components);
}, },
/** /**
@ -608,6 +615,8 @@ define([
if(smc.storeStyles) if(smc.storeStyles)
store.styles = JSON.stringify(this.getStyle()); store.styles = JSON.stringify(this.getStyle());
console.log('Store');
console.log(store);
sm.store(store); sm.store(store);
}, },
@ -615,11 +624,38 @@ define([
* Load data from the current storage * Load data from the current storage
*/ */
load: function(){ load: function(){
var result = this.getCacheLoad(1);
var comps = [];
if(result.components){
try{
comps = JSON.parse(result.components);
}catch(err){}
}else if(result.html){
comps = result.html;
}
console.log(result);
//this.setComponents(comps);
},
/**
* Returns cached load
* @param {Boolean} force Force to reload
* @return {Object}
* @private
*/
getCacheLoad: function(force){
var f = force ? 1 : 0;
if(this.cacheLoad && !f)
return this.cacheLoad;
var sm = this.StorageManager; var sm = this.StorageManager;
var load = []; var load = [];
if(!sm) if(!sm)
return; return {};
var smc = sm.getConfig(); var smc = sm.getConfig();
@ -635,20 +671,9 @@ define([
if(smc.storeStyles) if(smc.storeStyles)
load.push('styles'); load.push('styles');
var result = sm.load(load); this.cacheLoad = sm.load(load);
var comps = [];
if(result.components){
try{
comps = JSON.parse(result.components);
}catch(err){}
}else if(result.html){
comps = result.html;
}
console.log(result);
//this.setComponents(comps);
return this.cacheLoad;
}, },
}); });

16
src/parser/model/ParserHtml.js

@ -2,6 +2,8 @@ define(function(require) {
return function(config) { return function(config) {
var TEXT_NODE = 'span';
return { return {
/** /**
@ -84,13 +86,21 @@ define(function(require) {
} }
// Check for nested elements // Check for nested elements
if(node.childNodes.length) var nodeChild = node.childNodes.length;
model.components = this.parseNode(node); if(nodeChild){
// Avoid infinite text nodes nesting
var firstChild = node.childNodes[0];
if(nodeChild === 1 && firstChild.nodeType === 3 && model.tagName === TEXT_NODE){
model.type = 'text';
model.content = firstChild.nodeValue;
}else
model.components = this.parseNode(node);
}
// Find text nodes // Find text nodes
if(!model.tagName && node.nodeType === 3 && node.nodeValue.trim()){ if(!model.tagName && node.nodeType === 3 && node.nodeValue.trim()){
model.type = 'text'; model.type = 'text';
model.tagName = 'span'; model.tagName = TEXT_NODE;
model.content = node.nodeValue; model.content = node.nodeValue;
} }

9
styles/css/main.css

@ -2614,8 +2614,10 @@ html, body, #wte-app, .wte-editor {
top: 0; top: 0;
left: 3.5%; left: 3.5%;
overflow: auto; overflow: auto;
z-index: 1; } z-index: 1;
/* This simulate body behaviour */ }
.wte-cv-canvas > div { .wte-cv-canvas > div {
position: relative;
height: 100%; height: 100%;
overflow: auto; overflow: auto;
width: 100%; } width: 100%; }
@ -2686,7 +2688,7 @@ ol.example li.placeholder:before {
outline: none !important; } outline: none !important; }
/********* COMMANDS **********/ /********* COMMANDS **********/
.wte-com-dashed div { .wte-com-dashed * {
outline: 1px dashed #888; outline: 1px dashed #888;
outline-offset: -2px; outline-offset: -2px;
box-sizing: border-box; } box-sizing: border-box; }
@ -3444,7 +3446,8 @@ ol.example li.placeholder:before {
width: 25px; width: 25px;
border-right: 1px solid #353535; border-right: 1px solid #353535;
text-align: center; text-align: center;
cursor: pointer; } cursor: pointer;
outline: none; }
#wte-rte-toolbar .wte-rte-btn:last-child { #wte-rte-toolbar .wte-rte-btn:last-child {
border-right: none; } border-right: none; }
#wte-rte-toolbar .wte-rte-btn.btn-info { #wte-rte-toolbar .wte-rte-btn.btn-info {

7
styles/scss/main.scss

@ -98,7 +98,9 @@ html,body,#wte-app, .#{$app-prefix}editor{ height: 100%; }
overflow: auto; overflow: auto;
z-index:1; z-index:1;
/* This simulate body behaviour */
> div { > div {
position: relative;
height: 100%; height: 100%;
overflow: auto; overflow: auto;
width: 100%; width: 100%;
@ -149,7 +151,7 @@ ol.example li.placeholder:before {position: absolute;}
/********* COMMANDS **********/ /********* COMMANDS **********/
.#{$com-prefix}dashed div { .#{$com-prefix}dashed *{
outline: 1px dashed #888; outline: 1px dashed #888;
outline-offset: -2px; outline-offset: -2px;
box-sizing: border-box; box-sizing: border-box;
@ -1031,12 +1033,13 @@ $uploadPadding: 150px 10px;
z-index: 5; z-index: 5;
.#{$rte-prefix}btn { .#{$rte-prefix}btn {
color: $fontColor; color: $fontColor;
padding: 5px; padding: 5px;
width: 25px; width: 25px;
border-right: 1px solid #353535; border-right: 1px solid #353535;
text-align: center; text-align: center;
cursor: pointer; cursor: pointer;
outline: none;
&:last-child{ border-right:none; } &:last-child{ border-right:none; }
&.btn-info{ background-color: darken($mainDkColor,3%); } &.btn-info{ background-color: darken($mainDkColor,3%); }

2
test/specs/dom_components/main.js

@ -58,7 +58,7 @@ define([
it('Add components at init', function() { it('Add components at init', function() {
obj = new DomComponents({ obj = new DomComponents({
defaults : [{}, {}, {}] components : [{}, {}, {}]
}); });
obj.getComponents().length.should.equal(3); obj.getComponents().length.should.equal(3);
}); });

24
test/specs/parser/model/ParserHtml.js

@ -155,6 +155,30 @@ define([path + 'model/ParserHtml',],
obj.parse(str).should.deep.equal(result); obj.parse(str).should.deep.equal(result);
}); });
it('Parse nested span text nodes', function() {
var str = '<div>content1 <div><span>nested</span></div> content2</div>';
var result = {
tagName: 'div',
components: [{
tagName: 'span',
type: 'text',
content: 'content1 ',
},{
tagName: 'div',
components: [{
tagName: 'span',
type: 'text',
content: 'nested',
}]
},{
tagName: 'span',
type: 'text',
content: ' content2',
}],
};
obj.parse(str).should.deep.equal(result);
});
it('Parse multiple nodes', function() { it('Parse multiple nodes', function() {
var str = '<div></div><div></div>'; var str = '<div></div><div></div>';
var result = [{ tagName: 'div'},{ tagName: 'div'}]; var result = [{ tagName: 'div'},{ tagName: 'div'}];

Loading…
Cancel
Save