diff --git a/package-lock.json b/package-lock.json index 6b78dddb0..ab23a8701 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9935,8 +9935,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -9957,14 +9956,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -9979,20 +9976,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -10109,8 +10103,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -10122,7 +10115,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -10137,7 +10129,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -10145,14 +10136,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -10171,7 +10160,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -10252,8 +10240,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -10265,7 +10252,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -10351,8 +10337,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -10388,7 +10373,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -10408,7 +10392,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -10452,14 +10435,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, diff --git a/src/commands/view/OpenStyleManager.js b/src/commands/view/OpenStyleManager.js index 895a1206f..d79327860 100644 --- a/src/commands/view/OpenStyleManager.js +++ b/src/commands/view/OpenStyleManager.js @@ -1,6 +1,4 @@ import Backbone from 'backbone'; -import StyleManager from 'style_manager'; - const $ = Backbone.$; export default { @@ -27,7 +25,6 @@ export default { // Class Manager container var clm = em.SelectorManager; if (clm) this.$cn2.append(clm.render([])); - this.$cn2.append(em.StyleManager.render()); var smConfig = em.StyleManager.getConfig(); const pfx = smConfig.stylePrefix; diff --git a/src/commands/view/SelectComponent.js b/src/commands/view/SelectComponent.js index 5c592e37a..a977c9663 100644 --- a/src/commands/view/SelectComponent.js +++ b/src/commands/view/SelectComponent.js @@ -780,5 +780,6 @@ export default { this.onOut(); this.toggleToolsEl(); editor && editor.stopCommand('resize'); + this.editor = 0; } }; diff --git a/src/css_composer/model/CssRules.js b/src/css_composer/model/CssRules.js index 873a37ade..f4fe209b9 100644 --- a/src/css_composer/model/CssRules.js +++ b/src/css_composer/model/CssRules.js @@ -2,23 +2,20 @@ import Backbone from 'backbone'; import CssRule from './CssRule'; export default Backbone.Collection.extend({ + model: CssRule, + initialize(models, opt) { // Inject editor if (opt && opt.em) this.editor = opt.em; - // Not used - this.model = (attrs, options) => { - var model; - - if (!options.em && opt && opt.em) options.em = opt.em; - - switch (1) { - default: - model = new CssRule(attrs, options); - } + // This will put the listener post CssComposer.postLoad + setTimeout(() => this.on('remove', this.onRemove)); + }, - return model; - }; + onRemove(removed) { + const em = this.editor; + em.stopListening(removed); + em.get('UndoManager').remove(removed); }, add(models, opt = {}) { diff --git a/src/dom_components/model/Components.js b/src/dom_components/model/Components.js index f491d0941..d7ddcac31 100644 --- a/src/dom_components/model/Components.js +++ b/src/dom_components/model/Components.js @@ -9,37 +9,38 @@ export default Backbone.Collection.extend({ this.listenTo(this, 'add', this.onAdd); this.config = opt.config; this.em = opt.em; - const { em } = this; + }, - this.model = (attrs, options) => { - var model; - const df = opt.em.get('DomComponents').componentTypes; - options.em = opt.em; - options.config = opt.config; - options.componentTypes = df; - options.domc = opt.domc; - - for (var it = 0; it < df.length; it++) { - var dfId = df[it].id; - if (dfId == attrs.type) { - model = df[it].model; - break; - } + model(attrs, options) { + const { opt } = options.collection; + const { em } = opt; + let model; + const df = em.get('DomComponents').componentTypes; + options.em = em; + options.config = opt.config; + options.componentTypes = df; + options.domc = opt.domc; + + for (let it = 0; it < df.length; it++) { + const dfId = df[it].id; + if (dfId == attrs.type) { + model = df[it].model; + break; } + } - if (!model) { - // get the last one - model = df[df.length - 1].model; - em && - attrs.type && - em.logWarning(`Component type '${attrs.type}' not found`, { - attrs, - options - }); - } + // If no model found, get the default one + if (!model) { + model = df[df.length - 1].model; + em && + attrs.type && + em.logWarning(`Component type '${attrs.type}' not found`, { + attrs, + options + }); + } - return new model(attrs, options); - }; + return new model(attrs, options); }, parseString(value, opt = {}) { diff --git a/src/dom_components/view/ComponentView.js b/src/dom_components/view/ComponentView.js index 620c4842d..fc626fde5 100644 --- a/src/dom_components/view/ComponentView.js +++ b/src/dom_components/view/ComponentView.js @@ -87,18 +87,27 @@ export default Backbone.View.extend({ onDisable() {}, remove() { - Backbone.View.prototype.remove.apply(this, arguments); - const { model } = this; - const frame = this._getFrame() || {}; + const view = this; + Backbone.View.prototype.remove.apply(view, arguments); + const { model } = view; + const frame = view._getFrame() || {}; const frameM = frame.model; model.components().forEach(comp => { const view = comp.getView(frameM); view && view.remove(); }); const { views } = model; - views.splice(views.indexOf(this), 1); - this.removed(this._clbObj()); - return this; + views.splice(views.indexOf(view), 1); + view.removed(view._clbObj()); + view.$el.data({ model: '', collection: '', view: '' }); + delete view.model; + delete view.$el; + delete view.el.__gjsv; + delete view.childrenView; + delete view.scriptContainer; + delete view.opts; + // delete view.el; + return view; }, handleDragStart(event) { @@ -474,11 +483,13 @@ export default Backbone.View.extend({ renderChildren() { this.updateContent(); const container = this.getChildrenContainer(); - const view = new ComponentsView({ - collection: this.model.get('components'), - config: this.config, - componentTypes: this.opts.componentTypes - }); + const view = + this.childrenView || + new ComponentsView({ + collection: this.model.get('components'), + config: this.config, + componentTypes: this.opts.componentTypes + }); view.render(container); this.childrenView = view; diff --git a/src/dom_components/view/ComponentsView.js b/src/dom_components/view/ComponentsView.js index 5f22a1ba5..078fbea35 100644 --- a/src/dom_components/view/ComponentsView.js +++ b/src/dom_components/view/ComponentsView.js @@ -18,28 +18,31 @@ export default Backbone.View.extend({ removed.views.forEach(view => { if (!view) return; - view.remove.apply(view); const { childrenView, scriptContainer } = view; childrenView && childrenView.stopListening(); scriptContainer && scriptContainer.remove(); + view.remove.apply(view); }); - removed.components().forEach(it => this.removeChildren(it, coll, opts)); + const inner = removed.components(); + inner.forEach(it => this.removeChildren(it, coll, opts)); if (em && !tempRemove) { // Remove the component from the global list const id = removed.getId(); const domc = em.get('DomComponents'); + const sels = em.get('SelectorManager').getAll(); delete domc.componentsById[id]; // Remove all related CSS rules // TODO: remove from the frame container const allRules = em.get('CssComposer').getAll(); - allRules.remove( + const rulesRemoved = allRules.remove( allRules.filter( rule => rule.getSelectors().getFullString() === `#${id}` ) ); + sels.remove(rulesRemoved.map(rule => rule.getSelectors().at(0))); if (!removed.opt.temporary) { const cm = em.get('Commands'); @@ -50,6 +53,14 @@ export default Backbone.View.extend({ em.trigger('component:remove', removed); } } + + // Remove stuff registered in DomComponents.handleChanges + em.stopListening(inner); + em.stopListening(removed); + em.stopListening(removed.get('classes')); + const um = em.get('UndoManager'); + um.remove(removed); + um.remove(inner); }, /** @@ -86,6 +97,8 @@ export default Backbone.View.extend({ if (!this.compView) this.compView = require('./ComponentView').default; const { config, opts, em } = this; const fragment = fragmentEl || null; + const { frameView = {} } = config; + const sameFrameView = frameView.model && model.getView(frameView.model); const dt = opts.componentTypes || (em && em.get('DomComponents').getTypes()); const type = model.get('type'); @@ -97,12 +110,13 @@ export default Backbone.View.extend({ break; } } - - const view = new viewObject({ - model, - config, - componentTypes: dt - }); + const view = + sameFrameView || + new viewObject({ + model, + config, + componentTypes: dt + }); let rendered = view.render().el; if (fragment) { @@ -134,9 +148,10 @@ export default Backbone.View.extend({ return rendered; }, - resetChildren() { + resetChildren(models, { previousModels = [] } = {}) { this.parentEl.innerHTML = ''; - this.collection.each(model => this.addToCollection(model)); + previousModels.forEach(md => this.removeChildren(md, this.collection)); + models.each(model => this.addToCollection(model)); }, render(parent) { diff --git a/src/editor/model/Editor.js b/src/editor/model/Editor.js index bbeec265e..ccb5a22fe 100644 --- a/src/editor/model/Editor.js +++ b/src/editor/model/Editor.js @@ -688,6 +688,8 @@ export default Backbone.Model.extend({ * Destroy editor */ destroyAll() { + const editor = this.getEditor(); + const { editors } = this.config.grapesjs; const { DomComponents, CssComposer, @@ -697,6 +699,7 @@ export default Backbone.Model.extend({ Keymaps, RichTextEditor } = this.attributes; + this.stopDefault(); DomComponents.clear(); CssComposer.clear(); UndoManager.clear().removeAll(); @@ -706,6 +709,10 @@ export default Backbone.Model.extend({ RichTextEditor.destroy(); this.view.remove(); this.stopListening(); + this.clear({ silent: true }); + this._previousAttributes = {}; + this.attributes = {}; + editors.splice(editors.indexOf(editor), 1); $(this.config.el) .empty() .attr(this.attrsOrig); diff --git a/src/index.js b/src/index.js index 306a6739f..47a03c8c2 100644 --- a/src/index.js +++ b/src/index.js @@ -47,7 +47,7 @@ export default { init(config = {}) { const els = config.container; if (!els) throw new Error("'container' is required"); - config = { ...defaultConfig, ...config }; + config = { ...defaultConfig, ...config, grapesjs: this }; config.el = isElement(els) ? els : document.querySelector(els); const editor = new Editor(config).init(); diff --git a/src/navigator/view/ItemsView.js b/src/navigator/view/ItemsView.js index 313e524e1..7197d03d4 100644 --- a/src/navigator/view/ItemsView.js +++ b/src/navigator/view/ItemsView.js @@ -52,7 +52,8 @@ export default Backbone.View.extend({ removeChildren(removed) { const view = removed.viewLayer; if (!view) return; - view.remove.apply(view); + view.remove(); + removed.viewLayer = 0; }, /** diff --git a/src/style_manager/index.js b/src/style_manager/index.js index 6480d44f4..3b7fe8675 100644 --- a/src/style_manager/index.js +++ b/src/style_manager/index.js @@ -82,7 +82,8 @@ export default () => { }, onLoad() { - sectors.add(c.sectors); + // Use silent as sectors' view will be created and rendered on StyleManager.render + sectors.add(c.sectors, { silent: true }); }, postRender() { diff --git a/src/utils/Sorter.js b/src/utils/Sorter.js index 604cb381b..242025c2e 100644 --- a/src/utils/Sorter.js +++ b/src/utils/Sorter.js @@ -1055,6 +1055,8 @@ export default Backbone.View.extend({ this.toggleSortCursor(); this.toMove = null; + this.eventMove = 0; + this.dropModel = null; if (isFunction(onEndMove)) { const data = {