diff --git a/src/commands/view/SelectComponent.js b/src/commands/view/SelectComponent.js index 90bd934a9..50c78720d 100644 --- a/src/commands/view/SelectComponent.js +++ b/src/commands/view/SelectComponent.js @@ -116,20 +116,8 @@ export default { } } - // Get first valid hoverable model - if (model && !model.get('hoverable')) { - let parent = model && model.parent(); - while (parent && !parent.get('hoverable')) parent = parent.parent(); - model = parent; - } - - const opts = {}; this.currentDoc = trg.ownerDocument; - em.trigger('component:hover:before', model, opts); - if (!opts.abort) { - em.setHovered(model); - em.trigger('component:hover', model); - } + em.setHovered(model, { useValid: true }); frameView && em.set('currentFrame', frameView); }, @@ -299,28 +287,11 @@ export default { } if (model) { - let toSelect; - - if (model.get('selectable')) { - toSelect = model; - } else { - let parent = model.parent(); - while (parent && !parent.get('selectable')) parent = parent.parent(); - toSelect = parent; - } - - if (toSelect) { - // Avoid selection of inner text components during editing - if (em.isEditing() && !model.get('textable') && model.isChildOf('text')) { - return; - } - const opts = {}; - em.trigger('component:select:before', toSelect, opts); - if (!opts.abort) { - this.select(toSelect, ev); - em.trigger('component:select', toSelect); - } + // Avoid selection of inner text components during editing + if (em.isEditing() && !model.get('textable') && model.isChildOf('text')) { + return; } + this.select(model, ev); } }, @@ -331,7 +302,7 @@ export default { */ select(model, event = {}) { if (!model) return; - this.editor.select(model, { event }); + this.editor.select(model, { event, useValid: true }); this.initResize(model); }, diff --git a/src/editor/model/Editor.js b/src/editor/model/Editor.js index 5856d28eb..e3099f842 100644 --- a/src/editor/model/Editor.js +++ b/src/editor/model/Editor.js @@ -321,8 +321,22 @@ export default class EditorModel extends Model { multiple && this.removeSelected(selected.filter(s => !contains(els, s))); els.forEach(el => { - const model = getModel(el, $); - if (model && !model.get('selectable')) return; + let model = getModel(el); + + if (model) { + this.trigger('component:select:before', model, opts); + + // Check for valid selectable + if (!model.get('selectable') || opts.abort) { + if (opts.useValid) { + let parent = model.parent(); + while (parent && !parent.get('selectable')) parent = parent.parent(); + model = parent; + } else { + return; + } + } + } // Hanlde multiple selection if (ctrlKey && mltSel) { @@ -386,6 +400,7 @@ export default class EditorModel extends Model { const selected = this.get('selected'); opts.forceChange && this.removeSelected(model, opts); selected.addComponent(model, opts); + model && this.trigger('component:select', model, opts); }); } @@ -425,10 +440,31 @@ export default class EditorModel extends Model { * @private */ setHovered(el, opts = {}) { - const model = getModel(el, $); - if (model && !model.get('hoverable')) return; + if (!el) return this.set('componentHovered', ''); + + const ev = 'component:hover'; + let model = getModel(el); + + if (!model) return; + opts.forceChange && this.set('componentHovered', ''); - this.set('componentHovered', model, opts); + this.trigger(`${ev}:before`, model, opts); + + // Check for valid hoverable + if (!model.get('hoverable')) { + if (opts.useValid && !opts.abort) { + let parent = model && model.parent(); + while (parent && !parent.get('hoverable')) parent = parent.parent(); + model = parent; + } else { + return; + } + } + + if (!opts.abort) { + this.set('componentHovered', model, opts); + this.trigger(ev, model, opts); + } } getHovered() { diff --git a/src/utils/mixins.js b/src/utils/mixins.js index 3adbf83ab..f1dd4b354 100644 --- a/src/utils/mixins.js +++ b/src/utils/mixins.js @@ -187,7 +187,7 @@ export const escape = (str = '') => { */ const getModel = (el, $) => { let model = el; - if (!$ && el.__cashData) { + if (!$ && el && el.__cashData) { model = el.__cashData.model; } else if (isElement(el)) { model = $(el).data('model');