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.
198 lines
4.5 KiB
198 lines
4.5 KiB
import { result, forEach, keys } from 'underscore';
|
|
import { Model } from '../../common';
|
|
import EditorModel from '../../editor/model/Editor';
|
|
|
|
const TYPE_CLASS = 1;
|
|
const TYPE_ID = 2;
|
|
|
|
export interface SelectorProps {
|
|
name: string;
|
|
label?: string;
|
|
type?: number;
|
|
active?: boolean;
|
|
private?: boolean;
|
|
protected?: boolean;
|
|
}
|
|
|
|
/**
|
|
* @typedef Selector
|
|
* @property {String} name Selector name, eg. `my-class`
|
|
* @property {String} label Selector label, eg. `My Class`
|
|
* @property {Number} [type=1] Type of the selector. 1 (class) | 2 (id)
|
|
* @property {Boolean} [active=true] If not active, it's not selectable by the Style Manager.
|
|
* @property {Boolean} [private=false] If true, it can't be seen by the Style Manager, but it will be rendered in the canvas and in export code.
|
|
* @property {Boolean} [protected=false] If true, it can't be removed from the attached component.
|
|
*/
|
|
export default class Selector extends Model<SelectorProps & { [key: string]: unknown }> {
|
|
defaults() {
|
|
return {
|
|
name: '',
|
|
label: '',
|
|
type: TYPE_CLASS,
|
|
active: true,
|
|
private: false,
|
|
protected: false,
|
|
_undo: true,
|
|
};
|
|
}
|
|
|
|
// Type selectors: https://developer.mozilla.org/it/docs/Web/CSS/CSS_Selectors
|
|
static readonly TYPE_CLASS = TYPE_CLASS;
|
|
static readonly TYPE_ID = TYPE_ID;
|
|
|
|
em: EditorModel;
|
|
|
|
/**
|
|
* @hideconstructor
|
|
*/
|
|
constructor(props: any, opts: any = {}) {
|
|
super(props, opts);
|
|
const { config = {} } = opts;
|
|
const name = this.get('name');
|
|
const label = this.get('label');
|
|
|
|
if (!name) {
|
|
this.set('name', label);
|
|
} else if (!label) {
|
|
this.set('label', name);
|
|
}
|
|
|
|
const namePreEsc = this.get('name')!;
|
|
const { escapeName } = config;
|
|
const nameEsc = escapeName ? escapeName(namePreEsc) : Selector.escapeName(namePreEsc);
|
|
this.set('name', nameEsc);
|
|
this.em = opts.em;
|
|
}
|
|
|
|
isId() {
|
|
return this.get('type') === TYPE_ID;
|
|
}
|
|
|
|
isClass() {
|
|
return this.get('type') === TYPE_CLASS;
|
|
}
|
|
|
|
getFullName(opts: any = {}) {
|
|
const { escape } = opts;
|
|
const name = this.get('name');
|
|
let pfx = '';
|
|
|
|
switch (this.get('type')) {
|
|
case TYPE_CLASS:
|
|
pfx = '.';
|
|
break;
|
|
case TYPE_ID:
|
|
pfx = '#';
|
|
break;
|
|
}
|
|
|
|
return pfx + (escape ? escape(name) : name);
|
|
}
|
|
|
|
/**
|
|
* Get selector as a string.
|
|
* @returns {String}
|
|
* @example
|
|
* // Given such selector: { name: 'my-selector', type: 2 }
|
|
* console.log(selector.toString());
|
|
* // -> `#my-selector`
|
|
*/
|
|
toString() {
|
|
return this.getFullName();
|
|
}
|
|
|
|
/**
|
|
* Get selector name.
|
|
* @returns {String}
|
|
* @example
|
|
* // Given such selector: { name: 'my-selector', label: 'My selector' }
|
|
* console.log(selector.getLabel());
|
|
* // -> `my-selector`
|
|
*/
|
|
getName() {
|
|
return this.get('name') || '';
|
|
}
|
|
|
|
/**
|
|
* Get selector label.
|
|
* @returns {String}
|
|
* @example
|
|
* // Given such selector: { name: 'my-selector', label: 'My selector' }
|
|
* console.log(selector.getLabel());
|
|
* // -> `My selector`
|
|
*/
|
|
getLabel() {
|
|
return this.get('label') || '';
|
|
}
|
|
|
|
/**
|
|
* Update selector label.
|
|
* @param {String} label New label
|
|
* @example
|
|
* // Given such selector: { name: 'my-selector', label: 'My selector' }
|
|
* selector.setLabel('New Label')
|
|
* console.log(selector.getLabel());
|
|
* // -> `New Label`
|
|
*/
|
|
setLabel(label: string) {
|
|
return this.set('label', label);
|
|
}
|
|
|
|
/**
|
|
* Get selector active state.
|
|
* @returns {Boolean}
|
|
*/
|
|
getActive() {
|
|
return !!this.get('active');
|
|
}
|
|
|
|
/**
|
|
* Update selector active state.
|
|
* @param {Boolean} value New active state
|
|
*/
|
|
setActive(value: boolean) {
|
|
return this.set('active', value);
|
|
}
|
|
|
|
toJSON(opts = {}) {
|
|
const { em } = this;
|
|
let obj = Model.prototype.toJSON.call(this, [opts]);
|
|
const defaults = result(this, 'defaults');
|
|
|
|
if (em && em.getConfig().avoidDefaults) {
|
|
forEach(defaults, (value, key) => {
|
|
if (obj[key] === value) {
|
|
delete obj[key];
|
|
}
|
|
});
|
|
|
|
if (obj.label === obj.name) {
|
|
delete obj.label;
|
|
}
|
|
|
|
const objLen = keys(obj).length;
|
|
|
|
if (objLen === 1 && obj.name) {
|
|
obj = obj.name;
|
|
}
|
|
|
|
if (objLen === 2 && obj.name && obj.type) {
|
|
obj = this.getFullName();
|
|
}
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
/**
|
|
* Escape string
|
|
* @param {string} name
|
|
* @return {string}
|
|
* @private
|
|
*/
|
|
static escapeName(name: string) {
|
|
return `${name}`.trim().replace(/([^a-z0-9\w-\\:@\\/]+)/gi, '-');
|
|
}
|
|
}
|
|
|
|
Selector.prototype.idAttribute = 'name';
|
|
|