Browse Source

Merge branch 'css-composer' into dev with few updates

pull/14/head
Artur Arseniev 10 years ago
parent
commit
2273fb8cfa
  1. 2
      src/class_manager/config/config.js
  2. 15
      src/class_manager/view/ClassTagView.js
  3. 102
      src/code_manager/main.js
  4. 63
      src/code_manager/model/CssGenerator.js
  5. 27
      src/code_manager/model/HtmlGenerator.js
  6. 4
      src/commands/view/ExportTemplate.js
  7. 2
      src/style_manager/view/SectorsView.js
  8. 1
      test/runner/main.js
  9. 25
      test/specs/class_manager/view/ClassTagView.js
  10. 39
      test/specs/code_manager/main.js
  11. 106
      test/specs/code_manager/model/CodeModels.js

2
src/class_manager/config/config.js

@ -11,7 +11,7 @@ define(function () {
label: 'Classes', label: 'Classes',
// Label for states // Label for states
statesLabel: 'State', statesLabel: '',
}; };
}); });

15
src/class_manager/view/ClassTagView.js

@ -13,6 +13,7 @@ define(['backbone', 'text!./../template/classTag.html'],
this.config = o.config || {}; this.config = o.config || {};
this.coll = o.coll || null; this.coll = o.coll || null;
this.pfx = this.config.stylePrefix || ''; this.pfx = this.config.stylePrefix || '';
this.target = this.config.target;
this.className = this.pfx + 'tag'; this.className = this.pfx + 'tag';
this.closeId = this.pfx + 'close'; this.closeId = this.pfx + 'close';
this.chkId = this.pfx + 'checkbox'; this.chkId = this.pfx + 'checkbox';
@ -28,6 +29,7 @@ define(['backbone', 'text!./../template/classTag.html'],
changeStatus: function(){ changeStatus: function(){
this.model.set('active', !this.model.get('active')); this.model.set('active', !this.model.get('active'));
this.target.trigger('targetClassUpdated');
}, },
/** /**
@ -35,13 +37,15 @@ define(['backbone', 'text!./../template/classTag.html'],
* @param {Object} e * @param {Object} e
*/ */
removeTag: function(e){ removeTag: function(e){
var comp = this.config.target.get('selectedComponent'); var comp = this.target.get('selectedComponent');
if(comp) if(comp)
comp.get('classes').remove(this.model); comp.get('classes').remove(this.model);
if(this.coll) if(this.coll){
this.coll.remove(this.model); this.coll.remove(this.model);
this.target.trigger('targetClassRemoved');
}
this.remove(); this.remove();
}, },
@ -53,10 +57,13 @@ define(['backbone', 'text!./../template/classTag.html'],
if(!this.$chk) if(!this.$chk)
this.$chk = this.$el.find('#' + this.pfx + 'checkbox'); this.$chk = this.$el.find('#' + this.pfx + 'checkbox');
if(this.model.get('active')) if(this.model.get('active')){
this.$chk.removeClass('fa-circle-o').addClass('fa-dot-circle-o'); this.$chk.removeClass('fa-circle-o').addClass('fa-dot-circle-o');
else this.$el.removeClass('opac50');
}else{
this.$chk.removeClass('fa-dot-circle-o').addClass('fa-circle-o'); this.$chk.removeClass('fa-dot-circle-o').addClass('fa-circle-o');
this.$el.addClass('opac50');
}
}, },
/** @inheritdoc */ /** @inheritdoc */

102
src/code_manager/main.js

@ -2,7 +2,7 @@ define(function(require) {
/** /**
* @class CodeManager * @class CodeManager
* @param {Object} Configurations * @param {Object} Configurations
* *
* @return {Object} * @return {Object}
* */ * */
function CodeManager(config) function CodeManager(config)
@ -21,38 +21,38 @@ define(function(require) {
if (!(name in c)) if (!(name in c))
c[name] = defaults[name]; c[name] = defaults[name];
} }
this.gi = new gInterface(); this.gi = new gInterface();
this.generators = {}; this.generators = {};
this.defaultGenerators = {}; this.defaultGenerators = {};
this.currentGenerator = null; this.currentGenerator = null;
this.ei = new eInterface(); this.ei = new eInterface();
this.editors = {}; this.editors = {};
this.defaultEditors = {}; this.defaultEditors = {};
this.currentEditor = null; this.currentEditor = null;
var geHtml = new gHtml(), var geHtml = new gHtml(),
geCss = new gCss(), geCss = new gCss(),
geJson = new gJson(), geJson = new gJson(),
edCM = new eCM(); edCM = new eCM();
this.defaultGenerators[geHtml.getId()] = geHtml; this.defaultGenerators[geHtml.getId()] = geHtml;
this.defaultGenerators[geCss.getId()] = geCss; this.defaultGenerators[geCss.getId()] = geCss;
this.defaultGenerators[geJson.getId()] = geJson; this.defaultGenerators[geJson.getId()] = geJson;
this.defaultEditors[edCM.getId()] = edCM; this.defaultEditors[edCM.getId()] = edCM;
this.EditorView = editorView; this.EditorView = editorView;
this.config = c; this.config = c;
} }
CodeManager.prototype = { CodeManager.prototype = {
/** /**
* Add new code generator * Add new code generator
* @param {GeneratorInterface} generator * @param {GeneratorInterface} generator
* *
* @return this * @return this
* */ * */
addGenerator : function(generator) addGenerator : function(generator)
@ -63,43 +63,43 @@ define(function(require) {
console.warn("addGenerator: method '"+ method +"' was not found"); console.warn("addGenerator: method '"+ method +"' was not found");
return; return;
} }
var id = generator.getId(); var id = generator.getId();
this.generators[id] = generator; this.generators[id] = generator;
if(!this.currentGenerator) if(!this.currentGenerator)
this.currentGenerator = id; this.currentGenerator = id;
return this; return this;
}, },
/** /**
* Returns generator * Returns generator
* @param {String}|{Integer} id Generator ID * @param {String}|{Integer} id Generator ID
* *
* @return {GeneratorInterface}|null * @return {GeneratorInterface}|null
* */ * */
getGenerator : function(id) getGenerator : function(id)
{ {
if(id && this.generators[id]) if(id && this.generators[id])
generator = this.generators[id]; generator = this.generators[id];
return generator ? generator : null; return generator ? generator : null;
}, },
/** /**
* Returns generators * Returns generators
* *
* @return {Array} * @return {Array}
* */ * */
getGenerators : function() getGenerators : function()
{ {
return this.generators; return this.generators;
}, },
/** /**
* Get current generator * Get current generator
* *
* @return {GeneratorInterface} * @return {GeneratorInterface}
* */ * */
getCurrentGenerator : function() getCurrentGenerator : function()
@ -108,11 +108,11 @@ define(function(require) {
this.loadDefaultGenerators(); this.loadDefaultGenerators();
return this.getGenerator(this.currentGenerator); return this.getGenerator(this.currentGenerator);
}, },
/** /**
* Set current generator * Set current generator
* @param {Integer} id Generator ID * @param {Integer} id Generator ID
* *
* @return this * @return this
* */ * */
setCurrentGenerator : function(id) setCurrentGenerator : function(id)
@ -120,10 +120,10 @@ define(function(require) {
this.currentGenerator = id; this.currentGenerator = id;
return this; return this;
}, },
/** /**
* Load default generators * Load default generators
* *
* @return this * @return this
* */ * */
loadDefaultGenerators : function() loadDefaultGenerators : function()
@ -131,14 +131,14 @@ define(function(require) {
for (var id in this.defaultGenerators) { for (var id in this.defaultGenerators) {
this.addGenerator(this.defaultGenerators[id]); this.addGenerator(this.defaultGenerators[id]);
} }
return this; return this;
}, },
/** /**
* Add new editor * Add new editor
* @param {EditorInterface} editor * @param {EditorInterface} editor
* *
* @return this * @return this
* */ * */
addEditor : function(editor) addEditor : function(editor)
@ -149,43 +149,43 @@ define(function(require) {
console.warn("addEditor: method '"+ method +"' was not found"); console.warn("addEditor: method '"+ method +"' was not found");
return; return;
} }
var id = editor.getId(); var id = editor.getId();
this.editors[id] = editor; this.editors[id] = editor;
if(!this.currentEditor) if(!this.currentEditor)
this.currentEditor = id; this.currentEditor = id;
return this; return this;
}, },
/** /**
* Returns editor * Returns editor
* @param {String}|{Integer} id Editor ID * @param {String}|{Integer} id Editor ID
* *
* @return {EditorInterface}|null * @return {EditorInterface}|null
* */ * */
getEditor : function(id) getEditor : function(id)
{ {
if(id && this.editors[id]) if(id && this.editors[id])
editor = this.editors[id]; editor = this.editors[id];
return editor ? editor : null; return editor ? editor : null;
}, },
/** /**
* Returns editors * Returns editors
* *
* @return {Array} * @return {Array}
* */ * */
getEditors : function() getEditors : function()
{ {
return this.editors; return this.editors;
}, },
/** /**
* Get current editor * Get current editor
* *
* @return {EditorInterface} * @return {EditorInterface}
* */ * */
getCurrentEditor : function() getCurrentEditor : function()
@ -194,11 +194,11 @@ define(function(require) {
this.loadDefaultEditors(); this.loadDefaultEditors();
return this.getEditor(this.currentEditor); return this.getEditor(this.currentEditor);
}, },
/** /**
* Set current editor * Set current editor
* @param {Integer} id Editor ID * @param {Integer} id Editor ID
* *
* @return this * @return this
* */ * */
setCurrentEditor : function(id) setCurrentEditor : function(id)
@ -206,10 +206,10 @@ define(function(require) {
this.currentEditor = id; this.currentEditor = id;
return this; return this;
}, },
/** /**
* Load default editors * Load default editors
* *
* @return this * @return this
* */ * */
loadDefaultEditors : function() loadDefaultEditors : function()
@ -217,38 +217,38 @@ define(function(require) {
for (var id in this.defaultEditors) { for (var id in this.defaultEditors) {
this.addEditor(this.defaultEditors[id]); this.addEditor(this.defaultEditors[id]);
} }
return this; return this;
}, },
/** /**
* Get code by name * Get code by name
* @param {Backbone.Model} model Model * @param {Backbone.Model} model Model
* @param {String}|{Integer} v Id of code generator * @param {String}|{Integer} v Id of code generator
* *
* @return {String}|null * @return {String}|null
* */ * */
getCode : function(model, v) getCode : function(model, v, em)
{ {
var id = v || this.currentGenerator, var id = v || this.currentGenerator,
generator = this.generators[id]; generator = this.generators[id];
return generator ? generator.build(model) : null; return generator ? generator.build(model, em) : null;
}, },
/** /**
* Update editor content * Update editor content
* @param {EditorInteface} editor Editor * @param {EditorInteface} editor Editor
* @param {String} code Code value * @param {String} code Code value
* *
* @return void * @return void
* */ * */
updateEditor : function(editor, code) updateEditor : function(editor, code)
{ {
editor.setContent(code); editor.setContent(code);
}, },
}; };
return CodeManager; return CodeManager;
}); });

