Browse Source

Merge branch 'external-style' into dev

pull/540/head
Artur Arseniev 9 years ago
parent
commit
e2f51079e1
  1. 1
      src/code_manager/index.js
  2. 149
      src/code_manager/model/CssGenerator.js
  3. 43
      src/css_composer/index.js
  4. 76
      src/css_composer/model/CssRule.js
  5. 24
      src/css_composer/model/Selectors.js
  6. 76
      src/css_composer/view/CssRuleView.js
  7. 148
      src/dom_components/model/Component.js
  8. 26
      src/dom_components/model/Components.js
  9. 65
      src/dom_components/view/ComponentView.js
  10. 39
      src/domain_abstract/model/Styleable.js
  11. 6
      src/editor/config/config.js
  12. 8
      src/editor/index.js
  13. 30
      src/editor/model/Editor.js
  14. 11
      src/selector_manager/index.js
  15. 18
      src/selector_manager/model/Selector.js
  16. 6
      src/selector_manager/model/Selectors.js
  17. 36
      src/selector_manager/view/ClassTagsView.js
  18. 2
      src/storage_manager/config/config.js
  19. 10
      src/style_manager/index.js
  20. 97
      src/style_manager/view/SectorsView.js
  21. 57
      test/specs/code_manager/model/CodeModels.js
  22. 5
      test/specs/css_composer/e2e/CssComposer.js
  23. 38
      test/specs/css_composer/index.js
  24. 24
      test/specs/css_composer/model/CssModels.js
  25. 20
      test/specs/css_composer/view/CssRuleView.js
  26. 4
      test/specs/dom_components/index.js
  27. 1
      test/specs/dom_components/model/Component.js
  28. 8
      test/specs/dom_components/view/ComponentV.js
  29. 34
      test/specs/grapesjs/index.js
  30. 2
      test/specs/selector_manager/index.js
  31. 21
      test/specs/selector_manager/model/SelectorModels.js
  32. 13
      test/specs/selector_manager/view/ClassTagsView.js
  33. 14
      test/specs/style_manager/view/PropertyColorView.js
  34. 12
      test/specs/style_manager/view/PropertyCompositeView.js
  35. 14
      test/specs/style_manager/view/PropertyIntegerView.js
  36. 14
      test/specs/style_manager/view/PropertyRadioView.js
  37. 12
      test/specs/style_manager/view/PropertySelectView.js
  38. 12
      test/specs/style_manager/view/PropertyStackView.js
  39. 12
      test/specs/style_manager/view/PropertyView.js

1
src/code_manager/index.js

