mirror of https://github.com/artf/grapesjs.git
nocodeframeworkdrag-and-dropsite-buildersite-generatortemplate-builderui-builderweb-builderweb-builder-frameworkwebsite-builderno-codepage-builder
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
128 lines
3.1 KiB
128 lines
3.1 KiB
import { isString, isArray, keys, isUndefined } from 'underscore';
|
|
import { shallowDiff } from '../../utils/mixins';
|
|
import ParserHtml from '../../parser/model/ParserHtml';
|
|
import { Model } from '../../common';
|
|
|
|
export default class StyleableModel extends Model {
|
|
parseStyle = ParserHtml().parseStyle;
|
|
|
|
/**
|
|
* To trigger the style change event on models I have to
|
|
* pass a new object instance
|
|
* @param {Object} prop
|
|
* @return {Object}
|
|
*/
|
|
extendStyle(prop) {
|
|
return { ...this.getStyle(), ...prop };
|
|
}
|
|
|
|
/**
|
|
* Get style object
|
|
* @return {Object}
|
|
*/
|
|
getStyle(prop) {
|
|
const style = this.get('style') || {};
|
|
const result = { ...style };
|
|
return prop && isString(prop) ? result[prop] : result;
|
|
}
|
|
|
|
/**
|
|
* Set new style object
|
|
* @param {Object|string} prop
|
|
* @param {Object} opts
|
|
* @return {Object} Applied properties
|
|
*/
|
|
setStyle(prop = {}, opts = {}) {
|
|
if (isString(prop)) {
|
|
prop = this.parseStyle(prop);
|
|
}
|
|
|
|
const propOrig = this.getStyle(opts);
|
|
const propNew = { ...prop };
|
|
const newStyle = { ...propNew };
|
|
// Remove empty style properties
|
|
keys(newStyle).forEach(prop => {
|
|
if (newStyle[prop] === '') {
|
|
delete newStyle[prop];
|
|
}
|
|
});
|
|
this.set('style', newStyle, opts);
|
|
const diff = shallowDiff(propOrig, propNew);
|
|
// Delete the property used for partial updates
|
|
delete diff.__p;
|
|
keys(diff).forEach(pr => {
|
|
const em = this.em;
|
|
if (opts.noEvent) return;
|
|
this.trigger(`change:style:${pr}`);
|
|
if (em) {
|
|
em.trigger('styleable:change', this, pr, opts);
|
|
em.trigger(`styleable:change:${pr}`, this, pr, opts);
|
|
}
|
|
});
|
|
|
|
return propNew;
|
|
}
|
|
|
|
/**
|
|
* Add style property
|
|
* @param {Object|string} prop
|
|
* @param {string} value
|
|
* @example
|
|
* this.addStyle({color: 'red'});
|
|
* this.addStyle('color', 'blue');
|
|
*/
|
|
addStyle(prop, value = '', opts = {}) {
|
|
if (typeof prop == 'string') {
|
|
prop = {
|
|
prop: value,
|
|
};
|
|
} else {
|
|
opts = value || {};
|
|
}
|
|
|
|
prop = this.extendStyle(prop);
|
|
this.setStyle(prop, opts);
|
|
}
|
|
|
|
/**
|
|
* Remove style property
|
|
* @param {string} prop
|
|
*/
|
|
removeStyle(prop) {
|
|
let style = this.getStyle();
|
|
delete style[prop];
|
|
this.setStyle(style);
|
|
}
|
|
|
|
/**
|
|
* Returns string of style properties
|
|
* @param {Object} [opts={}] Options
|
|
* @return {String}
|
|
*/
|
|
styleToString(opts = {}) {
|
|
const result = [];
|
|
const style = this.getStyle(opts);
|
|
|
|
for (let prop in style) {
|
|
const imp = opts.important;
|
|
const important = isArray(imp) ? imp.indexOf(prop) >= 0 : imp;
|
|
const value = `${style[prop]}${important ? ' !important' : ''}`;
|
|
const propPrv = prop.substr(0, 2) == '__';
|
|
value && !propPrv && result.push(`${prop}:${value};`);
|
|
}
|
|
|
|
return result.join('');
|
|
}
|
|
|
|
getSelectors() {
|
|
return this.get('selectors') || this.get('classes');
|
|
}
|
|
|
|
getSelectorsString(opts) {
|
|
return this.selectorsToString ? this.selectorsToString(opts) : this.getSelectors().getFullString();
|
|
}
|
|
|
|
_validate(attr, opts) {
|
|
return true;
|
|
}
|
|
}
|
|
|