diff --git a/src/dom_components/model/Component.js b/src/dom_components/model/Component.js index 49c5f737b..573b560b3 100644 --- a/src/dom_components/model/Component.js +++ b/src/dom_components/model/Component.js @@ -585,22 +585,40 @@ const Component = Backbone.Model.extend(Styleable).extend( return isArray(this.get('__symbol')); }, - __getSymbToUp(opts = {}) { + __getSymbolOf() { + return this.get('__symbolOf'); + }, + + __getSymbToUp() { const symbol = this.get('__symbol'); - const isMain = Array.isArray(symbol); - return !isMain + return !this.__isSymbol() ? [] - : opts.all - ? symbol : symbol.filter(item => item.collection || item.prevColl); }, + __getSymbTop(opts) { + const isSymbol = this.__isSymbol(); + let result = this; + let parent = this.parent(opts); + + while ( + parent && + (isSymbol ? parent.__isSymbol() : parent.__getSymbolOf()) + ) { + result = parent; + parent = parent.parent(opts); + } + + return result; + }, + __upSymbProps() { const changed = this.changedAttributes(); const attrs = changed.attributes || {}; delete changed.status; delete changed.open; delete changed.__symbol; + delete changed.__symbolOf; delete changed.attributes; delete attrs.id; if (!isEmptyObj(attrs)) changed.attributes = attrs; @@ -627,16 +645,19 @@ const Component = Backbone.Model.extend(Styleable).extend( }); } else if (o.add) { // Add - const items = m.__getSymbToUp(); - console.log('Added', m.getId(), m.toHTML(), o, 'toUp', items); - this.__getSymbToUp().forEach(parent => { - const toAppend = - items.filter(item => { - const itemParent = item.parent({ prev: 1 }); - return parent === itemParent || parent.contains(itemParent); - })[0] || m.clone({ symbol: 1 }); - console.log('Added inner', toAppend.getId(), toAppend.toHTML()); - parent.append(toAppend, o); + const addedInstances = m.__getSymbToUp(); + console.log('Added', m.getId(), m.toHTML(), o, 'toUp', addedInstances); + this.__getSymbToUp().forEach(symbInst => { + const symbTop = symbInst.__getSymbTop(); + const inner = addedInstances.filter(addedInst => { + const addedTop = addedInst.__getSymbTop({ prev: 1 }); + return symbTop && addedTop && addedTop === symbTop; + })[0]; + const toAppend = inner || m.clone({ symbol: 1 }); + console.log('Added inner', toAppend.getId(), toAppend.toHTML(), { + inner + }); + symbInst.append(toAppend, o); }); } else { // Remove @@ -1001,13 +1022,15 @@ const Component = Backbone.Model.extend(Styleable).extend( // Symbols if (opt.symbol) { + // TODO Check if trying to clone a Symbol (check if parent is symbol) const symbols = this.get('__symbol') || []; symbols.push(cloned); this.set('__symbol', symbols); this.__initSymb(); - cloned.set('__symbol', this); + cloned.set('__symbolOf', this); } else { - cloned.set('__symbol', 0); + // If I clone an inner symbol, I have to reset it + cloned.unset('__symbol'); } return cloned; @@ -1138,18 +1161,19 @@ const Component = Backbone.Model.extend(Styleable).extend( * @return {Object} * @private */ - toJSON(...args) { - const obj = Backbone.Model.prototype.toJSON.apply(this, args); + toJSON(opts = {}) { + const obj = Backbone.Model.prototype.toJSON.call(this, opts); obj.attributes = this.getAttributes(); delete obj.attributes.class; delete obj.toolbar; delete obj.traits; - if (obj.__symbol) { - if (Array.isArray(obj.__symbol)) { + if (!opts.keepSymbols) { + if (obj.__symbol) { obj.__symbol = this.__getSymbToUp().map(i => i.getId()); - } else { - obj.__symbol = obj.__symbol.getId(); + } + if (obj.__symbolOf) { + obj.__symbolOf = obj.__symbolOf.getId(); } } diff --git a/src/dom_components/model/Components.js b/src/dom_components/model/Components.js index 247ef09bc..c7c014b3e 100644 --- a/src/dom_components/model/Components.js +++ b/src/dom_components/model/Components.js @@ -260,14 +260,20 @@ export default Backbone.Collection.extend({ const allComp = (domc && domc.allById()) || {}; const firstAdd = this.__firstAdd; const toCheck = isArray(firstAdd) ? firstAdd : [firstAdd]; + const silent = { silent: true }; const onAll = comps => { comps.forEach(comp => { const symbol = comp.get('__symbol'); - if (symbol && (isString(symbol) || isString(symbol[0]))) { - const result = isArray(symbol) - ? symbol.map(smb => allComp[smb]).filter(i => i) - : allComp[symbol]; - comp.set('__symbol', result, { silent: true }); + const symbolOf = comp.get('__symbolOf'); + if (symbol && isArray(symbol) && isString(symbol[0])) { + comp.set( + '__symbol', + symbol.map(smb => allComp[smb]).filter(i => i), + silent + ); + } + if (isString(symbolOf)) { + comp.set('__symbolOf', allComp[symbol], silent); } onAll(comp.components()); }); diff --git a/src/undo_manager/index.js b/src/undo_manager/index.js index 429fbdf52..24730d9b1 100644 --- a/src/undo_manager/index.js +++ b/src/undo_manager/index.js @@ -81,7 +81,7 @@ export default () => { const result = { object, before: beforeCache, - after: object.toJSON() + after: object.toJSON({ keepSymbols: 1 }) }; beforeCache = null; return result;