Browse Source

Refactor Component to class

pull/3692/head
Artur Arseniev 5 years ago
parent
commit
bbb85982d5
  1. 322
      src/dom_components/model/Component.js
  2. 1
      src/parser/model/ParserHtml.js

322
src/dom_components/model/Component.js

@ -13,7 +13,7 @@ import {
} from 'underscore'; } from 'underscore';
import { shallowDiff, capitalize, isEmptyObj, isObject } from 'utils/mixins'; import { shallowDiff, capitalize, isEmptyObj, isObject } from 'utils/mixins';
import Styleable from 'domain_abstract/model/Styleable'; import Styleable from 'domain_abstract/model/Styleable';
import Backbone from 'backbone'; import { Model } from 'backbone';
import Components from './Components'; import Components from './Components';
import Selector from 'selector_manager/model/Selector'; import Selector from 'selector_manager/model/Selector';
import Selectors from 'selector_manager/model/Selectors'; import Selectors from 'selector_manager/model/Selectors';
@ -87,53 +87,11 @@ export const keyUpdateInside = `${keyUpdate}-inside`;
* By default, when `toolbar` property is falsy the editor will add automatically commands like `move`, `delete`, etc. based on its properties. * By default, when `toolbar` property is falsy the editor will add automatically commands like `move`, `delete`, etc. based on its properties.
* @property {Collection<Component>} [components=null] Children components. Default: `null` * @property {Collection<Component>} [components=null] Children components. Default: `null`
*/ */
const Component = Backbone.Model.extend(Styleable).extend( export default class Component extends Model.extend(Styleable) {
{
defaults: {
tagName: 'div',
type: '',
name: '',
removable: true,
draggable: true,
droppable: true,
badgable: true,
stylable: true,
'stylable-require': '',
'style-signature': '',
unstylable: '',
highlightable: true,
copyable: true,
resizable: false,
editable: false,
layerable: true,
selectable: true,
hoverable: true,
void: false,
state: '', // Indicates if the component is in some CSS state like ':hover', ':active', etc.
status: '', // State, eg. 'selected'
content: '',
icon: '',
style: '', // Component related style
classes: '', // Array of classes
script: '',
'script-props': '',
'script-export': '',
attributes: '',
traits: ['id', 'title'],
propagate: '',
dmode: '',
toolbar: null,
[keySymbol]: 0,
[keySymbols]: 0,
[keySymbolOvrd]: 0,
_undo: true,
_undoexc: ['status', 'open']
},
/** /**
* Hook method, called once the model is created * Hook method, called once the model is created
*/ */
init() {}, init() {}
/** /**
* Hook method, called when the model has been updated (eg. updated some model's property) * Hook method, called when the model has been updated (eg. updated some model's property)
@ -141,12 +99,12 @@ const Component = Backbone.Model.extend(Styleable).extend(
* @param {*} value Property value, if triggered after some property update * @param {*} value Property value, if triggered after some property update
* @param {*} previous Property previous value, if triggered after some property update * @param {*} previous Property previous value, if triggered after some property update
*/ */
updated(property, value, previous) {}, updated(property, value, previous) {}
/** /**
* Hook method, called once the model has been removed * Hook method, called once the model has been removed
*/ */
removed() {}, removed() {}
initialize(props = {}, opt = {}) { initialize(props = {}, opt = {}) {
bindAll(this, '__upSymbProps', '__upSymbCls', '__upSymbComps'); bindAll(this, '__upSymbProps', '__upSymbCls', '__upSymbComps');
@ -217,7 +175,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
this.__isSymbolOrInst() && this.__initSymb(); this.__isSymbolOrInst() && this.__initSymb();
em && em.trigger('component:create', this); em && em.trigger('component:create', this);
} }
}, }
__postAdd(opts = {}) { __postAdd(opts = {}) {
const { em } = this; const { em } = this;
@ -228,7 +186,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
this.__hasUm = 1; this.__hasUm = 1;
} }
opts.recursive && comps.map(c => c.__postAdd(opts)); opts.recursive && comps.map(c => c.__postAdd(opts));
}, }
__postRemove() { __postRemove() {
const { em } = this; const { em } = this;
@ -237,7 +195,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
um.remove(this.components()); um.remove(this.components());
delete this.__hasUm; delete this.__hasUm;
} }
}, }
__onChange(m, opts) { __onChange(m, opts) {
const changed = this.changedAttributes(); const changed = this.changedAttributes();
@ -249,26 +207,26 @@ const Component = Backbone.Model.extend(Styleable).extend(
this.__changesUp(opts); this.__changesUp(opts);
this.__propSelfToParent({ component: this, changed, options: opts }); this.__propSelfToParent({ component: this, changed, options: opts });
} }
}, }
__changesUp(opts) { __changesUp(opts) {
const { em, frame } = this; const { em, frame } = this;
[frame, em].forEach(md => md && md.changesUp(opts)); [frame, em].forEach(md => md && md.changesUp(opts));
}, }
__propSelfToParent(props) { __propSelfToParent(props) {
this.trigger(keyUpdate, props); this.trigger(keyUpdate, props);
this.__propToParent(props); this.__propToParent(props);
}, }
__propToParent(props) { __propToParent(props) {
const parent = this.parent(); const parent = this.parent();
parent && parent.trigger(keyUpdateInside, props); parent && parent.trigger(keyUpdateInside, props);
}, }
__emitUpdateTlb() { __emitUpdateTlb() {
this.emitUpdate('toolbar'); this.emitUpdate('toolbar');
}, }
/** /**
* Check component's type * Check component's type
@ -280,7 +238,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
*/ */
is(type) { is(type) {
return !!(this.get('type') == type); return !!(this.get('type') == type);
}, }
/** /**
* Return all the propeties * Return all the propeties
@ -288,7 +246,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
*/ */
props() { props() {
return this.attributes; return this.attributes;
}, }
/** /**
* Get the index of the component in the parent collection. * Get the index of the component in the parent collection.
@ -297,7 +255,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
index() { index() {
const { collection } = this; const { collection } = this;
return collection && collection.indexOf(this); return collection && collection.indexOf(this);
}, }
/** /**
* Change the drag mode of the component. * Change the drag mode of the component.
@ -307,7 +265,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
*/ */
setDragMode(value) { setDragMode(value) {
return this.set('dmode', value); return this.set('dmode', value);
}, }
/** /**
* Find inner components by query string. * Find inner components by query string.
@ -328,7 +286,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
}); });
return result; return result;
}, }
/** /**
* Find all inner components by component type. * Find all inner components by component type.
@ -349,7 +307,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
}); });
find(this.components()); find(this.components());
return result; return result;
}, }
/** /**
* Find the closest parent component by query string. * Find the closest parent component by query string.
@ -363,7 +321,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
closest(query) { closest(query) {
const result = this.view.$el.closest(query); const result = this.view.$el.closest(query);
return result.length && result.data('model'); return result.length && result.data('model');
}, }
/** /**
* Find the closest parent component by its type. * Find the closest parent component by its type.
@ -383,7 +341,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
} }
return parent; return parent;
}, }
/** /**
* The method returns a Boolean value indicating whether the passed * The method returns a Boolean value indicating whether the passed
@ -403,7 +361,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
}; };
contains(this.components()); contains(this.components());
return result; return result;
}, }
/** /**
* Once the tag is updated I have to rerender the element * Once the tag is updated I have to rerender the element
@ -411,7 +369,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
*/ */
tagUpdated() { tagUpdated() {
this.trigger('rerender'); this.trigger('rerender');
}, }
/** /**
* Replace a component with another one * Replace a component with another one
@ -426,7 +384,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
const at = coll.indexOf(this); const at = coll.indexOf(this);
coll.remove(this); coll.remove(this);
return coll.add(el, { at }); return coll.add(el, { at });
}, }
/** /**
* Emit changes for each updated attribute * Emit changes for each updated attribute
@ -449,7 +407,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
keys(diff).forEach(pr => keys(diff).forEach(pr =>
this.trigger(`change:attributes:${pr}`, this, diff[pr], opts) this.trigger(`change:attributes:${pr}`, this, diff[pr], opts)
); );
}, }
/** /**
* Update attributes of the component * Update attributes of the component
@ -462,7 +420,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
setAttributes(attrs, opts = {}) { setAttributes(attrs, opts = {}) {
this.set('attributes', { ...attrs }, opts); this.set('attributes', { ...attrs }, opts);
return this; return this;
}, }
/** /**
* Add attributes to the component * Add attributes to the component
@ -480,7 +438,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
}, },
opts opts
); );
}, }
/** /**
* Remove attributes from the component * Remove attributes from the component
@ -496,7 +454,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
const compAttr = this.getAttributes(); const compAttr = this.getAttributes();
attrArr.map(i => delete compAttr[i]); attrArr.map(i => delete compAttr[i]);
return this.setAttributes(compAttr, opts); return this.setAttributes(compAttr, opts);
}, }
/** /**
* Get the style of the component * Get the style of the component
@ -517,7 +475,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
} }
return Styleable.getStyle.call(this); return Styleable.getStyle.call(this);
}, }
/** /**
* Set the style on the component * Set the style on the component
@ -551,7 +509,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
} }
return prop; return prop;
}, }
/** /**
* Return all component's attributes * Return all component's attributes
@ -603,7 +561,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
} }
return attributes; return attributes;
}, }
/** /**
* Add classes * Add classes
@ -618,7 +576,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
addClass(classes) { addClass(classes) {
const added = this.em.get('SelectorManager').addClass(classes); const added = this.em.get('SelectorManager').addClass(classes);
return this.get('classes').add(added); return this.get('classes').add(added);
}, }
/** /**
* Set classes (resets current collection) * Set classes (resets current collection)
@ -633,7 +591,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
setClass(classes) { setClass(classes) {
this.get('classes').reset(); this.get('classes').reset();
return this.addClass(classes); return this.addClass(classes);
}, }
/** /**
* Remove classes * Remove classes
@ -660,7 +618,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
}); });
return removed; return removed;
}, }
/** /**
* Returns component's classes as an array of strings * Returns component's classes as an array of strings
@ -670,28 +628,28 @@ const Component = Backbone.Model.extend(Styleable).extend(
const attr = this.getAttributes(); const attr = this.getAttributes();
const classStr = attr.class; const classStr = attr.class;
return classStr ? classStr.split(' ') : []; return classStr ? classStr.split(' ') : [];
}, }
__logSymbol(type, toUp, opts = {}) { __logSymbol(type, toUp, opts = {}) {
const symbol = this.__getSymbol(); const symbol = this.__getSymbol();
const symbols = this.__getSymbols(); const symbols = this.__getSymbols();
if (!symbol && !symbols) return; if (!symbol && !symbols) return;
this.em.log(type, { model: this, toUp, context: 'symbols', opts }); this.em.log(type, { model: this, toUp, context: 'symbols', opts });
}, }
__initSymb() { __initSymb() {
if (this.__symbReady) return; if (this.__symbReady) return;
this.on('change', this.__upSymbProps); this.on('change', this.__upSymbProps);
this.__symbReady = 1; this.__symbReady = 1;
}, }
__isSymbol() { __isSymbol() {
return isArray(this.get(keySymbols)); return isArray(this.get(keySymbols));
}, }
__isSymbolOrInst() { __isSymbolOrInst() {
return !!(this.__isSymbol() || this.get(keySymbol)); return !!(this.__isSymbol() || this.get(keySymbol));
}, }
__isSymbolTop() { __isSymbolTop() {
const parent = this.parent(); const parent = this.parent();
@ -700,7 +658,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
symb && symb &&
(!parent || (parent && !parent.__isSymbol() && !parent.__getSymbol())) (!parent || (parent && !parent.__isSymbol() && !parent.__getSymbol()))
); );
}, }
__isSymbolNested() { __isSymbolNested() {
if (!this.__isSymbolOrInst() || this.__isSymbolTop()) return false; if (!this.__isSymbolOrInst() || this.__isSymbolTop()) return false;
@ -709,16 +667,14 @@ const Component = Backbone.Model.extend(Styleable).extend(
: this.__getSymbol() : this.__getSymbol()
).__getSymbTop(); ).__getSymbTop();
const symbTop = this.__getSymbTop(); const symbTop = this.__getSymbTop();
const symbTopMain = symbTop.__isSymbol() const symbTopMain = symbTop.__isSymbol() ? symbTop : symbTop.__getSymbol();
? symbTop
: symbTop.__getSymbol();
return symbTopMain !== symbTopSelf; return symbTopMain !== symbTopSelf;
}, }
__getAllById() { __getAllById() {
const { em } = this; const { em } = this;
return em ? em.get('DomComponents').allById() : {}; return em ? em.get('DomComponents').allById() : {};
}, }
__getSymbol() { __getSymbol() {
let symb = this.get(keySymbol); let symb = this.get(keySymbol);
@ -732,7 +688,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
} }
} }
return symb; return symb;
}, }
__getSymbols() { __getSymbols() {
let symbs = this.get(keySymbols); let symbs = this.get(keySymbols);
@ -745,17 +701,16 @@ const Component = Backbone.Model.extend(Styleable).extend(
symbs = symbs.filter(symb => symb && !isString(symb)); symbs = symbs.filter(symb => symb && !isString(symb));
} }
return symbs; return symbs;
}, }
__isSymbOvrd(prop = '') { __isSymbOvrd(prop = '') {
const ovrd = this.get(keySymbolOvrd); const ovrd = this.get(keySymbolOvrd);
const [prp] = prop.split(':'); const [prp] = prop.split(':');
const props = prop !== prp ? [prop, prp] : [prop]; const props = prop !== prp ? [prop, prp] : [prop];
return ( return (
ovrd === true || ovrd === true || (isArray(ovrd) && props.some(p => ovrd.indexOf(p) >= 0))
(isArray(ovrd) && props.some(p => ovrd.indexOf(p) >= 0))
); );
}, }
__getSymbToUp(opts = {}) { __getSymbToUp(opts = {}) {
let result = []; let result = [];
@ -783,7 +738,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
.filter(s => !(changed && s.__isSymbOvrd(changed))); .filter(s => !(changed && s.__isSymbOvrd(changed)));
return result; return result;
}, }
__getSymbTop(opts) { __getSymbTop(opts) {
let result = this; let result = this;
@ -795,7 +750,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
} }
return result; return result;
}, }
__upSymbProps(m, opts = {}) { __upSymbProps(m, opts = {}) {
const changed = this.changedAttributes(); const changed = this.changedAttributes();
@ -825,7 +780,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
child.set(propsChanged, { fromInstance: this, ...opts }); child.set(propsChanged, { fromInstance: this, ...opts });
}); });
} }
}, }
__upSymbCls(m, c, opts = {}) { __upSymbCls(m, c, opts = {}) {
const toUp = this.__getSymbToUp(opts); const toUp = this.__getSymbToUp(opts);
@ -835,7 +790,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
child.set('classes', this.get('classes'), { fromInstance: this }); child.set('classes', this.get('classes'), { fromInstance: this });
}); });
this.__changesUp(opts); this.__changesUp(opts);
}, }
__upSymbComps(m, c, o) { __upSymbComps(m, c, o) {
const optUp = o || c || {}; const optUp = o || c || {};
@ -933,7 +888,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
} }
this.__changesUp(optUp); this.__changesUp(optUp);
}, }
initClasses(m, c, opts = {}) { initClasses(m, c, opts = {}) {
const event = 'change:classes'; const event = 'change:classes';
@ -949,7 +904,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
selectors.on('add remove reset', this.__upSymbCls); selectors.on('add remove reset', this.__upSymbCls);
this.listenTo(...toListen); this.listenTo(...toListen);
return this; return this;
}, }
initComponents() { initComponents() {
const event = 'change:components'; const event = 'change:components';
@ -971,7 +926,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
comps.on('add remove reset', this.__upSymbComps); comps.on('add remove reset', this.__upSymbComps);
this.listenTo(...toListen); this.listenTo(...toListen);
return this; return this;
}, }
initTraits(changed) { initTraits(changed) {
const { em } = this; const { em } = this;
@ -992,7 +947,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
this.listenTo(...toListen); this.listenTo(...toListen);
changed && em && em.trigger('component:toggled'); changed && em && em.trigger('component:toggled');
return this; return this;
}, }
initScriptProps() { initScriptProps() {
if (this.opt.temporary) return; if (this.opt.temporary) return;
@ -1006,12 +961,12 @@ const Component = Backbone.Model.extend(Styleable).extend(
prevPropsEv && this.off(prevPropsEv, this.__scriptPropsChange); prevPropsEv && this.off(prevPropsEv, this.__scriptPropsChange);
newPropsEv && this.on(newPropsEv, this.__scriptPropsChange); newPropsEv && this.on(newPropsEv, this.__scriptPropsChange);
this.on(...toListen); this.on(...toListen);
}, }
__scriptPropsChange(m, v, opts = {}) { __scriptPropsChange(m, v, opts = {}) {
if (opts.avoidStore) return; if (opts.avoidStore) return;
this.trigger('rerender'); this.trigger('rerender');
}, }
/** /**
* Add new component children * Add new component children
@ -1042,7 +997,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
}); });
const result = this.components().add(toAppend, opts); const result = this.components().add(toAppend, opts);
return isArray(result) ? result : [result]; return isArray(result) ? result : [result];
}, }
/** /**
* Set new collection if `components` are provided, otherwise the * Set new collection if `components` are provided, otherwise the
@ -1067,7 +1022,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
coll.reset(null, opts); coll.reset(null, opts);
return components && this.append(components, opts); return components && this.append(components, opts);
} }
}, }
/** /**
* Remove all inner components * Remove all inner components
@ -1076,7 +1031,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
empty(opts = {}) { empty(opts = {}) {
this.components().reset(null, opts); this.components().reset(null, opts);
return this; return this;
}, }
/** /**
* Get the parent component, if exists * Get the parent component, if exists
@ -1088,7 +1043,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
parent(opts = {}) { parent(opts = {}) {
const coll = this.collection || (opts.prev && this.prevColl); const coll = this.collection || (opts.prev && this.prevColl);
return coll && coll.parent; return coll && coll.parent;
}, }
/** /**
* Script updated * Script updated
@ -1096,7 +1051,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
*/ */
scriptUpdated() { scriptUpdated() {
this.set('scriptUpdated', 1); this.set('scriptUpdated', 1);
}, }
/** /**
* Init toolbar * Init toolbar
@ -1139,7 +1094,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
} }
model.set('toolbar', tb); model.set('toolbar', tb);
} }
}, }
/** /**
* Load traits * Load traits
@ -1163,7 +1118,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
} }
return this; return this;
}, }
/** /**
* Get the trait by id/name * Get the trait by id/name
@ -1177,7 +1132,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
return this.get('traits').filter(trait => { return this.get('traits').filter(trait => {
return trait.get('id') === id || trait.get('name') === id; return trait.get('id') === id || trait.get('name') === id;
})[0]; })[0];
}, }
/** /**
* Update a trait * Update a trait
@ -1196,7 +1151,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
trait && trait.set(props); trait && trait.set(props);
em && em.trigger('component:toggled'); em && em.trigger('component:toggled');
return this; return this;
}, }
/** /**
* Get the trait position index by id/name. Useful in case you want to * Get the trait position index by id/name. Useful in case you want to
@ -1210,7 +1165,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
getTraitIndex(id) { getTraitIndex(id) {
const trait = this.getTrait(id); const trait = this.getTrait(id);
return trait ? this.get('traits').indexOf(trait) : -1; return trait ? this.get('traits').indexOf(trait) : -1;
}, }
/** /**
* Remove trait/s by id/s. * Remove trait/s by id/s.
@ -1227,7 +1182,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
const removed = this.get('traits').remove(toRemove); const removed = this.get('traits').remove(toRemove);
em && em.trigger('component:toggled'); em && em.trigger('component:toggled');
return removed; return removed;
}, }
/** /**
* Add trait/s by id/s. * Add trait/s by id/s.
@ -1247,7 +1202,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
const added = this.get('traits').add(trait, opts); const added = this.get('traits').add(trait, opts);
em && em.trigger('component:toggled'); em && em.trigger('component:toggled');
return added; return added;
}, }
/** /**
* Normalize input classes from array to array of objects * Normalize input classes from array to array of objects
@ -1263,7 +1218,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
if (arr.models) return [...arr.models]; if (arr.models) return [...arr.models];
arr.forEach(val => res.push(clm.add(val))); arr.forEach(val => res.push(clm.add(val)));
return res; return res;
}, }
/** /**
* Override original clone method * Override original clone method
@ -1347,7 +1302,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
this.trigger(event, cloned); this.trigger(event, cloned);
return cloned; return cloned;
}, }
/** /**
* Get the name of the component * Get the name of the component
@ -1375,7 +1330,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
i18nDefName || i18nDefName ||
capitalize(defName) // Use the default name capitalize(defName) // Use the default name
); );
}, }
/** /**
* Get the icon string * Get the icon string
@ -1384,7 +1339,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
getIcon() { getIcon() {
let icon = this.get('icon'); let icon = this.get('icon');
return icon ? icon + ' ' : ''; return icon ? icon + ' ' : '';
}, }
/** /**
* Return HTML string of the component * Return HTML string of the component
@ -1455,7 +1410,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
!sTag && (code += `</${tag}>`); !sTag && (code += `</${tag}>`);
return code; return code;
}, }
/** /**
* Returns object of attributes for HTML * Returns object of attributes for HTML
@ -1466,7 +1421,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
var attr = this.getAttributes(); var attr = this.getAttributes();
delete attr.style; delete attr.style;
return attr; return attr;
}, }
/** /**
* Return a shallow copy of the model's attributes for JSON * Return a shallow copy of the model's attributes for JSON
@ -1475,7 +1430,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
* @private * @private
*/ */
toJSON(opts = {}) { toJSON(opts = {}) {
const obj = Backbone.Model.prototype.toJSON.call(this, opts); const obj = Model.prototype.toJSON.call(this, opts);
obj.attributes = this.getAttributes(); obj.attributes = this.getAttributes();
delete obj.attributes.class; delete obj.attributes.class;
delete obj.toolbar; delete obj.toolbar;
@ -1501,13 +1456,13 @@ const Component = Backbone.Model.extend(Styleable).extend(
} }
return obj; return obj;
}, }
/** /**
* Return an object containing only changed props * Return an object containing only changed props
*/ */
getChangedProps(res) { getChangedProps(res) {
const obj = res || Backbone.Model.prototype.toJSON.apply(this); const obj = res || Model.prototype.toJSON.apply(this);
const defaults = result(this, 'defaults'); const defaults = result(this, 'defaults');
forEach(defaults, (value, key) => { forEach(defaults, (value, key) => {
@ -1533,7 +1488,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
}); });
return obj; return obj;
}, }
/** /**
* Return the component id * Return the component id
@ -1542,7 +1497,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
getId() { getId() {
let attrs = this.get('attributes') || {}; let attrs = this.get('attributes') || {};
return attrs.id || this.ccid || this.cid; return attrs.id || this.ccid || this.cid;
}, }
/** /**
* Set new id on the component * Set new id on the component
@ -1554,7 +1509,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
attrs.id = id; attrs.id = id;
this.set('attributes', attrs, opts); this.set('attributes', attrs, opts);
return this; return this;
}, }
/** /**
* Get the DOM element of the component. * Get the DOM element of the component.
@ -1565,7 +1520,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
getEl(frame) { getEl(frame) {
const view = this.getView(frame); const view = this.getView(frame);
return view && view.el; return view && view.el;
}, }
/** /**
* Get the View of the component. * Get the View of the component.
@ -1581,12 +1536,12 @@ const Component = Backbone.Model.extend(Styleable).extend(
} }
return view; return view;
}, }
getCurrentView() { getCurrentView() {
const frame = (this.em.get('currentFrame') || {}).model; const frame = (this.em.get('currentFrame') || {}).model;
return this.getView(frame); return this.getView(frame);
}, }
__getScriptProps() { __getScriptProps() {
const modelProps = this.props(); const modelProps = this.props();
@ -1595,7 +1550,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
acc[prop] = modelProps[prop]; acc[prop] = modelProps[prop];
return acc; return acc;
}, {}); }, {});
}, }
/** /**
* Return script in string format, cleans 'function() {..' from scripts * Return script in string format, cleans 'function() {..' from scripts
@ -1639,7 +1594,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
}); });
} }
return scr; return scr;
}, }
emitUpdate(property, ...args) { emitUpdate(property, ...args) {
const { em } = this; const { em } = this;
@ -1660,7 +1615,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
changed: { [property]: item }, changed: { [property]: item },
options: args[2] || args[1] || {} options: args[2] || args[1] || {}
}); });
}, }
/** /**
* Execute callback function on itself and all inner components * Execute callback function on itself and all inner components
@ -1677,7 +1632,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
this.components().forEach(model => model.onAll(clb)); this.components().forEach(model => model.onAll(clb));
} }
return this; return this;
}, }
/** /**
* Remove the component * Remove the component
@ -1696,7 +1651,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
); );
!rmOpts.abort && remove(); !rmOpts.abort && remove();
return this; return this;
}, }
/** /**
* Move the component to another destination component * Move the component to another destination component
@ -1712,7 +1667,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
this.remove({ temporary: 1 }); this.remove({ temporary: 1 });
component && component.append(this, opts); component && component.append(this, opts);
return this; return this;
}, }
/** /**
* Reset id of the component and any of its style rule * Reset id of the component and any of its style rule
@ -1730,18 +1685,18 @@ const Component = Backbone.Model.extend(Styleable).extend(
const selector = rule && rule.get('selectors').at(0); const selector = rule && rule.get('selectors').at(0);
selector && selector.set('name', newId); selector && selector.set('name', newId);
return this; return this;
}, }
_getStyleRule({ id } = {}) { _getStyleRule({ id } = {}) {
const { em } = this; const { em } = this;
const idS = id || this.getId(); const idS = id || this.getId();
return em && em.get('CssComposer').getIdRule(idS); return em && em.get('CssComposer').getIdRule(idS);
}, }
_getStyleSelector(opts) { _getStyleSelector(opts) {
const rule = this._getStyleRule(opts); const rule = this._getStyleRule(opts);
return rule && rule.get('selectors').at(0); return rule && rule.get('selectors').at(0);
}, }
_idUpdated(m, v, opts = {}) { _idUpdated(m, v, opts = {}) {
if (opts.idUpdate) return; if (opts.idUpdate) return;
@ -1765,21 +1720,8 @@ const Component = Backbone.Model.extend(Styleable).extend(
const selector = this._getStyleSelector({ id: idPrev }); const selector = this._getStyleSelector({ id: idPrev });
selector && selector.set({ name: id, label: id }); selector && selector.set({ name: id, label: id });
} }
},
{
/**
* Detect if the passed element is a valid component.
* In case the element is valid an object abstracted
* from the element will be returned
* @param {HTMLElement}
* @return {Object}
* @private
*/
isComponent(el) {
return { tagName: el.tagName ? el.tagName.toLowerCase() : '' };
},
ensureInList(model) { static ensureInList(model) {
const list = Component.getList(model); const list = Component.getList(model);
const id = model.getId(); const id = model.getId();
const current = list[id]; const current = list[id];
@ -1795,7 +1737,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
} }
model.components().forEach(i => Component.ensureInList(i)); model.components().forEach(i => Component.ensureInList(i));
}, }
/** /**
* Relying simply on the number of components becomes a problem when you * Relying simply on the number of components becomes a problem when you
@ -1804,7 +1746,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
* @return {string} * @return {string}
* @private * @private
*/ */
createId(model, opts = {}) { static createId(model, opts = {}) {
const list = Component.getList(model); const list = Component.getList(model);
const { idMap = {} } = opts; const { idMap = {} } = opts;
let { id } = model.get('attributes'); let { id } = model.get('attributes');
@ -1820,9 +1762,9 @@ const Component = Backbone.Model.extend(Styleable).extend(
list[nextId] = model; list[nextId] = model;
return nextId; return nextId;
}, }
getNewId(list) { static getNewId(list) {
const count = Object.keys(list).length; const count = Object.keys(list).length;
// Testing 1000000 components with `+ 2` returns 0 collisions // Testing 1000000 components with `+ 2` returns 0 collisions
const ilen = count.toString().length + 2; const ilen = count.toString().length + 2;
@ -1834,9 +1776,9 @@ const Component = Backbone.Model.extend(Styleable).extend(
} }
return newId; return newId;
}, }
getIncrementId(id, list, opts = {}) { static getIncrementId(id, list, opts = {}) {
const { keepIds = [] } = opts; const { keepIds = [] } = opts;
let counter = 1; let counter = 1;
let newId = id; let newId = id;
@ -1849,26 +1791,26 @@ const Component = Backbone.Model.extend(Styleable).extend(
} }
return newId; return newId;
}, }
/** /**
* The list of components is taken from the Components module. * The list of components is taken from the Components module.
* Initially, the list, was set statically on the Component object but it was * Initially, the list, was set statically on the Component object but it was
* not ok, as it was shared between multiple editor instances * not ok, as it was shared between multiple editor instances
*/ */
getList(model) { static getList(model) {
const { opt = {} } = model; const { opt = {} } = model;
const { domc, em } = opt; const { domc, em } = opt;
const dm = domc || (em && em.get('DomComponents')); const dm = domc || (em && em.get('DomComponents'));
return dm ? dm.componentsById : {}; return dm ? dm.componentsById : {};
}, }
/** /**
* This method checks, for each parsed component and style object * This method checks, for each parsed component and style object
* (are not Components/CSSRules yet), for duplicated id and fixes them * (are not Components/CSSRules yet), for duplicated id and fixes them
* This method is used in Components.js just after the parsing * This method is used in Components.js just after the parsing
*/ */
checkId(components, styles = [], list = {}, opts = {}) { static checkId(components, styles = [], list = {}, opts = {}) {
const comps = isArray(components) ? components : [components]; const comps = isArray(components) ? components : [components];
const { keepIds = [] } = opts; const { keepIds = [] } = opts;
comps.forEach(comp => { comps.forEach(comp => {
@ -1892,7 +1834,57 @@ const Component = Backbone.Model.extend(Styleable).extend(
components && Component.checkId(components, styles, list, opts); components && Component.checkId(components, styles, list, opts);
}); });
} }
} }
);
export default Component; /**
* Detect if the passed element is a valid component.
* In case the element is valid an object abstracted
* from the element will be returned
* @param {HTMLElement}
* @return {Object}
* @private
*/
Component.isComponent = el => {
return { tagName: el.tagName ? el.tagName.toLowerCase() : '' };
};
Component.prototype.defaults = {
tagName: 'div',
type: '',
name: '',
removable: true,
draggable: true,
droppable: true,
badgable: true,
stylable: true,
'stylable-require': '',
'style-signature': '',
unstylable: '',
highlightable: true,
copyable: true,
resizable: false,
editable: false,
layerable: true,
selectable: true,
hoverable: true,
void: false,
state: '', // Indicates if the component is in some CSS state like ':hover', ':active', etc.
status: '', // State, eg. 'selected'
content: '',
icon: '',
style: '', // Component related style
classes: '', // Array of classes
script: '',
'script-props': '',
'script-export': '',
attributes: '',
traits: ['id', 'title'],
propagate: '',
dmode: '',
toolbar: null,
[keySymbol]: 0,
[keySymbols]: 0,
[keySymbolOvrd]: 0,
_undo: true,
_undoexc: ['status', 'open']
};

1
src/parser/model/ParserHtml.js

@ -128,6 +128,7 @@ export default config => {
// the first with a valid result will be that component // the first with a valid result will be that component
for (let it = 0; it < ct.length; it++) { for (let it = 0; it < ct.length; it++) {
const compType = ct[it]; const compType = ct[it];
console.log({ compType, model: compType.model });
obj = compType.model.isComponent(node); obj = compType.model.isComponent(node);
if (obj) { if (obj) {

Loading…
Cancel
Save