@ -182,6 +182,7 @@ module.exports = () => {
* var codeStr = codeManager.getCode(model, 'html'); * var codeStr = codeManager.getCode(model, 'html');
* */ * */
getCode(model, genId, opt = {}) { getCode(model, genId, opt = {}) {
opt.em = c.em;
var generator = this.getGenerator(genId); var generator = this.getGenerator(genId);
return generator ? generator.build(model, opt) : ''; return generator ? generator.build(model, opt) : '';
}, },

149
src/code_manager/model/CssGenerator.js

@ -1,107 +1,82 @@
var Backbone = require('backbone'); import { keys } from 'underscore';
module.exports = Backbone.Model.extend({ module.exports = require('backbone').Model.extend({
initialize() { initialize() {
this.compCls = []; this.compCls = [];
this.ids = [];
}, },
/** /**
* Get CSS from component * Get CSS from a component
* @param {Model} model * @param {Model} model
* @return {String} * @return {String}
*/ */
buildFromModel(model, opts = {}) { buildFromModel(model, opts = {}) {
var code = ''; let code = '';
var style = model.get('style'); const em = this.em;
var classes = model.get('classes'); const avoidInline = em && em.getConfig('avoidInlineStyle');
const style = model.get('style');
const classes = model.get('classes');
const wrappesIsBody = opts.wrappesIsBody; const wrappesIsBody = opts.wrappesIsBody;
this.ids.push(`#${model.getId()}`);
// Let's know what classes I've found // Let's know what classes I've found
if(classes) { classes.each(model => this.compCls.push(model.getFullName()));
classes.each(function(model){
this.compCls.push(model.get('name'));
}, this);
}
if(style && Object.keys(style).length !== 0) { if (style && keys(style).length && !avoidInline) {
let selector = `#${model.getId()}`; let selector = `#${model.getId()}`;
selector = wrappesIsBody && model.get('wrapper') ? selector = wrappesIsBody && model.get('wrapper') ? 'body' : selector;
'body' : selector; code = `${selector}{${model.styleToString()}}`;
code += `${selector}{`;
for(var prop in style){
if(style.hasOwnProperty(prop))
code += prop + ':' + style[prop] + ';';
}
code += '}';
} }
const components = model.components();
components.each(model => code += this.buildFromModel(model, opts));
return code; return code;
}, },
/**
* Get CSS from components
* @param {Model} model
* @return {String}
*/
buildFromComp(model) {
var coll = model.get('components') || model,
code = '';
coll.each(function(m) {
var cln = m.get('components');
code += this.buildFromModel(m);
if(cln.length){
code += this.buildFromComp(cln);
}
}, this);
return code;
},
/** @inheritdoc */
build(model, opts = {}) { build(model, opts = {}) {
const cssc = opts.cssc; const cssc = opts.cssc;
this.em = opts.em || '';
this.compCls = []; this.compCls = [];
this.ids = [];
var code = this.buildFromModel(model, opts); var code = this.buildFromModel(model, opts);
code += this.buildFromComp(model);
var compCls = this.compCls;
if (cssc) { if (cssc) {
var rules = cssc.getAll(); const rules = cssc.getAll();
var mediaRules = {}; const mediaRules = {};
rules.each(function(rule) {
var width = rule.get('mediaText'); rules.each(rule => {
const media = rule.get('mediaText');
// If width setted will render it later
if(width){ // If media is setted, I'll render it later
var mRule = mediaRules[width]; if (media) {
if(mRule) const mRules = mediaRules[media];
mRule.push(rule); if (mRules) {
else mRules.push(rule);
mediaRules[width] = [rule]; } else {
mediaRules[media] = [rule];
}
return; return;
} }
code += this.buildFromRule(rule); code += this.buildFromRule(rule);
}, this); });
// Get media rules // Get media rules
for (var ruleW in mediaRules) { for (let media in mediaRules) {
var meRules = mediaRules[ruleW]; let rulesStr = '';
var ruleC = ''; const mRules = mediaRules[media];
for(var i = 0, len = meRules.length; i < len; i++){ mRules.forEach(rule => rulesStr += this.buildFromRule(rule));
ruleC += this.buildFromRule(meRules[i]);
}
if (ruleC) { if (rulesStr) {
code += '@media ' + ruleW + '{' + ruleC + '}'; code += `@media ${media}{${rulesStr}}`;
} }
} }
} }
return code; return code;
}, },
@ -111,39 +86,25 @@ module.exports = Backbone.Model.extend({
* @return {string} CSS string * @return {string} CSS string
*/ */
buildFromRule(rule) { buildFromRule(rule) {
var result = ''; let result = '';
var selectorsAdd = rule.get('selectorsAdd'); const selectorStr = rule.selectorsToString();
var selectors = rule.get('selectors'); const selectorStrNoAdd = rule.selectorsToString({skipAdd: 1});
var ruleStyle = rule.get('style'); let found;
var state = rule.get('state');
var strSel = ''; // This will not render a rule if there is no its component
var found = 0; rule.get('selectors').each(selector => {
var compCls = this.compCls; const name = selector.getFullName();
if (this.compCls.indexOf(name) >= 0 || this.ids.indexOf(name) >= 0) {
// Get string of selectors
selectors.each(selector => {
strSel += '.' + selector.get('name');
if(compCls.indexOf(selector.get('name')) > -1)
found = 1; found = 1;
}
}); });
// With 'found' will skip rules which selectors are not found in if ((selectorStrNoAdd && found) || rule.get('selectorsAdd')) {
// canvas components. const style = rule.styleToString();
if ((strSel && found) || selectorsAdd) {
strSel += state ? ':' + state : '';
strSel += selectorsAdd ? (strSel ? ', ' : '') + selectorsAdd : '';
var strStyle = '';
// Get string of style properties
if(ruleStyle && Object.keys(ruleStyle).length !== 0){
for(var prop2 in ruleStyle){
if(ruleStyle.hasOwnProperty(prop2))
strStyle += prop2 + ':' + ruleStyle[prop2] + ';';
}
}
if(strStyle) if (style) {
result += strSel + '{' + strStyle + '}'; result += `${selectorStr}{${style}}`;
}
} }
return result; return result;

43
src/css_composer/index.js

@ -1,9 +1,12 @@
/** /**
* * [add](#add) * * [add](#add)
* * [get](#get) * * [get](#get)
* * [set](#set)
* * [getAll](#getall) * * [getAll](#getall)
* * [load](#load) * * [load](#load)
* * [store](#store) * * [store](#store)
* * [setIdRule](#setidrule)
* * [getIdRule](#getidrule)
* *
* This module contains and manage CSS rules for the template inside the canvas * This module contains and manage CSS rules for the template inside the canvas
* Before using the methods you should get first the module from the editor instance, in this way: * Before using the methods you should get first the module from the editor instance, in this way:
@ -23,12 +26,14 @@
*/ */
module.exports = () => { module.exports = () => {
let em;
var c = {}, var c = {},
defaults = require('./config/config'), defaults = require('./config/config'),
CssRule = require('./model/CssRule'), CssRule = require('./model/CssRule'),
CssRules = require('./model/CssRules'), CssRules = require('./model/CssRules'),
Selectors = require('./model/Selectors'),
CssRulesView = require('./view/CssRulesView'); CssRulesView = require('./view/CssRulesView');
const Selectors = require('selector_manager/model/Selectors');
const Selector = require('selector_manager/model/Selector');
var rules, rulesView; var rules, rulesView;
@ -78,6 +83,7 @@ module.exports = () => {
c.rules = elStyle || c.rules; c.rules = elStyle || c.rules;
c.sm = c.em; c.sm = c.em;
em = c.em;
rules = new CssRules([], c); rules = new CssRules([], c);
rulesView = new CssRulesView({ rulesView = new CssRulesView({
collection: rules, collection: rules,
@ -270,6 +276,39 @@ module.exports = () => {
return result; return result;
}, },
/**
* Add/update a css rule with id selector
* @param {string} name Id selector name, eg. 'my-id'
* @param {Object} style Style properties and values
* @param {Object} [opts={}] Custom options
* @return {CssRule}
*/
setIdRule(name, style = {}, opts = {}) {
const state = opts.state || '';
const media = opts.mediaText || em.getCurrentMedia();
const sm = em.get('SelectorManager');
const selector = sm.add({ name, type: Selector.TYPE_ID });
const rule = this.add(selector, state, media);
rule.setStyle(style, opts);
return rule;
},
/**
* Get css rule by id selector
* @param {string} name Id selector name, eg. 'my-id'
* @param {Object} [opts={}] Custom options
* @return {CssRule}
*/
getIdRule(name, opts = {}) {
const state = opts.state || '';
const media = opts.mediaText || em.getCurrentMedia();
const selector = em.get('SelectorManager').get(name, Selector.TYPE_ID);
return selector && this.get(selector, state, media);
},
/** /**
* Render the block of CSS rules * Render the block of CSS rules
* @return {HTMLElement} * @return {HTMLElement}
@ -277,7 +316,7 @@ module.exports = () => {
*/ */
render() { render() {
return rulesView.render().el; return rulesView.render().el;
} },
}; };
}; };

76
src/css_composer/model/CssRule.js

@ -1,7 +1,7 @@
import Styleable from 'domain_abstract/model/Styleable'; import Styleable from 'domain_abstract/model/Styleable';
var Backbone = require('backbone'); var Backbone = require('backbone');
var Selectors = require('./Selectors'); var Selectors = require('selector_manager/model/Selectors');
module.exports = Backbone.Model.extend(Styleable).extend({ module.exports = Backbone.Model.extend(Styleable).extend({
@ -23,26 +23,72 @@ module.exports = Backbone.Model.extend(Styleable).extend({
// Indicates if the rule is stylable // Indicates if the rule is stylable
stylable: true, stylable: true,
// If true, sets '!important' on all properties
// You can use an array to specify properties to set important
// Used in view
important: 0,
}, },
initialize(c, opt = {}) { initialize(c, opt = {}) {
this.config = c || {}; this.config = c || {};
const em = opt.em; const em = opt.em;
let selectors = this.config.selectors || []; let selectors = this.config.selectors || [];
this.em = em; this.em = em;
if (em) { if (em) {
const sm = em.get('SelectorManager'); const sm = em.get('SelectorManager');
const slct = []; const slct = [];
selectors.forEach((selector) => { selectors.forEach((selector) => {
slct.push(sm.add(selector)); slct.push(sm.add(selector));
}); });
selectors = slct; selectors = slct;
} }
this.set('selectors', new Selectors(selectors));
},
/**
* Return selectors fo the rule as a string
* @return {string}
*/
selectorsToString(opts = {}) {
const result = [];
const state = this.get('state');
const addSelector = this.get('selectorsAdd');
const selectors = this.get('selectors').getFullString();
const stateStr = state ? `:${state}` : '';
selectors && result.push(`${selectors}${stateStr}`);
addSelector && !opts.skipAdd && result.push(addSelector);
return result.join(', ');
},
/**
* Returns CSS string of the rule
* @param {Object} [opts={}] Options
* @return {string}
*/
toCSS(opts = {}) {
let result = '';
const media = this.get('mediaText');
const style = this.styleToString(opts);
const selectors = this.selectorsToString();
if (selectors && style) {
result = `${selectors}{${style}}`;
}
this.set('selectors', new Selectors(selectors)); if (media && result) {
result = `@media ${media}{${result}}`;
}
return result;
}, },
/** /**
* Compare the actual model with parameters * Compare the actual model with parameters
* @param {Object} selectors Collection of selectors * @param {Object} selectors Collection of selectors

24
src/css_composer/model/Selectors.js

@ -1,24 +0,0 @@
var Backbone = require('backbone');
module.exports = Backbone.Collection.extend({
initialize(models, opt) {
this.model = function(attrs, opts) {
var model;
switch(1){
default:
if(!this.ClassTag)
this.ClassTag = require("selector_manager/model/Selector");
model = new this.ClassTag(attrs, opts);
}
return model;
};
},
});

76
src/css_composer/view/CssRuleView.js

@ -1,76 +1,22 @@
var Backbone = require('backbone'); module.exports = require('backbone').View.extend({
module.exports = Backbone.View.extend({
tagName: 'style', tagName: 'style',
initialize(o) {
this.config = o.config || {};
this.listenTo(this.model, 'change:style', this.render);
this.listenTo(this.model, 'change:state', this.render);
this.listenTo(this.model, 'destroy remove', this.remove);
this.listenTo(this.model, 'change:mediaText', this.render);
this.listenTo(this.model.get('selectors'), 'change', this.selChanged);
},
/**
* Triggered when some selector is changed
* @private
*/
selChanged() {
this.selStr = this.renderSelectors();
this.render();
},
/** initialize(o = {}) {
* Returns string of selectors this.config = o.config || {};
* @return {String} const model = this.model;
* @private const toTrack = 'change:style change:state change:mediaText';
*/ this.listenTo(model, toTrack, this.render);
renderSelectors() { this.listenTo(model, 'destroy remove', this.remove);
var sel = []; this.listenTo(model.get('selectors'), 'change', this.render);
var model = this.model;
var add = model.get('selectorsAdd');
model.get('selectors').each(m => {
sel.push('.' + m.get('name'));
});
var sels = sel.join('');
return sels + (sels && add ? ', ' : '') + add;
}, },
/**
* Returns string of properties
* @return {String}
* @private
*/
renderProperties() {
var sel = [],
props = this.model.get('style');
for (var prop in props){
sel.push(prop + ':' + props[prop] + ';');
}
return sel.join('');
},
render() { render() {
var block = '', const model = this.model;
selStr = '', const important = model.get('important');
o = ''; this.el.innerHTML = this.model.toCSS({important});
if(!this.selStr)
this.selStr = this.renderSelectors();
var prpStr = this.renderProperties();
var stateStr = this.model.get('state');
var mediaText = this.model.get('mediaText');
if(this.selStr){
stateStr = stateStr ? ':' + stateStr : '';
block = prpStr !== '' ? '{' + prpStr + '}' : '';
}
o = this.selStr && block ? this.selStr + stateStr + block : '';
if(mediaText && o)
o = '@media ' + mediaText + '{' + o + '}';
this.$el.html(o);
return this; return this;
}, },

148
src/dom_components/model/Component.js

@ -1,10 +1,10 @@
import { isUndefined, isArray } from 'underscore'; import { isUndefined, isArray, isEmpty, has, clone } from 'underscore';
import Styleable from 'domain_abstract/model/Styleable'; import Styleable from 'domain_abstract/model/Styleable';
var Backbone = require('backbone'); const Backbone = require('backbone');
var Components = require('./Components'); const Components = require('./Components');
var Selectors = require('selector_manager/model/Selectors'); const Selectors = require('selector_manager/model/Selectors');
var Traits = require('trait_manager/model/Traits'); const Traits = require('trait_manager/model/Traits');
const escapeRegExp = (str) => { const escapeRegExp = (str) => {
return str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'); return str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&');
@ -121,7 +121,7 @@ module.exports = Backbone.Model.extend(Styleable).extend({
initialize(props = {}, opt = {}) { initialize(props = {}, opt = {}) {
const em = opt.sm || opt.em || {}; const em = opt.sm || opt.em || '';
// Propagate properties from parent if indicated // Propagate properties from parent if indicated
const parent = this.parent(); const parent = this.parent();
@ -150,7 +150,7 @@ module.exports = Backbone.Model.extend(Styleable).extend({
this.opt = opt; this.opt = opt;
this.sm = em; this.sm = em;
this.em = em; this.em = em;
this.config = props; this.config = opt.config || {};
this.set('attributes', this.get('attributes') || {}); this.set('attributes', this.get('attributes') || {});
this.listenTo(this, 'change:script', this.scriptUpdated); this.listenTo(this, 'change:script', this.scriptUpdated);
this.listenTo(this, 'change:traits', this.traitsUpdated); this.listenTo(this, 'change:traits', this.traitsUpdated);
@ -158,18 +158,6 @@ module.exports = Backbone.Model.extend(Styleable).extend({
this.initClasses(); this.initClasses();
this.initComponents(); this.initComponents();
this.initToolbar(); this.initToolbar();
// Normalize few properties from strings to arrays
var toNormalize = ['stylable'];
toNormalize.forEach(function(name) {
var value = this.get(name);
if (typeof value == 'string') {
var newValue = value.split(',').map(prop => prop.trim());
this.set(name, newValue);
}
}, this);
this.set('status', ''); this.set('status', '');
this.init(); this.init();
}, },
@ -198,12 +186,58 @@ module.exports = Backbone.Model.extend(Styleable).extend({
}, },
getStyle() {
const em = this.em;
if (em && em.getConfig('avoidInlineStyle')) {
const state = this.get('state');
const cc = em.get('CssComposer');
const rule = cc.getIdRule(this.getId(), { state });
this.rule = rule;
if (rule) {
return rule.getStyle();
}
}
return Styleable.getStyle.call(this);
},
setStyle(prop = {}, opts = {}) {
const em = this.em;
if (em && em.getConfig('avoidInlineStyle')) {
prop = Styleable.setStyle.call(this, prop, {silent: 1, avoidStore: 1});
const state = this.get('state');
const cc = em.get('CssComposer');
this.rule = cc.setIdRule(this.getId(), prop, { ...opts, state });
} else {
prop = Styleable.setStyle.apply(this, arguments);
}
return prop;
},
/** /**
* Return attributes * Return attributes
* @return {Object} * @return {Object}
*/ */
getAttributes() { getAttributes() {
return this.get('attributes'); const classes = [];
const attributes = this.get('attributes') || {};
// Add classes
this.get('classes').each(cls => classes.push(cls.get('name')));
classes.length && (attributes.class = classes.join(' '));
// If style is not empty I need an ID attached to the component
if (!isEmpty(this.getStyle()) && !has(attributes, 'id')) {
attributes.id = this.getId();
}
return attributes;
}, },
@ -240,7 +274,7 @@ module.exports = Backbone.Model.extend(Styleable).extend({
initClasses() { initClasses() {
const classes = this.normalizeClasses(this.get('classes') || this.config.classes || []); const classes = this.normalizeClasses(this.get('classes') || []);
this.set('classes', new Selectors(classes)); this.set('classes', new Selectors(classes));
return this; return this;
}, },
@ -329,7 +363,7 @@ module.exports = Backbone.Model.extend(Styleable).extend({
*/ */
traitsUpdated() { traitsUpdated() {
let found = 0; let found = 0;
const attrs = Object.assign({}, this.get('attributes')); const attrs = { ...this.get('attributes') };
const traits = this.get('traits'); const traits = this.get('traits');
if (!(traits instanceof Traits)) { if (!(traits instanceof Traits)) {
@ -442,21 +476,21 @@ module.exports = Backbone.Model.extend(Styleable).extend({
* @private * @private
*/ */
clone(reset) { clone(reset) {
var attr = _.clone(this.attributes), const em = this.em;
comp = this.get('components'), const style = this.getStyle();
traits = this.get('traits'), const attr = clone(this.attributes);
cls = this.get('classes'); delete attr.attributes.id;
attr.components = []; attr.components = [];
attr.classes = []; attr.classes = [];
attr.traits = []; attr.traits = [];
comp.each((md, i) => { this.get('components').each((md, i) => {
attr.components[i] = md.clone(1); attr.components[i] = md.clone(1);
}); });
traits.each((md, i) => { this.get('traits').each((md, i) => {
attr.traits[i] = md.clone(); attr.traits[i] = md.clone();
}); });
cls.each((md, i) => { this.get('classes').each((md, i) => {
attr.classes[i] = md.get('name'); attr.classes[i] = md.get('name');
}); });
@ -467,6 +501,10 @@ module.exports = Backbone.Model.extend(Styleable).extend({
this.opt.collection = null; this.opt.collection = null;
} }
if (em && em.getConfig('avoidInlineStyle') && !isEmpty(style)) {
attr.style = style;
}
return new this.constructor(attr, this.opt); return new this.constructor(attr, this.opt);
}, },
@ -502,43 +540,25 @@ module.exports = Backbone.Model.extend(Styleable).extend({
* @private * @private
*/ */
toHTML(opts) { toHTML(opts) {
var code = ''; const model = this;
var m = this; const attrs = [];
var tag = m.get('tagName'); const classes = [];
var idFound = 0; const tag = model.get('tagName');
var sTag = m.get('void'); const sTag = model.get('void');
var attrId = ''; const attributes = this.getAttrToHTML();
var strAttr = '';
var attr = this.getAttrToHTML(); for (let attr in attributes) {
const value = attributes[attr];
for (var prop in attr) {
if (prop == 'id') { if (!isUndefined(value) && value !== '') {
idFound = 1; attrs.push(`${attr}="${value}"`);
} }
var val = attr[prop];
strAttr += typeof val !== undefined && val !== '' ?
' ' + prop + '="' + val + '"' : '';
} }
// Build the string of classes let attrString = attrs.length ? ` ${attrs.join(' ')}` : '';
var strCls = ''; let code = `<${tag}${attrString}${sTag ? '/' : ''}>${model.get('content')}`;
m.get('classes').each(m => { model.get('components').each(comp => code += comp.toHTML());
strCls += ' ' + m.get('name'); !sTag && (code += `</${tag}>`);
});
strCls = strCls !== '' ? ' class="' + strCls.trim() + '"' : '';
// If style is not empty I need an ID attached to the component
if(!_.isEmpty(m.get('style')) && !idFound)
attrId = ' id="' + m.getId() + '" ';
code += '<' + tag + strCls + attrId + strAttr + (sTag ? '/' : '') + '>' + m.get('content');
m.get('components').each(m => {
code += m.toHTML();
});
if(!sTag)
code += '</'+tag+'>';
return code; return code;
}, },
@ -550,7 +570,7 @@ module.exports = Backbone.Model.extend(Styleable).extend({
* @private * @private
*/ */
getAttrToHTML() { getAttrToHTML() {
var attr = this.get('attributes') || {}; var attr = this.getAttributes();
delete attr.style; delete attr.style;
return attr; return attr;
}, },

26
src/dom_components/model/Components.js

@ -1,4 +1,6 @@
var Backbone = require('backbone'); import { isEmpty } from 'underscore';
const Backbone = require('backbone');
module.exports = Backbone.Collection.extend({ module.exports = Backbone.Collection.extend({
@ -67,16 +69,18 @@ module.exports = Backbone.Collection.extend({
}, },
onAdd(model, c, opts) { onAdd(model, c, opts) {
var style = model.get('style'); const em = this.editor;
var em = this.editor; const style = model.get('style');
const avoidInline = em && em.getConfig('avoidInlineStyle');
if (!_.isEmpty(style) && em && em.get && em.get('Config').forceClass) {
var cssC = this.editor.get('CssComposer'); if (!isEmpty(style) && !avoidInline &&
var newClass = this.editor.get('SelectorManager').add(model.cid); em && em.get && em.get('Config').forceClass) {
model.set({style:{}}); var cssC = this.editor.get('CssComposer');
model.get('classes').add(newClass); var newClass = this.editor.get('SelectorManager').add(model.cid);
var rule = cssC.add(newClass); model.set({style:{}});
rule.set('style', style); model.get('classes').add(newClass);
var rule = cssC.add(newClass);
rule.set('style', style);
} }
}, },

65
src/dom_components/view/ComponentView.js

@ -1,3 +1,5 @@
import { isArray } from 'underscore';
const ComponentsView = require('./ComponentsView'); const ComponentsView = require('./ComponentsView');
module.exports = Backbone.View.extend({ module.exports = Backbone.View.extend({
@ -10,13 +12,14 @@ module.exports = Backbone.View.extend({
return this.model.get('tagName'); return this.model.get('tagName');
}, },
initialize(opt) { initialize(opt = {}) {
const model = this.model; const model = this.model;
this.opts = opt || {}; const config = opt.config || {};
this.config = this.opts.config || {}; this.opts = opt;
this.em = this.config.em || ''; this.config = config;
this.pfx = this.config.stylePrefix || ''; this.em = config.em || '';
this.ppfx = this.config.pStylePrefix || ''; this.pfx = config.stylePrefix || '';
this.ppfx = config.pStylePrefix || '';
this.attr = model.get('attributes'); this.attr = model.get('attributes');
this.classe = this.attr.class || []; this.classe = this.attr.class || [];
const $el = this.$el; const $el = this.$el;
@ -64,6 +67,7 @@ module.exports = Backbone.View.extend({
} }
}, },
/** /**
* Import, if possible, classes inside main container * Import, if possible, classes inside main container
* @private * @private
@ -78,6 +82,7 @@ module.exports = Backbone.View.extend({
} }
}, },
/** /**
* Fires on state update. If the state is not empty will add a helper class * Fires on state update. If the state is not empty will add a helper class
* @param {Event} e * @param {Event} e
@ -94,6 +99,7 @@ module.exports = Backbone.View.extend({
} }
}, },
/** /**
* Update item on status change * Update item on status change
* @param {Event} e * @param {Event} e
@ -131,6 +137,7 @@ module.exports = Backbone.View.extend({
} }
}, },
/** /**
* Update highlight attribute * Update highlight attribute
* @private * @private
@ -140,14 +147,24 @@ module.exports = Backbone.View.extend({
this.setAttribute('data-highlightable', hl ? 1 : ''); this.setAttribute('data-highlightable', hl ? 1 : '');
}, },
/** /**
* Update style attribute * Update style attribute
* @private * @private
* */ * */
updateStyle() { updateStyle() {
this.setAttribute('style', this.getStyleString()); const em = this.em;
const model = this.model;
if (em && em.get('avoidInlineStyle')) {
this.el.id = model.getId();
model.setStyle(model.getStyle());
} else {
this.setAttribute('style', model.styleToString());
}
}, },
/** /**
* Update classe attribute * Update classe attribute
* @private * @private
@ -180,10 +197,13 @@ module.exports = Backbone.View.extend({
getClasses() { getClasses() {
var attr = this.model.get("attributes"), var attr = this.model.get("attributes"),
classes = attr['class'] || []; classes = attr['class'] || [];
if(classes.length){ classes = isArray(classes) ? classes : [classes];
return classes.join(" ");
}else if (classes.length) {
return classes.join(' ');
} else {
return null; return null;
}
}, },
/** /**
@ -214,31 +234,6 @@ module.exports = Backbone.View.extend({
this.getChildrenContainer().innerHTML = this.model.get('content'); this.getChildrenContainer().innerHTML = this.model.get('content');
}, },
/**
* Return style string
* @return {string}
* @private
* */
getStyleString() {
var style = '';
this.style = this.model.get('style');
for(var key in this.style) {
if(this.style.hasOwnProperty(key))
style += key + ':' + this.style[key] + ';';
}
return style;
},
/**
* Reply to event call
* @param object Event that generated the request
* @private
* */
eventCall(event) {
event.viewResponse = this;
},
/** /**
* Prevent default helper * Prevent default helper
* @param {Event} e * @param {Event} e

39
src/domain_abstract/model/Styleable.js

@ -1,9 +1,11 @@
import { isString } from 'underscore'; import { isString, isArray } from 'underscore';
import ParserHtml from 'parser/model/ParserHtml'; import ParserHtml from 'parser/model/ParserHtml';
const parseStyle = ParserHtml().parseStyle; const parseStyle = ParserHtml().parseStyle;
export default { export default {
parseStyle,
/** /**
* To trigger the style change event on models I have to * To trigger the style change event on models I have to
* pass a new object instance * pass a new object instance
@ -11,34 +13,40 @@ export default {
* @return {Object} * @return {Object}
*/ */
extendStyle(prop) { extendStyle(prop) {
return Object.assign({}, this.getStyle(), prop); return { ...this.getStyle(), ...prop};
}, },
/** /**
* Get style object * Get style object
* @return {Object} * @return {Object}
*/ */
getStyle() { getStyle() {
return Object.assign({}, this.get('style')); return { ...this.get('style') };
}, },
/** /**
* Set new style object * Set new style object
* @param {Object|string} prop * @param {Object|string} prop
* @param {Object} opts * @param {Object} opts
* @return {Object} Applied properties
*/ */
setStyle(prop = {}, opts = {}) { setStyle(prop = {}, opts = {}) {
if (isString(prop)) { if (isString(prop)) {
prop = parseStyle(prop); prop = parseStyle(prop);
} }
this.set('style', Object.assign({}, prop), opts); this.set('style', { ...prop }, opts);
for (let pr in prop) { for (let pr in prop) {
this.trigger(`change:style:${pr}`); this.trigger(`change:style:${pr}`);
} }
return prop;
}, },
/** /**
* Add style property * Add style property
* @param {Object|string} prop * @param {Object|string} prop
@ -60,6 +68,7 @@ export default {
this.setStyle(prop, opts); this.setStyle(prop, opts);
}, },
/** /**
* Remove style property * Remove style property
* @param {string} prop * @param {string} prop
@ -68,5 +77,25 @@ export default {
let style = this.getStyle(); let style = this.getStyle();
delete style[prop]; delete style[prop];
this.setStyle(style); this.setStyle(style);
} },
/**
* Returns string of style properties
* @param {Object} [opts={}] Options
* @return {String}
*/
styleToString(opts = {}) {
const result = [];
const style = this.getStyle();
for (let prop in style) {
const imp = opts.important;
const important = isArray(imp) ? imp.indexOf(prop) >= 0 : imp;
const value = `${style[prop]}${important ? ' !important' : ''}`;
result.push(`${prop}:${value};`);
}
return result.join('');
},
} }

6
src/editor/config/config.js

@ -71,6 +71,12 @@ module.exports = {
// The wrapper, if visible, will be shown as a `<body>` // The wrapper, if visible, will be shown as a `<body>`
wrappesIsBody: 1, wrappesIsBody: 1,
// Usually when you update the `style` of the component this changes the
// element's `style` attribute. Unfortunately, inline styling doesn't allow
// use of media queries (@media) or even pseudo selectors (eg. :hover).
// When `avoidInlineStyle` is true all styles are inserted inside the css rule
avoidInlineStyle: 0,
// Dom element // Dom element
el: '', el: '',

8
src/editor/index.js

@ -238,10 +238,12 @@ module.exports = config => {
/** /**
* Returns configuration object * Returns configuration object
* @return {Object} * @param {string} [prop] Property name
* @return {any} Returns the configuration object or
* the value of the specified property
*/ */
getConfig() { getConfig(prop) {
return c; return em.getConfig(prop);
}, },
/** /**

30
src/editor/model/Editor.js

@ -47,7 +47,7 @@ module.exports = Backbone.Model.extend({
device: '', device: '',
}, },
initialize(c) { initialize(c = {}) {
this.config = c; this.config = c;
this.set('Config', c); this.set('Config', c);
this.set('modules', []); this.set('modules', []);
@ -66,6 +66,19 @@ module.exports = Backbone.Model.extend({
this.on('change:changesCount', this.updateChanges, this); this.on('change:changesCount', this.updateChanges, this);
}, },
/**
* Get configurations
* @param {string} [prop] Property name
* @return {any} Returns the configuration object or
* the value of the specified property
*/
getConfig(prop) {
const config = this.config;
return isUndefined(prop) ? config : config[prop];
},
/** /**
* Should be called after all modules and plugins are loaded * Should be called after all modules and plugins are loaded
* @param {Function} clb * @param {Function} clb
@ -614,6 +627,21 @@ module.exports = Backbone.Model.extend({
w.getSelection().removeAllRanges(); w.getSelection().removeAllRanges();
}, },
/**
* Get the current media text
* @return {string}
*/
getCurrentMedia() {
const config = this.config;
const device = this.getDeviceModel();
const condition = config.mediaCondition;
const preview = config.devicePreviewMode;
const width = device && device.get('widthMedia');
return device && width && !preview ? `(${condition}: ${width})` : '';
},
/** /**
* Set/get data from the HTMLElement * Set/get data from the HTMLElement
* @param {HTMLElement} el * @param {HTMLElement} el

11
src/selector_manager/index.js

@ -61,6 +61,10 @@ module.exports = config => {
return { return {
Selector,
Selectors,
/** /**
* Name of the module * Name of the module
* @type {String} * @type {String}
@ -129,7 +133,7 @@ module.exports = config => {
} }
const cname = opts.name; const cname = opts.name;
const selector = cname ? this.get(cname) : selectors.where(opts)[0]; const selector = cname ? this.get(cname, opts.type) : selectors.where(opts)[0];
if (!selector) { if (!selector) {
return selectors.add(opts); return selectors.add(opts);
@ -163,12 +167,13 @@ module.exports = config => {
/** /**
* Get the selector by its name * Get the selector by its name
* @param {String} name Selector name * @param {String} name Selector name
* @param {String} tyoe Selector type
* @return {Model|null} * @return {Model|null}
* @example * @example
* var selector = selectorManager.get('selectorName'); * var selector = selectorManager.get('selectorName');
* */ * */
get(name) { get(name, type = Selector.TYPE_CLASS) {
return selectors.where({name})[0]; return selectors.where({name, type})[0];
}, },
/** /**

18
src/selector_manager/model/Selector.js

@ -1,15 +1,19 @@
var Backbone = require('backbone'); var Backbone = require('backbone');
const TYPE_CLASS = 1;
const TYPE_ID = 2;
const Selector = Backbone.Model.extend({ const Selector = Backbone.Model.extend({
idAttribute: 'name', idAttribute: 'name',
defaults: { defaults: {
name: '', name: '',
label: '', label: '',
// Type of the selector // Type of the selector
type: 'class', type: TYPE_CLASS,
// If not active it's not selectable by the style manager (uncheckboxed) // If not active it's not selectable by the style manager (uncheckboxed)
active: true, active: true,
@ -18,7 +22,7 @@ const Selector = Backbone.Model.extend({
// Will be rendered only in export code // Will be rendered only in export code
private: false, private: false,
// If true, can't be removed by the user, from the attacched element // If true, can't be removed from the attacched element
protected: false, protected: false,
}, },
@ -43,10 +47,10 @@ const Selector = Backbone.Model.extend({
let init = ''; let init = '';
switch (this.get('type')) { switch (this.get('type')) {
case 'class': case TYPE_CLASS:
init = '.'; init = '.';
break; break;
case 'id': case TYPE_ID:
init = '#'; init = '#';
break; break;
} }
@ -55,6 +59,12 @@ const Selector = Backbone.Model.extend({
} }
}, { }, {
// All type selectors: https://developer.mozilla.org/it/docs/Web/CSS/CSS_Selectors
// Here I define only what I need
TYPE_CLASS,
TYPE_ID,
/** /**
* Escape string * Escape string
* @param {string} name * @param {string} name

6
src/selector_manager/model/Selectors.js

@ -11,5 +11,11 @@ module.exports = Backbone.Collection.extend({
getValid() { getValid() {
return _.filter(this.models, item => !item.get('private')); return _.filter(this.models, item => !item.get('private'));
},
getFullString() {
const result = [];
this.each(selector => result.push(selector.getFullName()));
return result.join('').trim();
} }
}); });

36
src/selector_manager/view/ClassTagsView.js

@ -33,7 +33,7 @@ module.exports = Backbone.View.extend({
events: {}, events: {},
initialize(o) { initialize(o = {}) {
this.config = o.config || {}; this.config = o.config || {};
this.pfx = this.config.stylePrefix || ''; this.pfx = this.config.stylePrefix || '';
this.ppfx = this.config.pStylePrefix || ''; this.ppfx = this.config.pStylePrefix || '';
@ -48,7 +48,8 @@ module.exports = Backbone.View.extend({
this.events['keyup #' + this.newInputId] = 'onInputKeyUp'; this.events['keyup #' + this.newInputId] = 'onInputKeyUp';
this.events['change #' + this.stateInputId] = 'stateChanged'; this.events['change #' + this.stateInputId] = 'stateChanged';
this.target = this.config.em; this.target = this.config.em;
this.em = this.target;
this.listenTo(this.target ,'change:selectedComponent',this.componentChanged); this.listenTo(this.target ,'change:selectedComponent',this.componentChanged);
this.listenTo(this.target, 'targetClassUpdated', this.updateSelector); this.listenTo(this.target, 'targetClassUpdated', this.updateSelector);
@ -148,38 +149,39 @@ module.exports = Backbone.View.extend({
* @private * @private
*/ */
updateStateVis() { updateStateVis() {
if(this.collection.length) const em = this.em;
const avoidInline = em && em.getConfig('avoidInlineStyle');
if(this.collection.length || avoidInline)
this.getStatesC().css('display','block'); this.getStatesC().css('display','block');
else else
this.getStatesC().css('display','none'); this.getStatesC().css('display','none');
this.updateSelector(); this.updateSelector();
}, },
/** /**
* Udpate selector helper * Udpate selector helper
* @return {this} * @return {this}
* @private * @private
*/ */
updateSelector() { updateSelector() {
const selected = this.target.get('selectedComponent'); const selected = this.target.getSelected();
this.compTarget = selected; this.compTarget = selected;
if(!selected || !selected.get)
return;
var result = '';
this.collection.each(model => {
if(model.get('active'))
result += '.' + model.get('name');
});
var state = selected.get('state');
result = state ? result + ':' + state : result;
result = result || selected.getName();
var el = this.el.querySelector('#' + this.pfx + 'sel');
if (el) { if (!selected || !selected.get) {
el.innerHTML = result; return;
} }
const state = selected.get('state');
let result = this.collection.getFullString();
result = result || `#${selected.getId()}`;
result += state ? `:${state}` : '';
const el = this.el.querySelector('#' + this.pfx + 'sel');
el && (el.innerHTML = result);
}, },
/** /**
* Triggered when the select with states is changed * Triggered when the select with states is changed
* @param {Object} e * @param {Object} e

2
src/storage_manager/config/config.js

@ -24,7 +24,7 @@ module.exports = {
//Enable/Disable saving HTML template //Enable/Disable saving HTML template
storeHtml: 1, storeHtml: 1,
//Enable/Disable saving HTML template //Enable/Disable saving CSS template
storeCss: 1, storeCss: 1,
// ONLY FOR LOCAL STORAGE // ONLY FOR LOCAL STORAGE

10
src/style_manager/index.js

@ -253,13 +253,9 @@ module.exports = () => {
const em = c.em; const em = c.em;
if (em && classes && classes.length) { if (em && classes && classes.length) {
const emConfig = em.get('Config'); const conf = em.get('Config');
const previewMode = emConfig.devicePreviewMode; const state = !conf.devicePreviewMode ? model.get('state') : '';
const device = em.getDeviceModel(); const deviceW = em.getCurrentMedia();
const state = !previewMode ? model.get('state') : '';
const widthMedia = device && device.get('widthMedia');
const deviceW = device && !previewMode && widthMedia ?
`(${emConfig.mediaCondition}: ${widthMedia})` : '';
const cssC = em.get('CssComposer'); const cssC = em.get('CssComposer');
const valid = classes.getStyleable(); const valid = classes.getStyleable();
const CssRule = cssC.get(valid, state, deviceW); const CssRule = cssC.get(valid, state, deviceW);

97
src/style_manager/view/SectorsView.js

@ -9,7 +9,7 @@ module.exports = Backbone.View.extend({
this.pfx = this.config.stylePrefix || ''; this.pfx = this.config.stylePrefix || '';
this.target = o.target || {}; this.target = o.target || {};
// The taget that will emit events for properties // The target that will emit events for properties
const target = {}; const target = {};
extend(target, Backbone.Events); extend(target, Backbone.Events);
const body = document.body; const body = document.body;
@ -18,10 +18,10 @@ module.exports = Backbone.View.extend({
target.computedDefault = { ...window.getComputedStyle(dummy) }; target.computedDefault = { ...window.getComputedStyle(dummy) };
body.removeChild(dummy); body.removeChild(dummy);
this.propTarget = target; this.propTarget = target;
const coll = this.collection;
this.listenTo( this.collection, 'add', this.addTo); this.listenTo(coll, 'add', this.addTo);
this.listenTo( this.collection, 'reset', this.render); this.listenTo(coll, 'reset', this.render);
this.listenTo( this.target, 'change:selectedComponent targetClassAdded targetClassRemoved targetClassUpdated ' + this.listenTo(this.target, 'change:selectedComponent targetClassAdded targetClassRemoved targetClassUpdated ' +
'targetStateUpdated targetStyleUpdated change:device', this.targetUpdated); 'targetStateUpdated targetStyleUpdated change:device', this.targetUpdated);
}, },
@ -42,34 +42,63 @@ module.exports = Backbone.View.extend({
*/ */
targetUpdated() { targetUpdated() {
var em = this.target; var em = this.target;
var el = em.get('selectedComponent'); let model = em.getSelected();
const um = em.get('UndoManager'); const um = em.get('UndoManager');
const cc = em.get('CssComposer');
const avoidInline = em.getConfig('avoidInlineStyle');
if(!el) if (!model) {
return; return;
}
// TODO make use of getModelToStyle here const id = model.getId();
const config = em.get('Config'); const config = em.get('Config');
var previewMode = config.devicePreviewMode; var classes = model.get('classes');
var classes = el.get('classes');
var pt = this.propTarget; var pt = this.propTarget;
var device = em.getDeviceModel(); const state = !config.devicePreviewMode ? model.get('state') : '';
var state = !previewMode ? el.get('state') : ''; const opts = { state };
var widthMedia = device && device.get('widthMedia');
var stateStr = state ? `:${state}` : null; var stateStr = state ? `:${state}` : null;
var view = el.view; var view = model.view;
var mediaText = device && !previewMode && widthMedia ? const media = em.getCurrentMedia();
`(${config.mediaCondition}: ${widthMedia})` : '';
pt.helper = null; pt.helper = null;
if (view) { if (view) {
pt.computed = window.getComputedStyle(view.el, stateStr); pt.computed = window.getComputedStyle(view.el, state ? `:${state}` : null);
}
const appendStateRule = (style = {}) => {
const sm = em.get('SelectorManager');
const helperClass = sm.add('hc-state');
let helperRule = cc.get([helperClass]);
if (!helperRule) {
helperRule = cc.add([helperClass]);
} else {
// I will make it last again, otherwise it could be overridden
const rules = cc.getAll();
rules.remove(helperRule);
rules.add(helperRule);
}
helperRule.set('important', 1);
helperRule.setStyle(style);
pt.helper = helperRule;
};
// If true the model will be always a rule
if (avoidInline) {
const ruleId = cc.getIdRule(id, opts);
if (!ruleId) {
model = cc.setIdRule(id, {}, opts);
} else {
model = ruleId;
}
} }
if (classes.length) { if (classes.length) {
var cssC = em.get('CssComposer');
var valid = classes.getStyleable(); var valid = classes.getStyleable();
var iContainer = cssC.get(valid, state, mediaText); var iContainer = cc.get(valid, state, media);
if (!iContainer && valid.length) { if (!iContainer && valid.length) {
// I stop undo manager here as after adding the CSSRule (generally after // I stop undo manager here as after adding the CSSRule (generally after
@ -77,42 +106,34 @@ module.exports = Backbone.View.extend({
// the collection, therefore updating it in style manager will not affect it // the collection, therefore updating it in style manager will not affect it
// #268 // #268
um.stopTracking(); um.stopTracking();
iContainer = cssC.add(valid, state, mediaText); iContainer = cc.add(valid, state, media);
iContainer.set('style', el.get('style')); iContainer.setStyle(model.getStyle());
el.set('style', {}); model.setStyle({});
um.startTracking(); um.startTracking();
} }
if (!iContainer) { if (!iContainer) {
// In this case it's just a Component without any valid selector // In this case it's just a Component without any valid selector
pt.model = el; pt.model = model;
pt.trigger('update'); pt.trigger('update');
return; return;
} }
// If the state is not empty, there should be a helper rule in play // If the state is not empty, there should be a helper rule in play
// The helper rule will get the same style of the iContainer // The helper rule will get the same style of the iContainer
if (state) { state && appendStateRule(iContainer.getStyle());
var clm = em.get('SelectorManager');
var helperClass = clm.add('hc-state');
var helperRule = cssC.get([helperClass]);
if(!helperRule)
helperRule = cssC.add([helperClass]);
else{
// I will make it last again, otherwise it could be overridden
cssC.getAll().remove(helperRule);
cssC.getAll().add(helperRule);
}
helperRule.set('style', iContainer.get('style'));
pt.helper = helperRule;
}
pt.model = iContainer; pt.model = iContainer;
pt.trigger('update'); pt.trigger('update');
return; return;
} }
pt.model = el; if (state) {
const ruleState = cc.getIdRule(id, opts);
state && appendStateRule(ruleState && ruleState.getStyle());
}
pt.model = model;
pt.trigger('update'); pt.trigger('update');
}, },

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

@ -2,18 +2,24 @@ const CssGenerator = require('code_manager/model/CssGenerator');
const HtmlGenerator = require('code_manager/model/HtmlGenerator'); const HtmlGenerator = require('code_manager/model/HtmlGenerator');
const DomComponents = require('dom_components'); const DomComponents = require('dom_components');
const Component = require('dom_components/model/Component'); const Component = require('dom_components/model/Component');
const Editor = require('editor/model/Editor');
const CssComposer = require('css_composer'); const CssComposer = require('css_composer');
module.exports = { module.exports = {
run() { run() {
let comp; let comp;
let dcomp;
let obj; let obj;
let em;
let cc;
describe('HtmlGenerator', () => { describe('HtmlGenerator', () => {
beforeEach(() => { beforeEach(() => {
em = new Editor();
obj = new HtmlGenerator(); obj = new HtmlGenerator();
var dcomp = new DomComponents(); dcomp = new DomComponents();
comp = new Component({}, { comp = new Component({}, {
em,
componentTypes: dcomp.componentTypes, componentTypes: dcomp.componentTypes,
}); });
}); });
@ -54,16 +60,19 @@ module.exports = {
['class1', 'class2'].forEach(item => { ['class1', 'class2'].forEach(item => {
m1.get('classes').add({name: item}); m1.get('classes').add({name: item});
}); });
expect(obj.build(comp)).toEqual('<article class="class1 class2" data-test1="value1" data-test2="value2"></article>'); expect(obj.build(comp)).toEqual('<article data-test1="value1" data-test2="value2" class="class1 class2"></article>');
}); });
}); });
describe('CssGenerator', () => { describe('CssGenerator', () => {
var newCssComp = () => new CssComposer().init(); var newCssComp = () => new CssComposer().init();
beforeEach(() => { beforeEach(() => {
em = new Editor({});
cc = em.get('CssComposer');
obj = new CssGenerator(); obj = new CssGenerator();
var dcomp = new DomComponents(); dcomp = new DomComponents();
comp = new Component({}, { comp = new Component({}, {
em,
componentTypes: dcomp.componentTypes, componentTypes: dcomp.componentTypes,
}); });
}); });
@ -213,6 +222,48 @@ module.exports = {
comp.get('components').remove(m1); comp.get('components').remove(m1);
expect(obj.build(comp, {cssc})).toEqual(''); expect(obj.build(comp, {cssc})).toEqual('');
}); });
it('Render correctly a rule without avoidInlineStyle option', () => {
comp.setStyle({color: 'red'});
const id = comp.getId();
const result = `#${id}{color:red;}`;
expect(obj.build(comp, {cssc: cc})).toEqual(result);
});
it('Render correctly a rule with avoidInlineStyle option', () => {
em.getConfig().avoidInlineStyle = 1;
comp = new Component({}, {
em,
componentTypes: dcomp.componentTypes,
});
comp.setStyle({color: 'red'});
const id = comp.getId();
const result = `#${id}{color:red;}`;
expect(obj.build(comp, {cssc: cc, em})).toEqual(result);
});
it('Render correctly a rule with avoidInlineStyle and state', () => {
em.getConfig().avoidInlineStyle = 1;
const state = 'hover';
comp.config.avoidInlineStyle = 1;
comp.set('state', state);
comp.setStyle({color: 'red'});
const id = comp.getId();
const result = `#${id}:${state}{color:red;}`;
expect(obj.build(comp, {cssc: cc, em})).toEqual(result);
});
it('Render correctly a rule with avoidInlineStyle and w/o state', () => {
em.getConfig().avoidInlineStyle = 1;
const state = 'hover';
comp.config.avoidInlineStyle = 1;
comp.setStyle({color: 'blue'});
comp.set('state', state);
comp.setStyle({color: 'red'});
const id = comp.getId();
const result = `#${id}{color:blue;}#${id}:${state}{color:red;}`;
expect(obj.build(comp, {cssc: cc, em})).toEqual(result);
});
}) })
} }
}; };

5
test/specs/css_composer/e2e/CssComposer.js

@ -130,10 +130,11 @@ module.exports = {
active: true, active: true,
label: 'test1', label: 'test1',
name: 'test1', name: 'test1',
type: 'class', type: clsm.Selector.TYPE_CLASS,
private: false, private: false,
protected: false, protected: false,
}], }],
important: 0,
selectorsAdd: '', selectorsAdd: '',
state: '', state: '',
stylable: true, stylable: true,
@ -172,6 +173,7 @@ module.exports = {
rule1Out = JSON.parse(JSON.stringify(rule1Out)); rule1Out = JSON.parse(JSON.stringify(rule1Out));
rule2Out = JSON.parse(JSON.stringify(rule2Out)); rule2Out = JSON.parse(JSON.stringify(rule2Out));
var rule1Result = { var rule1Result = {
important: 0,
mediaText: '', mediaText: '',
selectors: [], selectors: [],
selectorsAdd: '*', selectorsAdd: '*',
@ -183,6 +185,7 @@ module.exports = {
} }
}; };
var rule2Result = { var rule2Result = {
important: 0,
mediaText: '', mediaText: '',
selectors: [], selectors: [],
selectorsAdd: 'p', selectorsAdd: 'p',

38
test/specs/css_composer/index.js

@ -1,16 +1,17 @@
var Models = require('./model/CssModels'); const Models = require('./model/CssModels');
var CssRuleView = require('./view/CssRuleView'); const CssRuleView = require('./view/CssRuleView');
var CssRulesView = require('./view/CssRulesView'); const CssRulesView = require('./view/CssRulesView');
var CssComposer = require('css_composer'); const CssComposer = require('css_composer');
var e2e = require('./e2e/CssComposer'); const e2e = require('./e2e/CssComposer');
var utils = require('./../test_utils.js'); const utils = require('./../test_utils.js');
const Editor = require('editor/model/Editor');
describe('Css Composer', () => { describe('Css Composer', () => {
describe('Main', () => { describe('Main', () => {
var obj; var obj;
var em;
var config; var config;
var storagMock = utils.storageMock(); var storagMock = utils.storageMock();
var editorModel = { var editorModel = {
@ -33,7 +34,8 @@ describe('Css Composer', () => {
beforeEach(() => { beforeEach(() => {
config = {}; em = new Editor({});
config = {em};
obj = new CssComposer().init(config); obj = new CssComposer().init(config);
}); });
@ -158,6 +160,26 @@ describe('Css Composer', () => {
expect(obj.render()).toExist(); expect(obj.render()).toExist();
}); });
it('Create a rule with id selector by using setIdRule()', () => {
const name = 'test';
obj.setIdRule(name, {color: 'red'});
expect(obj.getAll().length).toEqual(1);
const rule = obj.getIdRule(name);
expect(rule.selectorsToString()).toEqual(`#${name}`);
expect(rule.styleToString()).toEqual(`color:red;`);
expect(rule.styleToString({important: 1})).toEqual(`color:red !important;`);
expect(rule.styleToString({important: ['color']})).toEqual(`color:red !important;`);
});
it('Create a rule with id selector and state by using setIdRule()', () => {
const name = 'test';
const state = 'hover';
obj.setIdRule(name, {color: 'red'}, {state});
expect(obj.getAll().length).toEqual(1);
const rule = obj.getIdRule(name, {state});
expect(rule.selectorsToString()).toEqual(`#${name}:${state}`);
});
}); });
Models.run(); Models.run();

24
test/specs/css_composer/model/CssModels.js

@ -56,6 +56,30 @@ module.exports = {
expect(obj.compare([s2, s1], 'hover', '1000')).toEqual(true); expect(obj.compare([s2, s1], 'hover', '1000')).toEqual(true);
}); });
it('toCSS returns empty if there is no style', () => {
var s1 = obj.get('selectors').add({ name: 'test1' });
expect(obj.toCSS()).toEqual('');
});
it('toCSS returns empty if there is no selectors', () => {
obj.setStyle({color: 'red'});
expect(obj.toCSS()).toEqual('');
});
it('toCSS returns simple CSS', () => {
obj.get('selectors').add({ name: 'test1' });
obj.setStyle({color: 'red'});
expect(obj.toCSS()).toEqual(`.test1{color:red;}`);
});
it('toCSS wraps correctly inside media rule', () => {
const media = '(max-width: 768px)';
obj.set('mediaText', media);
obj.get('selectors').add({ name: 'test1' });
obj.setStyle({color: 'red'});
expect(obj.toCSS()).toEqual(`@media ${media}{.test1{color:red;}}`);
});
}); });
describe('CssRules', () => { describe('CssRules', () => {

20
test/specs/css_composer/view/CssRuleView.js

@ -26,26 +26,6 @@ module.exports = {
expect(CssRuleView).toExist(); expect(CssRuleView).toExist();
}); });
it('Correct behaviour of renderSelectors with single selector', () => {
obj.model.get('selectors').add({name: 'test'});
expect(obj.renderSelectors()).toEqual('.test');
});
it('Correct behaviour of renderSelectors with multiple selectors', () => {
obj.model.get('selectors').add([{name: 'test2'}, {name: 'test1'}]);
expect(obj.renderSelectors()).toEqual('.test2.test1');
});
it('Correct behaviour of renderProperties with single property', () => {
obj.model.set('style', {'prop': 'value'});
expect(obj.renderProperties()).toEqual('prop:value;');
});
it('Correct behaviour of renderProperties with multiple properties', () => {
obj.model.set('style', {'prop2': 'value2', 'prop3': 'value3'});
expect(obj.renderProperties()).toEqual('prop2:value2;prop3:value3;');
});
it('Empty style inside', function() { it('Empty style inside', function() {
expect(fixtures.innerHTML).toEqual('<style></style>'); expect(fixtures.innerHTML).toEqual('<style></style>');
}); });

4
test/specs/dom_components/index.js

@ -5,12 +5,14 @@ const ComponentView = require('./view/ComponentV');
const ComponentsView = require('./view/ComponentsView'); const ComponentsView = require('./view/ComponentsView');
const ComponentTextView = require('./view/ComponentTextView'); const ComponentTextView = require('./view/ComponentTextView');
const ComponentImageView = require('./view/ComponentImageView'); const ComponentImageView = require('./view/ComponentImageView');
const Editor = require('editor/model/Editor');
const utils = require('./../test_utils.js'); const utils = require('./../test_utils.js');
describe('DOM Components', () => { describe('DOM Components', () => {
describe('Main', () => { describe('Main', () => {
var em;
var obj; var obj;
var config; var config;
var storagMock = utils.storageMock(); var storagMock = utils.storageMock();
@ -39,7 +41,9 @@ describe('DOM Components', () => {
beforeEach(() => { beforeEach(() => {
em = new Editor();
config = { config = {
em,
storeWrapper: 1, storeWrapper: 1,
}; };
obj = new DomComponents().init(config); obj = new DomComponents().init(config);

1
test/specs/dom_components/model/Component.js

@ -169,6 +169,7 @@ module.exports = {
}); });
expect(obj.getAttributes()).toEqual({ expect(obj.getAttributes()).toEqual({
id: 'test', id: 'test',
class: 'class1 class2',
'data-test': 'value', 'data-test': 'value',
}); });
expect(obj.get('classes').length).toEqual(2); expect(obj.get('classes').length).toEqual(2);

8
test/specs/dom_components/view/ComponentV.js

@ -80,14 +80,6 @@ module.exports = {
expect(view.el.getAttribute('style')).toEqual(null); expect(view.el.getAttribute('style')).toEqual(null);
}); });
it('Get style string', () => {
model.set('style', {
color: 'red',
float: 'left'
});
expect(view.getStyleString()).toEqual('color:red;float:left;');
});
it('Add class', () => { it('Add class', () => {
model.get('classes').add({name: 'test'}); model.get('classes').add({name: 'test'});
expect(view.el.getAttribute('class')).toEqual('test'); expect(view.el.getAttribute('class')).toEqual('test');

34
test/specs/grapesjs/index.js

@ -16,11 +16,12 @@ describe('GrapesJS', () => {
var storage; var storage;
var storageId = 'testStorage'; var storageId = 'testStorage';
var storageMock = { var storageMock = {
store(data) { store(data, clb) {
storage = data; storage = data;
clb();
}, },
load(keys) { load(keys, clb) {
return storage; return clb(storage);
}, },
}; };
@ -36,7 +37,8 @@ describe('GrapesJS', () => {
container: '#' + editorName, container: '#' + editorName,
storageManager: { storageManager: {
autoload: 0, autoload: 0,
type:'none' autosave: 0,
type: ''
}, },
} }
obj = grapesjs; obj = grapesjs;
@ -47,11 +49,6 @@ describe('GrapesJS', () => {
fixtures = document.body.querySelector('#fixtures'); fixtures = document.body.querySelector('#fixtures');
}); });
afterEach(() => {
config = {};
obj = null;
});
it('Main object should be loaded', () => { it('Main object should be loaded', () => {
expect(obj).toExist(); expect(obj).toExist();
}); });
@ -76,7 +73,7 @@ describe('GrapesJS', () => {
it('New editor is empty', () => { it('New editor is empty', () => {
var editor = obj.init(config); var editor = obj.init(config);
var html = editor.getHtml(); var html = editor.getHtml();
var css = editor.getCss(); //var css = editor.getCss();
var protCss = editor.getConfig().protectedCss; var protCss = editor.getConfig().protectedCss;
expect((html ? html : '')).toNotExist(); expect((html ? html : '')).toNotExist();
//expect((css ? css : '')).toEqual(protCss); //expect((css ? css : '')).toEqual(protCss);
@ -154,7 +151,7 @@ describe('GrapesJS', () => {
expect(styles.at(1).get('selectors').at(0).get('name')).toEqual('test5'); expect(styles.at(1).get('selectors').at(0).get('name')).toEqual('test5');
}); });
it('Adds new storage as plugin and store data there', () => { it.skip('Adds new storage as plugin and store data there', done => {
var pluginName = storageId + '-plugin'; var pluginName = storageId + '-plugin';
obj.plugins.add(pluginName, edt => { obj.plugins.add(pluginName, edt => {
edt.StorageManager.add(storageId, storageMock); edt.StorageManager.add(storageId, storageMock);
@ -163,9 +160,11 @@ describe('GrapesJS', () => {
config.plugins = [pluginName]; config.plugins = [pluginName];
var editor = obj.init(config); var editor = obj.init(config);
editor.setComponents(htmlString); editor.setComponents(htmlString);
editor.store(); editor.store(() => {
editor.load((data) => { editor.load((data) => {
expect(data.html).toEqual(htmlString); expect(data.html).toEqual(htmlString);
done();
});
}); });
}); });
@ -182,8 +181,7 @@ describe('GrapesJS', () => {
expect(editor.customValue).toEqual('TEST'); expect(editor.customValue).toEqual('TEST');
}); });
// Problems with iframe loading it('Execute custom command', () => {
it.skip('Execute custom command', () => {
var editor = obj.init(config); var editor = obj.init(config);
editor.testVal = ''; editor.testVal = '';
editor.setComponents(htmlString); editor.setComponents(htmlString);
@ -196,7 +194,7 @@ describe('GrapesJS', () => {
expect(editor.testVal).toEqual(htmlString + '5'); expect(editor.testVal).toEqual(htmlString + '5');
}); });
it.skip('Stop custom command', () => { it('Stop custom command', () => {
var editor = obj.init(config); var editor = obj.init(config);
editor.testVal = ''; editor.testVal = '';
editor.setComponents(htmlString); editor.setComponents(htmlString);
@ -231,7 +229,7 @@ describe('GrapesJS', () => {
}); });
// Problems with iframe loading // Problems with iframe loading
it.skip('Init new editor with custom plugin overrides default commands', () => { it('Init new editor with custom plugin overrides default commands', () => {
var editor, var editor,
pluginName = 'test-plugin-opts'; pluginName = 'test-plugin-opts';

2
test/specs/selector_manager/index.js

@ -44,7 +44,7 @@ describe('SelectorManager', () => {
it('Default new selector is a class type', () => { it('Default new selector is a class type', () => {
obj.add('test'); obj.add('test');
expect(obj.get('test').get('type')).toEqual('class'); expect(obj.get('test').get('type')).toEqual(obj.Selector.TYPE_CLASS);
}); });
it('Check name property', () => { it('Check name property', () => {

21
test/specs/selector_manager/model/SelectorModels.js

@ -37,7 +37,13 @@ module.exports = {
}); });
describe('Selectors', () => { describe('Selectors', () => {
var obj;
beforeEach(() => {
obj = new Selectors();
});
it('Creates collection item correctly', () => { it('Creates collection item correctly', () => {
var c = new Selectors(); var c = new Selectors();
@ -45,6 +51,21 @@ module.exports = {
expect(m instanceof Selector).toEqual(true); expect(m instanceof Selector).toEqual(true);
}); });
it('getFullString with single class', () => {
obj.add({name: 'test'});
expect(obj.getFullString()).toEqual('.test');
});
it('getFullString with multiple classes', () => {
obj.add([{name: 'test'}, {name: 'test2'}]);
expect(obj.getFullString()).toEqual('.test.test2');
});
it('getFullString with mixed selectors', () => {
obj.add([{name: 'test'}, {name: 'test2', type: Selector.TYPE_ID}]);
expect(obj.getFullString()).toEqual('.test#test2');
});
}); });
} }
}; };

13
test/specs/selector_manager/view/ClassTagsView.js

@ -1,5 +1,6 @@
const ClassTagsView = require('selector_manager/view/ClassTagsView'); const ClassTagsView = require('selector_manager/view/ClassTagsView');
const Selectors = require('selector_manager/model/Selectors'); const Selectors = require('selector_manager/model/Selectors');
const Editor = require('editor/model/Editor');
module.exports = { module.exports = {
run() { run() {
@ -11,6 +12,7 @@ module.exports = {
var testLabel; var testLabel;
var coll; var coll;
var target; var target;
var em;
before(() => { before(() => {
document.body.innerHTML = '<div id="fixtures"></div>'; document.body.innerHTML = '<div id="fixtures"></div>';
@ -23,10 +25,8 @@ module.exports = {
}); });
beforeEach(function () { beforeEach(function () {
target = { get() {} }; target = new Editor();
coll = new Selectors(); coll = new Selectors();
_.extend(target, Backbone.Events);
view = new ClassTagsView({ view = new ClassTagsView({
config : { em: target }, config : { em: target },
collection: coll collection: coll
@ -74,16 +74,13 @@ module.exports = {
expect(this.input.css('display')).toNotEqual('none'); expect(this.input.css('display')).toNotEqual('none');
}); });
it.skip('Stop tag creation', function() { it('Stop tag creation', function() {
this.btnAdd.trigger('click'); this.btnAdd.trigger('click');
this.input.val('test') this.input.val('test')
this.input.trigger('blur'); this.input.trigger('blur');
//(this.btnAdd.css('display') !== 'none').should.equal(true);
//(this.input.css('display') == 'none').should.equal(true);
//this.input.val().should.equal('');
expect(this.btnAdd.css('display')).toNotEqual('none'); expect(this.btnAdd.css('display')).toNotEqual('none');
expect(this.input.css('display')).toEqual('none'); expect(this.input.css('display')).toEqual('none');
expect(this.input.val()).toEqual(''); expect(this.input.val()).toEqual(null);
}); });
it.skip('Check keyup of ESC on input', function() { it.skip('Check keyup of ESC on input', function() {

14
test/specs/style_manager/view/PropertyColorView.js

@ -1,12 +1,17 @@
const PropertyColorView = require('style_manager/view/PropertyColorView'); const PropertyColorView = require('style_manager/view/PropertyColorView');
const Property = require('style_manager/model/Property'); const Property = require('style_manager/model/Property');
const Component = require('dom_components/model/Component'); const Component = require('dom_components/model/Component');
const Editor = require('editor/model/Editor');
const DomComponents = require('dom_components');
module.exports = { module.exports = {
run() { run() {
describe('PropertyColorView', () => { describe('PropertyColorView', () => {
let em;
let dcomp;
let compOpts;
var component; var component;
var fixtures; var fixtures;
var target; var target;
@ -22,13 +27,16 @@ module.exports = {
}); });
beforeEach(() => { beforeEach(() => {
target = new Component(); em = new Editor({});
component = new Component(); dcomp = new DomComponents();
compOpts = { em, componentTypes: dcomp.componentTypes };
propTarget = Object.assign({}, Backbone.Events);
target = new Component({}, compOpts);
component = new Component({}, compOpts);
model = new Property({ model = new Property({
type: 'color', type: 'color',
property: propName property: propName
}); });
propTarget = Object.assign({}, Backbone.Events);
propTarget.model = component; propTarget.model = component;
view = new PropertyColorView({ view = new PropertyColorView({
model, model,

12
test/specs/style_manager/view/PropertyCompositeView.js

@ -2,12 +2,17 @@ const PropertyCompositeView = require('style_manager/view/PropertyCompositeView'
const Property = require('style_manager/model/Property'); const Property = require('style_manager/model/Property');
const PropertyComposite = require('style_manager/model/PropertyComposite'); const PropertyComposite = require('style_manager/model/PropertyComposite');
const Component = require('dom_components/model/Component'); const Component = require('dom_components/model/Component');
const Editor = require('editor/model/Editor');
const DomComponents = require('dom_components');
module.exports = { module.exports = {
run() { run() {
describe('PropertyCompositeView', () => { describe('PropertyCompositeView', () => {
let em;
let dcomp;
let compOpts;
var component; var component;
var fixtures; var fixtures;
var target; var target;
@ -35,8 +40,11 @@ module.exports = {
}]; }];
beforeEach(() => { beforeEach(() => {
target = new Component(); em = new Editor({});
component = new Component(); dcomp = new DomComponents();
compOpts = { em, componentTypes: dcomp.componentTypes };
target = new Component({}, compOpts);
component = new Component({}, compOpts);
target.model = component; target.model = component;
model = new PropertyComposite({ model = new PropertyComposite({
type: 'composite', type: 'composite',

14
test/specs/style_manager/view/PropertyIntegerView.js

@ -2,12 +2,17 @@ const PropertyIntegerView = require('style_manager/view/PropertyIntegerView');
const Property = require('style_manager/model/Property'); const Property = require('style_manager/model/Property');
const PropertyInteger = require('style_manager/model/PropertyInteger'); const PropertyInteger = require('style_manager/model/PropertyInteger');
const Component = require('dom_components/model/Component'); const Component = require('dom_components/model/Component');
const Editor = require('editor/model/Editor');
const DomComponents = require('dom_components');
module.exports = { module.exports = {
run() { run() {
describe('PropertyIntegerView', () => { describe('PropertyIntegerView', () => {
let em;
let dcomp;
let compOpts;
var component; var component;
var fixtures; var fixtures;
var target; var target;
@ -25,13 +30,16 @@ module.exports = {
var unitsElSel = '.field-units select'; var unitsElSel = '.field-units select';
beforeEach(() => { beforeEach(() => {
target = new Component(); em = new Editor({});
component = new Component(); dcomp = new DomComponents();
compOpts = { em, componentTypes: dcomp.componentTypes };
propTarget = Object.assign({}, Backbone.Events);
target = new Component({}, compOpts);
component = new Component({}, compOpts);
model = new PropertyInteger({ model = new PropertyInteger({
units, units,
property: propName property: propName
}); });
propTarget = Object.assign({}, Backbone.Events);
propTarget.model = component; propTarget.model = component;
view = new PropertyIntegerView({ view = new PropertyIntegerView({
model, model,

14
test/specs/style_manager/view/PropertyRadioView.js

@ -1,12 +1,17 @@
const PropertyRadioView = require('style_manager/view/PropertyRadioView'); const PropertyRadioView = require('style_manager/view/PropertyRadioView');
const Property = require('style_manager/model/Property'); const Property = require('style_manager/model/Property');
const Component = require('dom_components/model/Component'); const Component = require('dom_components/model/Component');
const Editor = require('editor/model/Editor');
const DomComponents = require('dom_components');
module.exports = { module.exports = {
run() { run() {
describe('PropertyRadioView', () => { describe('PropertyRadioView', () => {
let em;
let dcomp;
let compOpts;
var component; var component;
var fixtures; var fixtures;
var target; var target;
@ -27,14 +32,17 @@ module.exports = {
var getCheckedEl = (view) => view.getInputEl().querySelectorAll('input:checked')[0]; var getCheckedEl = (view) => view.getInputEl().querySelectorAll('input:checked')[0];
beforeEach(() => { beforeEach(() => {
target = new Component(); em = new Editor({});
component = new Component(); dcomp = new DomComponents();
compOpts = { em, componentTypes: dcomp.componentTypes };
propTarget = Object.assign({}, Backbone.Events);
target = new Component({}, compOpts);
component = new Component({}, compOpts);
model = new Property({ model = new Property({
type: 'radio', type: 'radio',
list: options, list: options,
property: propName property: propName
}); });
propTarget = Object.assign({}, Backbone.Events);
propTarget.model = component; propTarget.model = component;
view = new PropertyRadioView({ view = new PropertyRadioView({
model, model,

12
test/specs/style_manager/view/PropertySelectView.js

@ -1,5 +1,7 @@
const PropertySelectView = require('style_manager/view/PropertySelectView'); const PropertySelectView = require('style_manager/view/PropertySelectView');
const Property = require('style_manager/model/Property'); const Property = require('style_manager/model/Property');
const Editor = require('editor/model/Editor');
const DomComponents = require('dom_components');
const Component = require('dom_components/model/Component'); const Component = require('dom_components/model/Component');
module.exports = { module.exports = {
@ -7,6 +9,9 @@ module.exports = {
describe('PropertySelectView', () => { describe('PropertySelectView', () => {
let em;
let dcomp;
let compOpts;
var component; var component;
var fixtures; var fixtures;
var target; var target;
@ -23,9 +28,12 @@ module.exports = {
]; ];
beforeEach(() => { beforeEach(() => {
em = new Editor({});
dcomp = new DomComponents();
compOpts = { em, componentTypes: dcomp.componentTypes };
propTarget = Object.assign({}, Backbone.Events); propTarget = Object.assign({}, Backbone.Events);
target = new Component(); target = new Component({}, compOpts);
component = new Component(); component = new Component({}, compOpts);
model = new Property({ model = new Property({
type: 'select', type: 'select',
list: options, list: options,

12
test/specs/style_manager/view/PropertyStackView.js

@ -1,12 +1,17 @@
const PropertyStackView = require('style_manager/view/PropertyStackView'); const PropertyStackView = require('style_manager/view/PropertyStackView');
const Property = require('style_manager/model/PropertyStack'); const Property = require('style_manager/model/PropertyStack');
const Component = require('dom_components/model/Component'); const Component = require('dom_components/model/Component');
const Editor = require('editor/model/Editor');
const DomComponents = require('dom_components');
module.exports = { module.exports = {
run() { run() {
describe('PropertyStackView', () => { describe('PropertyStackView', () => {
let em;
let dcomp;
let compOpts;
var component; var component;
var fixtures; var fixtures;
var target; var target;
@ -41,8 +46,11 @@ module.exports = {
]; ];
beforeEach(() => { beforeEach(() => {
target = new Component(); em = new Editor({});
component = new Component(); dcomp = new DomComponents();
compOpts = { em, componentTypes: dcomp.componentTypes };
target = new Component({}, compOpts);
component = new Component({}, compOpts);
target.model = component; target.model = component;
model = new Property({ model = new Property({
type: 'stack', type: 'stack',

12
test/specs/style_manager/view/PropertyView.js

@ -1,5 +1,7 @@
const PropertyView = require('style_manager/view/PropertyView'); const PropertyView = require('style_manager/view/PropertyView');
const Property = require('style_manager/model/Property'); const Property = require('style_manager/model/Property');
const Editor = require('editor/model/Editor');
const DomComponents = require('dom_components');
const Component = require('dom_components/model/Component'); const Component = require('dom_components/model/Component');
module.exports = { module.exports = {
@ -7,6 +9,9 @@ module.exports = {
describe('PropertyView', () => { describe('PropertyView', () => {
let em;
let dcomp;
let compOpts;
var component; var component;
var fixtures; var fixtures;
var target; var target;
@ -19,9 +24,12 @@ module.exports = {
var defValue = 'testDefault'; var defValue = 'testDefault';
beforeEach(() => { beforeEach(() => {
em = new Editor({});
dcomp = new DomComponents();
compOpts = { em, componentTypes: dcomp.componentTypes };
propTarget = Object.assign({}, Backbone.Events); propTarget = Object.assign({}, Backbone.Events);
target = new Component(); target = new Component({}, compOpts);
component = new Component(); component = new Component({}, compOpts);
model = new Property({property: propName}); model = new Property({property: propName});
propTarget.model = component; propTarget.model = component;
options = { options = {

Loading…
Cancel
Save