Browse Source

Updated `SelectorManager.add` method, now it can receive an array of selectors to add

pull/1730/head
Artur Arseniev 8 years ago
parent
commit
9e61bea2ac
  1. 22
      src/css_composer/index.js
  2. 2
      src/parser/index.js
  3. 2
      src/parser/model/BrowserParserCss.js
  4. 57
      src/selector_manager/index.js
  5. 2
      src/selector_manager/model/Selectors.js
  6. 11
      test/specs/css_composer/index.js
  7. 46
      test/specs/selector_manager/index.js

22
src/css_composer/index.js

@ -382,6 +382,28 @@ module.exports = () => {
return selector && this.get(selector, state, media); return selector && this.get(selector, state, media);
}, },
setRule(selectors, style, opts = {}) {
const node = em.get('Parser').parserCss.checkNode({
selectors,
style,
atRule: null,
params: null
})[0];
const sm = em.get('SelectorManager');
const selector = sm.add(node.selectors);
const rule = this.add(selector, node.state);
rule.setStyle(style, opts);
throw rule.toCSS();
return rule;
},
getRule(selectors, opts = {}) {
const sm = em.get('SelectorManager');
const node = em.get('Parser').parserCss.checkNode({ selectors })[0];
const selector = sm.get(node.selectors);
return selector && this.get(selector, node.state);
},
/** /**
* Render the block of CSS rules * Render the block of CSS rules
* @return {HTMLElement} * @return {HTMLElement}

2
src/parser/index.js

@ -48,6 +48,8 @@ module.exports = () => {
pHtml = new parserHtml(conf); pHtml = new parserHtml(conf);
pCss = new parserCss(conf); pCss = new parserCss(conf);
this.em = conf.em; this.em = conf.em;
this.parserCss = pCss;
this.parserHtml = pHtml;
return this; return this;
}, },

2
src/parser/model/BrowserParserCss.js

@ -101,7 +101,7 @@ export const parseCondition = node => {
* @param {Object} style Key-value object of style declarations * @param {Object} style Key-value object of style declarations
* @return {Object} * @return {Object}
*/ */
export const createNode = (selectors, style, opts = {}) => { export const createNode = (selectors, style = {}, opts = {}) => {
const node = {}; const node = {};
const selLen = selectors.length; const selLen = selectors.length;
const lastClass = selectors[selLen - 1]; const lastClass = selectors[selLen - 1];

57
src/selector_manager/index.js

@ -44,7 +44,7 @@
* @module SelectorManager * @module SelectorManager
*/ */
import { isString, isElement, isObject } from 'underscore'; import { isString, isElement, isObject, isArray } from 'underscore';
const isId = str => isString(str) && str[0] == '#'; const isId = str => isString(str) && str[0] == '#';
const isClass = str => isString(str) && str[0] == '.'; const isClass = str => isString(str) && str[0] == '.';
@ -118,22 +118,9 @@ module.exports = config => {
} }
}, },
/** addSelector(name, opt = {}) {
* Add a new selector to collection if it's not already exists. Class type is a default one let opts = { ...opt };
* @param {String} name Selector name
* @param {Object} opts Selector options
* @param {String} [opts.label=''] Label for the selector, if it's not provided the label will be the same as the name
* @param {String} [opts.type=1] Type of the selector. At the moment, only 'class' (1) is available
* @return {Model}
* @example
* var selector = selectorManager.add('selectorName');
* // Same as
* var selector = selectorManager.add('selectorName', {
* type: 1,
* label: 'selectorName'
* });
* */
add(name, opts = {}) {
if (isObject(name)) { if (isObject(name)) {
opts = name; opts = name;
} else { } else {
@ -143,6 +130,8 @@ module.exports = config => {
if (isId(opts.name)) { if (isId(opts.name)) {
opts.name = opts.name.substr(1); opts.name = opts.name.substr(1);
opts.type = Selector.TYPE_ID; opts.type = Selector.TYPE_ID;
} else if (isClass(opts.name)) {
opts.name = opts.name.substr(1);
} }
if (opts.label && !opts.name) { if (opts.label && !opts.name) {
@ -161,6 +150,31 @@ module.exports = config => {
return selector; return selector;
}, },
/**
* Add a new selector to collection if it's not already exists. Class type is a default one
* @param {String|Array} name Selector/s name
* @param {Object} opts Selector options
* @param {String} [opts.label=''] Label for the selector, if it's not provided the label will be the same as the name
* @param {String} [opts.type=1] Type of the selector. At the moment, only 'class' (1) is available
* @return {Model|Array}
* @example
* const selector = selectorManager.add('selectorName');
* // Same as
* const selector = selectorManager.add('selectorName', {
* type: 1,
* label: 'selectorName'
* });
* // Multiple selectors
* const selectors = selectorManager.add(['.class1', '.class2', '#id1']);
* */
add(name, opts = {}) {
if (isArray(name)) {
return name.map(item => this.addSelector(item, opts));
} else {
return this.addSelector(name, opts);
}
},
/** /**
* Add class selectors * Add class selectors
* @param {Array|string} classes Array or string of classes * @param {Array|string} classes Array or string of classes
@ -178,7 +192,14 @@ module.exports = config => {
classes = classes.trim().split(' '); classes = classes.trim().split(' ');
} }
classes.forEach(name => added.push(selectors.add({ name }))); classes.forEach(name =>
added.push(
selectors.add({
name,
type: Selector.TYPE_ID
})
)
);
return added; return added;
}, },

2
src/selector_manager/model/Selectors.js

@ -4,6 +4,8 @@ const Selector = require('./Selector');
module.exports = require('backbone').Collection.extend({ module.exports = require('backbone').Collection.extend({
model: Selector, model: Selector,
modelId: attr => `${attr.name}_${attr.type}`,
getStyleable() { getStyleable() {
return filter( return filter(
this.models, this.models,

11
test/specs/css_composer/index.js

@ -7,7 +7,7 @@ const utils = require('./../test_utils.js');
const Editor = require('editor/model/Editor'); const Editor = require('editor/model/Editor');
describe('Css Composer', () => { describe('Css Composer', () => {
describe('Main', () => { describe.only('Main', () => {
var obj; var obj;
var em; var em;
var config; var config;
@ -207,6 +207,15 @@ describe('Css Composer', () => {
const rule = obj.getClassRule(name, { state }); const rule = obj.getClassRule(name, { state });
expect(rule.selectorsToString()).toEqual(`.${name}:${state}`); expect(rule.selectorsToString()).toEqual(`.${name}:${state}`);
}); });
test('Create a simple class-based rule with setRule', () => {
const selector = '.test';
obj.setRule(selector, { color: 'red' });
expect(obj.getAll().length).toEqual(1);
const rule = obj.getRule(selector);
expect(rule.selectorsToString()).toEqual(selector);
expect(rule.styleToString()).toEqual(`color:red;`);
});
}); });
Models.run(); Models.run();

46
test/specs/selector_manager/index.js

@ -60,6 +60,13 @@ describe('SelectorManager', () => {
expect(sel.get('label')).toEqual(name); expect(sel.get('label')).toEqual(name);
}); });
test('Check name property by adding as class', () => {
var name = 'test';
var sel = obj.add(`.${name}`);
expect(sel.get('name')).toEqual(name);
expect(sel.get('label')).toEqual(name);
});
test('Add 2 selectors', () => { test('Add 2 selectors', () => {
obj.add('test'); obj.add('test');
obj.add('test2'); obj.add('test2');
@ -72,6 +79,45 @@ describe('SelectorManager', () => {
expect(obj.getAll().length).toEqual(1); expect(obj.getAll().length).toEqual(1);
}); });
test('Add multiple selectors', () => {
const result = obj.add([
'.test1',
'test1',
'.test2',
'.test2',
'#test3',
'test3',
'test3',
'#test3'
]);
expect(Array.isArray(result)).toEqual(true);
expect(obj.getAll().length).toEqual(4);
expect(
obj
.getAll()
.at(0)
.getFullName()
).toEqual('.test1');
expect(
obj
.getAll()
.at(1)
.getFullName()
).toEqual('.test2');
expect(
obj
.getAll()
.at(2)
.getFullName()
).toEqual('#test3');
expect(
obj
.getAll()
.at(3)
.getFullName()
).toEqual('.test3');
});
test('Get selector', () => { test('Get selector', () => {
var name = 'test'; var name = 'test';
var sel = obj.add(name); var sel = obj.add(name);

Loading…
Cancel
Save