63
src/code_manager/model/CssGenerator.js

@ -1,44 +1,71 @@
define(['backbone'], define(['backbone'],
function (Backbone) { function (Backbone) {
/** /**
* @class CssGenerator * @class CssGenerator
* */ * */
return Backbone.Model.extend({ return Backbone.Model.extend({
initialize: function(){
this.buff = [];
},
/** @inheritdoc */ /** @inheritdoc */
getId : function() getId : function()
{ {
return 'css'; return 'css';
}, },
/** @inheritdoc */ /** @inheritdoc */
build: function(model) build: function(model, cssc)
{ {
var coll = model.get('components') || model, var coll = model.get('components') || model,
code = ''; code = '';
coll.each(function(m){ coll.each(function(m){
var css = m.get('style'), var css = m.get('style'),
cln = m.get('components'); // Children cls = m.get('classes'),
cln = m.get('components');
// Get id-relative style
if(css && Object.keys(css).length !== 0){ if(css && Object.keys(css).length !== 0){
code += '#' + m.cid + '{'; code += '#' + m.cid + '{';
for(var prop in css) for(var prop in css)
if(css.hasOwnProperty(prop)) if(css.hasOwnProperty(prop))
code += prop + ': ' + css[prop] + ';'; code += prop + ':' + css[prop] + ';';
code += '}'; code += '}';
} }
if(cssc && cls.length){
var rule = cssc.getRule(cls.models);
if(rule){
var selectors = rule.get('selectors');
var ruleStyle = rule.get('style');
var strSel = '';
selectors.each(function(selector){
strSel += '.' + selector.get('name');
});
if(this.buff.indexOf(strSel) < 0){
this.buff.push(strSel);
code += strSel + '{';
if(ruleStyle && Object.keys(ruleStyle).length !== 0){
for(var prop2 in ruleStyle)
if(ruleStyle.hasOwnProperty(prop2))
code += prop2 + ':' + ruleStyle[prop2] + ';';
}
code += '}';
}
}
}
if(cln.length) if(cln.length)
code += this.build(cln); code += this.build(cln, cssc);
}, this); }, this);
return code; return code;
}, },
}); });
}); });

