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.
188 lines
4.8 KiB
188 lines
4.8 KiB
import { isString } from 'underscore';
|
|
import Property from './Property';
|
|
|
|
export default Property.extend({
|
|
defaults: {
|
|
...Property.prototype.defaults,
|
|
// 'background' is a good example where to make a difference
|
|
// between detached and not
|
|
//
|
|
// - NOT detached (default)
|
|
// background: url(..) no-repeat center ...;
|
|
// - Detached
|
|
// background-image: url();
|
|
// background-repeat: repeat;
|
|
// ...
|
|
detached: 0,
|
|
|
|
// Array of sub properties
|
|
properties: [],
|
|
|
|
// Separator to use to split property values (only for not detached properties)
|
|
separator: ' ',
|
|
|
|
// Separator to use to join property values (only for not detached properties)
|
|
join: null,
|
|
|
|
fromStyle: null,
|
|
|
|
toStyle: null,
|
|
},
|
|
|
|
initialize(props = {}, opts = {}) {
|
|
Property.callParentInit(Property, this, props, opts);
|
|
const { em } = this;
|
|
const Properties = require('./Properties').default;
|
|
const properties = new Properties(this.get('properties') || [], { em, parentProp: this });
|
|
this.set('properties', properties, { silent: 1 });
|
|
this.listenTo(properties, 'change', this.__upProperties);
|
|
this.listenTo(this, 'change:value', this.updateValues);
|
|
Property.callInit(this, props, opts);
|
|
},
|
|
|
|
__upProperties(prop, opts = {}) {
|
|
if (!this.__hasCustom() || opts.__up || opts.__clearIn) return;
|
|
|
|
if (this.isDetached()) {
|
|
this.__upTargetsStyle({ [prop.getName()]: prop.__getFullValue() }, opts);
|
|
} else {
|
|
const { __clear, ...rest } = opts;
|
|
this.upValue(this.__getFullValue(), rest);
|
|
}
|
|
},
|
|
|
|
__upTargetsStyle(style, opts) {
|
|
const toStyle = this.get('toStyle');
|
|
let newStyle = style;
|
|
|
|
if (toStyle && !opts.__clear) {
|
|
const values = this.getValues();
|
|
newStyle = toStyle(values, { ...opts, style });
|
|
}
|
|
|
|
if (!this.isDetached()) {
|
|
this.getProperties().map(prop => {
|
|
newStyle[prop.getName()] = '';
|
|
});
|
|
}
|
|
|
|
return Property.prototype.__upTargetsStyle.call(this, newStyle, opts);
|
|
},
|
|
|
|
__getFullValue(opts = {}) {
|
|
if (this.isDetached() || opts.__clear) {
|
|
return '';
|
|
}
|
|
|
|
return this.getProperties()
|
|
.map(p => p.__getFullValue({ withDefault: 1 }))
|
|
.filter(Boolean)
|
|
.join(this.__getJoin());
|
|
},
|
|
|
|
__getJoin() {
|
|
const join = this.get('join');
|
|
return isString(join) ? join : this.get('separator');
|
|
},
|
|
|
|
clear() {
|
|
this.getProperties().map(p => p.clear({ __clearIn: true }));
|
|
return Property.prototype.clear.call(this);
|
|
},
|
|
|
|
/**
|
|
* Get current values of properties
|
|
* @param {Object} [opts={}] Options
|
|
* @param {Boolean} [opts.byName=false] Use property name as key instead of ID
|
|
* @returns {Object}
|
|
*/
|
|
getValues({ byName } = {}) {
|
|
return this.getProperties().reduce((res, prop) => {
|
|
const key = byName ? prop.getName() : prop.getId();
|
|
res[key] = `${prop.__getFullValue({ withDefault: 1 })}`;
|
|
return res;
|
|
}, {});
|
|
},
|
|
|
|
/**
|
|
* Clear the value
|
|
* @return {this}
|
|
* @deprecated
|
|
*/
|
|
clearValue(opts = {}) {
|
|
this.get('properties').each(property => property.clearValue());
|
|
return Property.prototype.clearValue.apply(this, arguments);
|
|
},
|
|
|
|
/**
|
|
* Update property values
|
|
* @deprecated
|
|
*/
|
|
updateValues() {
|
|
const values = this.getFullValue().split(this.getSplitSeparator());
|
|
this.get('properties').each((property, i) => {
|
|
const len = values.length;
|
|
// Try to get value from a shorthand:
|
|
// 11px -> 11px 11px 11px 11xp
|
|
// 11px 22px -> 11px 22px 11px 22xp
|
|
const value = values[i] || values[(i % len) + (len != 1 && len % 2 ? 1 : 0)];
|
|
// There some issue with UndoManager
|
|
//property.setValue(value, 0, {fromParent: 1});
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Split by sperator but avoid it inside parenthesis
|
|
* @return {RegExp}
|
|
*/
|
|
getSplitSeparator() {
|
|
return new RegExp(`${this.get('separator')}(?![^\\(]*\\))`);
|
|
},
|
|
|
|
/**
|
|
* Returns default value
|
|
* @param {Boolean} defaultProps Force to get defaults from properties
|
|
* @return {string}
|
|
*/
|
|
getDefaultValue(defaultProps) {
|
|
let value = this.get('defaults');
|
|
|
|
if (value && !defaultProps) {
|
|
return value;
|
|
}
|
|
|
|
value = '';
|
|
const properties = this.get('properties');
|
|
properties.each((prop, index) => (value += `${prop.getDefaultValue()} `));
|
|
return value.trim();
|
|
},
|
|
|
|
getFullValue() {
|
|
if (this.get('detached')) {
|
|
return '';
|
|
}
|
|
|
|
return this.get('properties').getFullValue();
|
|
},
|
|
|
|
/**
|
|
* Get property at some index
|
|
* @param {Number} index
|
|
* @return {Object}
|
|
*/
|
|
getPropertyAt(index) {
|
|
return this.get('properties').at(index);
|
|
},
|
|
|
|
isDetached() {
|
|
return !!this.get('detached');
|
|
},
|
|
|
|
getProperties() {
|
|
return [...this.get('properties').models];
|
|
},
|
|
|
|
getProperty(id) {
|
|
return this.get('properties').filter(prop => prop.get('id') === id)[0] || null;
|
|
},
|
|
});
|
|
|