Browse Source

Add `setAttributes`, `getAttributes`, `setClass` and `addClass` to Component

pull/437/head
Artur Arseniev 9 years ago
parent
commit
f87e924ce5
  1. 70
      src/dom_components/model/Component.js
  2. 6
      src/dom_components/model/ComponentText.js
  3. 9
      src/dom_components/view/ComponentTextView.js
  4. 10
      src/domain_abstract/model/Styleable.js
  5. 29
      src/selector_manager/index.js
  6. 74
      test/specs/dom_components/model/Component.js
  7. 31
      test/specs/selector_manager/index.js

70
src/dom_components/model/Component.js

@ -69,7 +69,7 @@ module.exports = Backbone.Model.extend(Styleable).extend({
icon: '',
// Component related style
style: {},
style: '',
// Key-value object of the component's attributes
attributes: '',
@ -98,7 +98,7 @@ module.exports = Backbone.Model.extend(Styleable).extend({
},
initialize(props = {}, opt = {}) {
const em = opt.sm || {};
const em = opt.sm || opt.em || {};
// Check void elements
if(opt && opt.config &&
@ -108,6 +108,7 @@ module.exports = Backbone.Model.extend(Styleable).extend({
this.opt = opt;
this.sm = em;
this.em = em;
this.config = props;
this.set('attributes', this.get('attributes') || {});
this.listenTo(this, 'change:script', this.scriptUpdated);
@ -132,6 +133,71 @@ module.exports = Backbone.Model.extend(Styleable).extend({
this.init();
},
/**
* Update attributes of the model
* @param {Object} attrs Key value attributes
* @example
* model.setAttributes({id: 'test', 'data-key': 'value'});
*/
setAttributes(attrs) {
attrs = { ...attrs };
// Handle classes
const classes = attrs.class;
classes && this.setClass(classes);
delete attrs.class;
// Handle style
const style = attrs.style;
style && this.setStyle(style);
delete attrs.style;
this.set('attributes', attrs);
},
/**
* Return attributes
* @return {Object}
*/
getAttributes() {
return this.get('attributes');
},
/**
* Add classes
* @param {Array|string} classes Array or string of classes
* @return {Array} Array of added selectors
* @example
* model.addClass('class1');
* model.addClass('class1 class2');
* model.addClass(['class1', 'class2']);
* // -> [SelectorObject, ...]
*/
addClass(classes) {
const added = this.em.get('SelectorManager').addClass(classes);
return this.get('classes').add(added);
},
/**
* Set classes (resets current collection)
* @param {Array|string} classes Array or string of classes
* @return {Array} Array of added selectors
* @example
* model.setClass('class1');
* model.setClass('class1 class2');
* model.setClass(['class1', 'class2']);
* // -> [SelectorObject, ...]
*/
setClass(classes) {
this.get('classes').reset();
return this.addClass(classes);
},
initClasses() {
const classes = this.normalizeClasses(this.get('classes') || this.config.classes || []);
this.set('classes', new Selectors(classes));

6
src/dom_components/model/ComponentText.js

@ -1,11 +1,11 @@
var Component = require('./Component');
const Component = require('./Component');
module.exports = Component.extend({
defaults: _.extend({}, Component.prototype.defaults, {
defaults: { ...Component.prototype.defaults,
type: 'text',
droppable: false,
editable: true,
}),
},
});

9
src/dom_components/view/ComponentTextView.js

@ -23,14 +23,13 @@ module.exports = ComponentView.extend({
* @private
* */
enableEditing() {
if (this.rteEnabled) {
const rte = this.rte;
if (this.rteEnabled || !this.model.get('editable')) {
return;
}
const editable = this.model.get('editable');
const rte = this.rte;
if (rte && editable) {
if (rte) {
try {
this.activeRte = rte.enable(this, this.activeRte);
} catch (err) {

10
src/domain_abstract/model/Styleable.js

@ -1,3 +1,7 @@
import { isString } from 'underscore';
import ParserHtml from 'parser/model/ParserHtml';
const parseStyle = ParserHtml().parseStyle;
export default {
/**
@ -20,10 +24,14 @@ export default {
/**
* Set new style object
* @param {Object} prop
* @param {Object|string} prop
* @param {Object} opts
*/
setStyle(prop = {}, opts = {}) {
if (isString(prop)) {
prop = parseStyle(prop);
}
this.set('style', Object.assign({}, prop), opts);
},

29
src/selector_manager/index.js

@ -1,8 +1,4 @@
/**
* * [add](#add)
* * [get](#get)
* * [getAll](#getall)
*
* Selectors in GrapesJS are used in CSS Composer inside Rules and in Components as classes. To get better this concept let's take
* a look at this code:
*
@ -52,6 +48,9 @@
* statesLabel: '- Selecte State -',
* }
*/
import { isString } from 'underscore'
module.exports = config => {
var c = config || {},
defaults = require('./config/config'),
@ -139,6 +138,28 @@ module.exports = config => {
return selector;
},
/**
* Add class selectors
* @param {Array|string} classes Array or string of classes
* @return {Array} Array of added selectors
* @example
* sm.addClass('class1');
* sm.addClass('class1 class2');
* sm.addClass(['class1', 'class2']);
* // -> [SelectorObject, ...]
*/
addClass(classes) {
const added = [];
if (isString(classes)) {
classes = classes.trim().split(' ');
}
classes.forEach(name => added.push(selectors.add({name})))
return added;
},
/**
* Get the selector by its name
* @param {String} name Selector name

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

@ -6,18 +6,22 @@ const ComponentLink = require('dom_components/model/ComponentLink');
const ComponentMap = require('dom_components/model/ComponentMap');
const ComponentVideo = require('dom_components/model/ComponentVideo');
const Components = require('dom_components/model/Components');
const Selector = require('selector_manager/model/Selector');
const Editor = require('editor/model/Editor');
const $ = Backbone.$;
module.exports = {
run() {
var obj;
var dcomp;
var compOpts;
let obj;
let dcomp;
let compOpts;
let em;
describe('Component', () => {
beforeEach(() => {
obj = new Component();
em = new Editor({});
obj = new Component({}, {em});
dcomp = new DomComponents();
compOpts = {
componentTypes: dcomp.componentTypes,
@ -116,6 +120,68 @@ module.exports = {
expect(obj).toEqual({tagName: 'span'});
});
it('setClass single class string', () => {
obj.setClass('class1');
const result = obj.get('classes').models;
expect(result.length).toEqual(1);
expect(result[0] instanceof Selector).toEqual(true);
expect(result[0].get('name')).toEqual('class1');
});
it('setClass multiple class string', () => {
obj.setClass('class1 class2');
const result = obj.get('classes').models;
expect(result.length).toEqual(2);
});
it('setClass single class array', () => {
obj.setClass(['class1']);
const result = obj.get('classes').models;
expect(result.length).toEqual(1);
});
it('setClass multiple class array', () => {
obj.setClass(['class1', 'class2']);
const result = obj.get('classes').models;
expect(result.length).toEqual(2);
});
it('addClass multiple array', () => {
obj.addClass(['class1', 'class2']);
const result = obj.get('classes').models;
expect(result.length).toEqual(2);
});
it('addClass avoid same name classes', () => {
obj.addClass(['class1', 'class2']);
obj.addClass(['class1', 'class3']);
const result = obj.get('classes').models;
expect(result.length).toEqual(3);
});
it('setAttributes', () => {
obj.setAttributes({
id: 'test',
'data-test': 'value',
class: 'class1 class2',
style: 'color: white; background: #fff'
});
expect(obj.getAttributes()).toEqual({
id: 'test',
'data-test': 'value',
});
expect(obj.get('classes').length).toEqual(2);
expect(obj.getStyle()).toEqual({
color: 'white',
background: '#fff',
});
});
it('setAttributes overwrites correctly', () => {
obj.setAttributes({id: 'test', 'data-test': 'value'});
obj.setAttributes({'data-test': 'value2'});
expect(obj.getAttributes()).toEqual({'data-test': 'value2'});
});
});
describe('Image Component', () => {

31
test/specs/selector_manager/index.js

@ -1,4 +1,5 @@
var SelectorManager = require('selector_manager');
var Selector = require('selector_manager/model/Selector');
var Models = require('./model/SelectorModels');
var ClassTagView = require('./view/ClassTagView');
var ClassTagsView = require('./view/ClassTagsView');
@ -75,6 +76,36 @@ describe('SelectorManager', () => {
expect(obj.get('test')).toEqual(undefined);
});
it('addClass single class string', () => {
const result = obj.addClass('class1');
expect(result.length).toEqual(1);
expect(result[0] instanceof Selector).toEqual(true);
expect(result[0].get('name')).toEqual('class1');
});
it('addClass multiple class string', () => {
const result = obj.addClass('class1 class2');
expect(result.length).toEqual(2);
expect(obj.getAll().length).toEqual(2);
});
it('addClass single class array', () => {
const result = obj.addClass(['class1']);
expect(result.length).toEqual(1);
});
it('addClass multiple class array', () => {
const result = obj.addClass(['class1', 'class2']);
expect(result.length).toEqual(2);
});
it('addClass Avoid same name classes', () => {
obj.addClass('class1');
const result = obj.addClass('class1');
expect(obj.getAll().length).toEqual(1);
expect(result.length).toEqual(1);
});
});
Models.run();

Loading…
Cancel
Save