diff --git a/src/commands/view/SelectComponent.js b/src/commands/view/SelectComponent.js index 78bdee21e..4a9c09a21 100644 --- a/src/commands/view/SelectComponent.js +++ b/src/commands/view/SelectComponent.js @@ -202,16 +202,36 @@ module.exports = { if (model) { if (model.get('selectable')) { - editor.select(model); - this.initResize(model); + this.select(model, e); } else { let parent = model.parent(); while (parent && !parent.get('selectable')) parent = parent.parent(); - parent && editor.select(parent); + this.select(parent, e); } } }, + /** + * Select component + * @param {Component} model + * @param {Event} event + */ + select(model, event = {}) { + if (!model) return; + const ctrlKey = event.ctrlKey || event.metaKey; + const { editor } = this; + console.log('shiftKey', event.shiftKey, 'ctrlKey', ctrlKey); + + if (ctrlKey) { + editor.selectToggle(model); + // else if (shiftKey) // multiple selection + } else { + editor.select(model); + } + + this.initResize(model); + }, + /** * Update badge for the component * @param {Object} Component diff --git a/src/dom_components/index.js b/src/dom_components/index.js index ca8aed7e3..cd2a505d1 100644 --- a/src/dom_components/index.js +++ b/src/dom_components/index.js @@ -193,6 +193,10 @@ module.exports = () => { em.get('Parser').compTypes = componentTypes; em.on('change:selectedComponent', this.componentChanged, this); em.on('change:componentHovered', this.componentHovered, this); + + const selected = em.get('selected'); + em.listenTo(selected, 'add', this.selectAdded); + em.listenTo(selected, 'remove', this.selectRemoved); } // Build wrapper @@ -511,6 +515,20 @@ module.exports = () => { return; }, + selectAdded(component) { + console.log('ADDED', component); + const status = 'selected'; + component.set({ status }); + }, + + selectRemoved(component) { + console.log('Removed', component); + component.set({ + status: '', + state: '' + }); + }, + /** * Triggered when the selected component is changed * @private diff --git a/src/dom_components/view/ComponentView.js b/src/dom_components/view/ComponentView.js index 29cf256df..e3973c13a 100644 --- a/src/dom_components/view/ComponentView.js +++ b/src/dom_components/view/ComponentView.js @@ -24,7 +24,7 @@ module.exports = Backbone.View.extend({ this.classe = this.attr.class || []; const $el = this.$el; const classes = model.get('classes'); - this.listenTo(model, 'destroy remove', this.remove); + //this.listenTo(model, 'destroy remove', this.remove); this.listenTo(model, 'change:style', this.updateStyle); this.listenTo(model, 'change:attributes', this.updateAttributes); this.listenTo(model, 'change:highlightable', this.updateHighlight); diff --git a/src/dom_components/view/ComponentsView.js b/src/dom_components/view/ComponentsView.js index 12e46091e..2c7199e7a 100644 --- a/src/dom_components/view/ComponentsView.js +++ b/src/dom_components/view/ComponentsView.js @@ -8,6 +8,15 @@ module.exports = Backbone.View.extend({ const coll = this.collection; this.listenTo(coll, 'add', this.addTo); this.listenTo(coll, 'reset', this.resetChildren); + this.listenTo(coll, 'remove', this.removeChildren); + }, + + removeChildren(removed) { + console.log('removed', removed); + const view = removed.view; + view.prototype.remove.apply(view); + const children = view.childrenView; + children && children.stopListening(); }, /** diff --git a/src/editor/index.js b/src/editor/index.js index 4482e264e..745d79e21 100644 --- a/src/editor/index.js +++ b/src/editor/index.js @@ -404,6 +404,42 @@ module.exports = config => { return this; }, + /** + * Add component to selection + * @param {Component|HTMLElement} el Component to select + * @return {this} + * @example + * editor.selectAdd(model); + */ + selectAdd(el) { + em.addSelected(el); + return this; + }, + + /** + * Remove component from selection + * @param {Component|HTMLElement} el Component to select + * @return {this} + * @example + * editor.selectRemove(model); + */ + selectRemove(el) { + em.removeSelected(el); + return this; + }, + + /** + * Toggle component selection + * @param {Component|HTMLElement} el Component to select + * @return {this} + * @example + * editor.selectToggle(model); + */ + selectToggle(el) { + em.toggleSelected(el); + return this; + }, + /** * Set device to the editor. If the device exists it will * change the canvas to the proper width diff --git a/src/editor/model/Editor.js b/src/editor/model/Editor.js index c52e54a97..57dd87e9a 100644 --- a/src/editor/model/Editor.js +++ b/src/editor/model/Editor.js @@ -24,6 +24,7 @@ const deps = [ ]; const Backbone = require('backbone'); +const { Collection } = Backbone; let timedInterval; require('utils/extender')({ @@ -34,18 +35,21 @@ require('utils/extender')({ const $ = Backbone.$; module.exports = Backbone.Model.extend({ - defaults: { - clipboard: null, - designerMode: false, - selectedComponent: null, - componentHovered: null, - previousModel: null, - changesCount: 0, - storables: [], - modules: [], - toLoad: [], - opened: {}, - device: '' + defaults() { + return { + selected: new Collection(), + clipboard: null, + designerMode: false, + selectedComponent: null, + componentHovered: null, + previousModel: null, + changesCount: 0, + storables: [], + modules: [], + toLoad: [], + opened: {}, + device: '' + }; }, initialize(c = {}) { @@ -241,6 +245,47 @@ module.exports = Backbone.Model.extend({ this.set('selectedComponent', model, opts); }, + /** + * Add component to selection + * @param {Component|HTMLElement} el Component to select + * @param {Object} [opts={}] Options, optional + * @private + */ + addSelected(el, opts = {}) { + let model = el; + isElement(el) && (model = $(el).data('model')); + if (model && !model.get('selectable')) return; + this.get('selected').push(model, opts); + }, + + /** + * Remove component from selection + * @param {Component|HTMLElement} el Component to select + * @param {Object} [opts={}] Options, optional + * @private + */ + removeSelected(el, opts = {}) { + let model = el; + isElement(el) && (model = $(el).data('model')); + this.get('selected').remove(model, opts); + }, + + /** + * Toggle component selection + * @param {Component|HTMLElement} el Component to select + * @param {Object} [opts={}] Options, optional + * @private + */ + toggleSelected(el, opts = {}) { + let model = el; + isElement(el) && (model = $(el).data('model')); + if (this.get('selected').contains(model)) { + this.removeSelected(model, opts); + } else { + this.addSelected(model, opts); + } + }, + /** * Hover a component * @param {Component|HTMLElement} el Component to select