diff --git a/src/canvas/view/CanvasView.js b/src/canvas/view/CanvasView.js index 8523b6c8b..b8af53a44 100644 --- a/src/canvas/view/CanvasView.js +++ b/src/canvas/view/CanvasView.js @@ -362,7 +362,7 @@ export default Backbone.View.extend({ }, /** - * Returns element's data info + * Returns element's rect info * @param {HTMLElement} el * @return {Object} * @private diff --git a/src/commands/view/SelectComponent.js b/src/commands/view/SelectComponent.js index 71ad8e441..48abe5307 100644 --- a/src/commands/view/SelectComponent.js +++ b/src/commands/view/SelectComponent.js @@ -1,5 +1,5 @@ import Backbone from 'backbone'; -import { bindAll, isElement, isUndefined } from 'underscore'; +import { bindAll, isElement, isUndefined, debounce } from 'underscore'; import { on, off, getUnitFromValue, isTaggableNode } from 'utils/mixins'; import ToolbarView from 'dom_components/view/ToolbarView'; import Toolbar from 'dom_components/model/Toolbar'; @@ -54,7 +54,7 @@ export default { em[method]('change:componentHovered', this.onHovered, this); em[method]('component:update', this.updateAttached, this); em[method]('change:canvasOffset', this.updateAttached, this); - em[method]('frame:scroll', this.onFrameScroll); + // em[method]('frame:scroll', this.onFrameScroll); }; trigger(win, body); // TODO remove em.get('Canvas') @@ -85,12 +85,6 @@ export default { } } - // Adjust tools scroll top - if (!this.adjScroll) { - this.adjScroll = 1; - this.updateAttached(); - } - // Get first valid hoverable model if (model && !model.get('hoverable')) { let parent = model && model.parent(); @@ -102,15 +96,19 @@ export default { }, onHovered(em, component) { - const trg = component && component.getEl(); - if (trg) { - const pos = this.getElementPos(trg); - this.updateBadge(trg, pos); - this.updateHighlighter(trg, pos); - this.showElementOffset(trg, pos); + const el = component && component.getEl(); + + if (el) { + const pos = this.getElementPos(el); + this.elHovered = { el, pos }; + this.updateToolsHover(el, pos); } }, + getElHovered() { + return this.elHovered || {}; + }, + /** * Out command * @param {Object} e @@ -287,7 +285,6 @@ export default { const ppfx = config.pStylePrefix || ''; const customeLabel = config.customBadgeLabel; const model = $(el).data('model'); - this.cacheEl = el; if (!model || !model.get('badgable')) return; const badge = this.getBadge(); const icon = model.getIcon(); @@ -359,11 +356,10 @@ export default { // Get the selected model directly from the Editor as the event might // be triggered manually without the model const model = this.em.getSelected(); - const view = model && model.view; + const el = model && model.getEl(); this.updateToolbar(model); - if (view) { - const { el } = view; + if (el) { this.showFixedElementOffset(el); this.hideElementOffset(); this.hideHighlighter(); @@ -525,7 +521,6 @@ export default { } var toolbar = model.get('toolbar'); - var ppfx = this.ppfx; var showToolbar = em.get('Config').showToolbar; if (showToolbar && toolbar && toolbar.length) { @@ -542,10 +537,8 @@ export default { } this.toolbar.reset(toolbar); - const view = model.view; toolbarStyle.top = '-100px'; toolbarStyle.left = 0; - setTimeout(() => view && this.updateToolbarPos(view.el), 0); } else { toolbarStyle.display = 'none'; } @@ -556,39 +549,42 @@ export default { * @param {HTMLElement} el * @param {Object} pos */ - updateToolbarPos(el, elPos) { + updateToolbarPos(el, pos) { const { canvas } = this; const unit = 'px'; const toolbarEl = canvas.getToolbarEl(); const toolbarStyle = toolbarEl.style; toolbarStyle.opacity = 0; - const pos = canvas.getTargetToElementDim(toolbarEl, el, { - elPos, - event: 'toolbarPosUpdate' - }); if (pos) { - const frameOffset = canvas.getCanvasView().getFrameOffset(); - pos.top = this.frameRect(el, 1, pos); - pos.left = this.frameRect(el, 0, pos); + const cv = canvas.getCanvasView(); + const frCvOff = cv.getPosition(); + const frameOffset = cv.getFrameOffset(); + const toolbarH = toolbarEl ? toolbarEl.offsetHeight : 0; + const toolbarW = toolbarEl ? toolbarEl.offsetWidth : 0; + let top = this.frameRect(el, 1, pos) - toolbarH; + let left = this.frameRect(el, 0, pos) + pos.width - toolbarW; + left = left < 0 ? 0 : left; // Scroll with the window if the top edge is reached and the // element is bigger than the canvas - const fullHeight = pos.elementHeight + pos.targetHeight; - if (pos.top <= pos.canvasTop && !(fullHeight >= frameOffset.height)) { - pos.top = pos.top + fullHeight; + const fullHeight = pos.height + toolbarH; + const elIsShort = fullHeight < frameOffset.height; + + if (top < frCvOff.top && elIsShort) { + top = top + fullHeight; + } else if (top < 0) { + top = top > -pos.height ? 0 : top + fullHeight - toolbarH; } // Check left position of the toolbar - const elRight = pos.elementLeft + pos.elementWidth; - let left = elRight - pos.targetWidth; + const leftR = left + toolbarW; - if (elRight > pos.canvasWidth) { - left -= elRight - pos.canvasWidth; + if (leftR > frCvOff.width) { + left -= leftR - frCvOff.width; } - left = left < 0 ? 0 : left; - toolbarStyle.top = `${pos.top}${unit}`; + toolbarStyle.top = `${top}${unit}`; toolbarStyle.left = `${left}${unit}`; toolbarStyle.opacity = ''; } @@ -624,34 +620,41 @@ export default { * @private */ onFrameScroll(ev) { - const el = this.cacheEl; + const { el } = this.getElHovered(); + const pos = this.getElementPos(el); // TODO check if this could be cached + const model = this.em.getSelected(); + const viewEl = model && model.getEl(); + el && this.updateToolsHover(el, pos); + viewEl && this.updateToolbarPos(viewEl, this.getElementPos(viewEl)); + }, - if (el) { - const elPos = this.getElementPos(el); - this.updateBadge(el, elPos); - const model = this.em.getSelected(); - const viewEl = model && model.getEl(); - viewEl && this.updateToolbarPos(viewEl); - this.updateHighlighter(el, elPos); - this.showElementOffset(el, elPos); - } + /** + * Update tools visible on hover + * @param {HTMLElement} el + * @param {Object} pos + */ + updateToolsHover(el, pos) { + this.updateBadge(el, pos); + this.updateHighlighter(el, pos); + this.showElementOffset(el, pos); }, /** * Update attached elements, eg. component toolbar */ - updateAttached() { + updateAttached: debounce(function() { const { resizer, em } = this; const model = em.getSelected(); - const view = model && model.view; + const el = model && model.getEl(); - if (view) { - const { el } = view; - this.updateToolbarPos(el); + if (el && this.elSelected !== el) { + this.elSelected = el; + const pos = this.getElementPos(el); + this.updateToolbarPos(el, pos); this.showFixedElementOffset(el); resizer && resizer.updateContainer(); } - }, + }), /** * Returns element's data info