27
src/code_manager/model/HtmlGenerator.js

@ -16,15 +16,18 @@ define(['backbone'],
code = ''; code = '';
coll.each(function(m){ coll.each(function(m){
var tag = m.get('tagName'), // Tag name var tag = m.get('tagName'), // Tag name
sTag = 0, // Single tag sTag = 0, // Single tag
attr = '', // Attributes string attr = '', // Attributes string
cln = m.get('components'); // Children attrId = '',
strCls = '',
_.each(m.get('attributes'),function(value, prop){ cln = m.get('components'), // Children
attrs = m.get('attributes'),
classes = m.get('classes');
_.each(attrs,function(value, prop){
if(prop == 'onmousedown') if(prop == 'onmousedown')
return; return;
attr += value && prop!='style' ? ' ' + prop + '="' + value + '" ' : ''; attr += value && prop!='style' ? ' ' + prop + '="' + value + '"' : '';
}); });
if(m.get('type') == 'image'){ if(m.get('type') == 'image'){
@ -33,7 +36,15 @@ define(['backbone'],
attr += 'src="' + m.get('src') + '"'; attr += 'src="' + m.get('src') + '"';
} }
code += '<'+tag+' id="'+m.cid+'"' + attr + (sTag ? '/' : '') + '>' + m.get('content'); if(!_.isEmpty(m.get('style')))
attrId = ' id="' + m.cid + '" ';
classes.each(function(m){
strCls += ' ' + m.get('name');
});
strCls = strCls !== '' ? ' class="' + strCls.trim() + '"' : '';
code += '<' + tag + strCls + attrId + attr + (sTag ? '/' : '') + '>' + m.get('content');
if(cln.length) if(cln.length)
code += this.build(cln); code += this.build(cln);

4
src/commands/view/ExportTemplate.js

@ -9,6 +9,7 @@ define(function() {
this.components = em.get('Canvas').getWrapper().get('components'); this.components = em.get('Canvas').getWrapper().get('components');
this.modal = em.get('Modal') || null; this.modal = em.get('Modal') || null;
this.cm = em.get('CodeManager') || null; this.cm = em.get('CodeManager') || null;
this.cssc = em.get('CssComposer') || null;
this.enable(); this.enable();
}, },
@ -62,7 +63,8 @@ define(function() {
} }
this.htmlEditor.setContent( this.cm.getCode(this.components, 'html') ); this.htmlEditor.setContent( this.cm.getCode(this.components, 'html') );
this.cssEditor.setContent( this.cm.getCode(this.components, 'css') ); this.cm.getGenerator('css').buff = [];
this.cssEditor.setContent( this.cm.getCode(this.components, 'css', this.cssc));
if(this.sender) if(this.sender)
this.sender.set('active',false); this.sender.set('active',false);

2
src/style_manager/view/SectorsView.js

@ -13,7 +13,7 @@ define(['backbone','./SectorView'],
// The taget that will emit events for properties // The taget that will emit events for properties
this.propTarget = {}; this.propTarget = {};
_.extend(this.propTarget, Backbone.Events); _.extend(this.propTarget, Backbone.Events);
this.listenTo( this.target, 'change:selectedComponent targetClassAdded', this.targetUpdated); this.listenTo( this.target, 'change:selectedComponent targetClassAdded targetClassRemoved targetClassUpdated', this.targetUpdated);
}, },

1
test/runner/main.js

@ -14,6 +14,7 @@ require(['../src/config/require-config.js', 'config/config.js'], function() {
'specs/dom_components/main.js', 'specs/dom_components/main.js',
'specs/class_manager/main.js', 'specs/class_manager/main.js',
'specs/css_composer/main.js', 'specs/css_composer/main.js',
'specs/code_manager/main.js',
], function(chai) ], function(chai)
{ {
var should = chai.should(), var should = chai.should(),

25
test/specs/class_manager/view/ClassTagView.js

@ -12,16 +12,19 @@ define([path + 'ClassTagView', 'ClassManager/model/ClassTags'],
}); });
beforeEach(function () { beforeEach(function () {
var coll = new ClassTags(); this.coll = new ClassTags();
this.testLabel = 'TestLabel'; this.testLabel = 'TestLabel';
var model = coll.add({ var model = this.coll.add({
name: 'test', name: 'test',
label: this.testLabel, label: this.testLabel,
}); });
this.view = new ClassTagView({ this.view = new ClassTagView({
config : {}, config : {},
model: model model: model,
coll: this.coll
}); });
this.view.target = { get:function(){} };
_.extend(this.view.target, Backbone.Events);
this.$fixture.empty().appendTo(this.$fixtures); this.$fixture.empty().appendTo(this.$fixtures);
this.$fixture.html(this.view.render().el); this.$fixture.html(this.view.render().el);
}); });
@ -73,6 +76,14 @@ define([path + 'ClassTagView', 'ClassManager/model/ClassTags'],
this.$fixture.html().should.be.empty; this.$fixture.html().should.be.empty;
}); });
it('On remove triggers event', function() {
var spy = sinon.spy();
sinon.stub(this.view.target, 'get').returns(0);
this.view.target.on("targetClassRemoved", spy);
this.view.$el.find('#close').trigger('click');
spy.called.should.equal(true);
});
it('Checkbox toggles status', function() { it('Checkbox toggles status', function() {
var spy = sinon.spy(); var spy = sinon.spy();
this.view.model.on("change:active", spy); this.view.model.on("change:active", spy);
@ -82,6 +93,14 @@ define([path + 'ClassTagView', 'ClassManager/model/ClassTags'],
spy.called.should.equal(true); spy.called.should.equal(true);
}); });
it('On toggle triggers event', function() {
var spy = sinon.spy();
sinon.stub(this.view.target, 'get').returns(0);
this.view.target.on("targetClassUpdated", spy);
this.view.$el.find('#checkbox').trigger('click');
spy.called.should.equal(true);
});
it('Label toggles status', function() { it('Label toggles status', function() {
var spy = sinon.spy(); var spy = sinon.spy();
this.view.model.on("change:active", spy); this.view.model.on("change:active", spy);

39
test/specs/code_manager/main.js

@ -0,0 +1,39 @@
var modulePath = './../../../test/specs/code_manager';
define([
'CodeManager',
modulePath + '/model/CodeModels',
//modulePath + '/view/ClassTagView',
//modulePath + '/view/ClassTagsView',
//modulePath + '/e2e/ClassManager'
],
function(
CodeManager,
Models
) {
describe('Code Manager', function() {
describe('Main', function() {
beforeEach(function () {
this.obj = new CodeManager();
});
afterEach(function () {
delete this.obj;
});
it('Object exists', function() {
CodeManager.should.be.exist;
});
});
Models.run();
//ClassTagView.run();
//ClassTagsView.run();
//e2e.run();
});
});

106
test/specs/code_manager/model/CodeModels.js

@ -0,0 +1,106 @@
var path = 'CodeManager/model/';
define([path + 'HtmlGenerator',
path + 'CssGenerator',
'DomComponents/model/Component',
'CssComposer'],
function(HtmlGenerator, CssGenerator, Component, CssComposer) {
return {
run : function(){
describe('HtmlGenerator', function() {
beforeEach(function () {
this.obj = new HtmlGenerator();
});
afterEach(function () {
delete this.obj;
});
it('Build correctly one component', function() {
var comp = new Component();
this.obj.build(comp).should.equal('');
});
it('Build correctly empty component inside', function() {
var comp = new Component();
var m1 = comp.get('components').add({});
this.obj.build(comp).should.equal('<div></div>');
});
it('Build correctly not empty component inside', function() {
var comp = new Component();
var m1 = comp.get('components').add({
tagName: 'article',
attributes: {
'data-test1': 'value1',
'data-test2': 'value2'
}
});
this.obj.build(comp).should.equal('<article data-test1="value1" data-test2="value2"></article>');
});
it('Build correctly component with classes', function() {
var comp = new Component();
var m1 = comp.get('components').add({
tagName: 'article',
attributes: {
'data-test1': 'value1',
'data-test2': 'value2'
}
});
['class1', 'class2'].forEach(function(item){
m1.get('classes').add({name: item});
});
this.obj.build(comp).should.equal('<article class="class1 class2" data-test1="value1" data-test2="value2"></article>');
});
});
describe('CssGenerator', function() {
beforeEach(function () {
this.obj = new CssGenerator();
});
afterEach(function () {
delete this.obj;
});
it('Build correctly one component', function() {
var comp = new Component();
this.obj.build(comp).should.equal('');
});
it('Build correctly empty component inside', function() {
var comp = new Component();
var m1 = comp.get('components').add({tagName: 'article'});
this.obj.build(comp).should.equal('');
});
it('Build correctly component with style inside', function() {
var comp = new Component();
var m1 = comp.get('components').add({
tagName: 'article',
style: {
'prop1': 'value1',
'prop2': 'value2'
}
});
this.obj.build(comp).should.equal('#' + m1.cid +'{prop1:value1;prop2:value2;}');
});
it('Build correctly component with class styled', function() {
var comp = new Component();
var m1 = comp.get('components').add({tagName: 'article'});
var cls1 = m1.get('classes').add({name: 'class1'});
var cssc = new CssComposer();
var rule = cssc.newRule(cls1);
rule.set('style',{'prop1':'value1', 'prop2':'value2'});
cssc.addRule(rule);
this.obj.build(comp, cssc).should.equal('.class1{prop1:value1;prop2:value2;}');
});
})
}
};
});
Loading…
Cancel
Save