diff --git a/Packages/ohif-core/client/components/base/mixins/dropdown.js b/Packages/ohif-core/client/components/base/mixins/dropdown.js index 048562dd2..49240db97 100644 --- a/Packages/ohif-core/client/components/base/mixins/dropdown.js +++ b/Packages/ohif-core/client/components/base/mixins/dropdown.js @@ -114,8 +114,8 @@ OHIF.mixins.dropdown = new OHIF.Mixin({ if (event) { const originalEventTouches = event.originalEvent.touches; const position = { - left: 0, - top: 0 + left: 0, + top: 0 }; if (originalEventTouches && originalEventTouches.length > 0) { @@ -123,7 +123,7 @@ OHIF.mixins.dropdown = new OHIF.Mixin({ position.top = originalEventTouches[0].pageY; } else { position.left = event.clientX; - position.top = event.clientY + position.top = event.clientY; } if (centered) { diff --git a/Packages/ohif-core/client/ui/bounded/bounded.js b/Packages/ohif-core/client/ui/bounded/bounded.js index d316d119c..1a69b030d 100644 --- a/Packages/ohif-core/client/ui/bounded/bounded.js +++ b/Packages/ohif-core/client/ui/bounded/bounded.js @@ -172,29 +172,33 @@ class Bounded { } }; - this.cssTransformHandler = (elementInfo, boundingInfo) => { + this.getCSSTranslate = () => { const matrixToArray = str => str.match(/(-?[0-9\.]+)/g); const transformMatrix = matrixToArray(this.$positionElement.css('transform')) || []; - let translateX = parseFloat(transformMatrix[4]) || 0; - let translateY = parseFloat(transformMatrix[5]) || 0; + return { + x: parseFloat(transformMatrix[4]) || 0, + y: parseFloat(transformMatrix[5]) || 0 + }; + }; + this.cssTransformHandler = (elementInfo, boundingInfo, translate) => { if (elementInfo.x1 > boundingInfo.x1) { - translateX -= elementInfo.x1 - boundingInfo.x1; + translate.x -= elementInfo.x1 - boundingInfo.x1; } if (elementInfo.y1 > boundingInfo.y1) { - translateY -= elementInfo.y1 - boundingInfo.y1; + translate.y -= elementInfo.y1 - boundingInfo.y1; } if (elementInfo.x0 < boundingInfo.x0) { - translateX += boundingInfo.x0 - elementInfo.x0; + translate.x += boundingInfo.x0 - elementInfo.x0; } if (elementInfo.y0 < boundingInfo.y0) { - translateY += boundingInfo.y0 - elementInfo.y0; + translate.y += boundingInfo.y0 - elementInfo.y0; } - const translation = `translate(${translateX}px, ${translateY}px)`; + const translation = `translate(${translate.x}px, ${translate.y}px)`; OHIF.ui.styleProperty.set(this.positionElement, 'transform', translation); }; @@ -205,8 +209,9 @@ class Bounded { const boundingInfo = Bounded.spatialInfo(boundingElement, boundingElement); // Check if CSS positioning or transform will be used - if (useTransform) { - this.cssTransformHandler(elementInfo, boundingInfo); + const translate = this.getCSSTranslate(); + if (useTransform && (translate.x || translate.y)) { + this.cssTransformHandler(elementInfo, boundingInfo, translate); } else { this.cssPositionHandler(elementInfo, boundingInfo); } diff --git a/Packages/ohif-core/client/ui/draggable/draggable.js b/Packages/ohif-core/client/ui/draggable/draggable.js index a491ac398..26b9c2798 100644 --- a/Packages/ohif-core/client/ui/draggable/draggable.js +++ b/Packages/ohif-core/client/ui/draggable/draggable.js @@ -105,6 +105,7 @@ function makeDraggable(element, options) { $container.css('cursor', 'move'); $element.css('cursor', 'move'); + $element.addClass('dragging'); reposition(elementLeft, elementTop); @@ -125,6 +126,7 @@ function makeDraggable(element, options) { function stopMoving() { $container.css('cursor', 'default'); $element.css('cursor', options.defaultElementCursor); + $element.removeClass('dragging'); $(document).off('mousemove', moveHandler); $(document).off('touchmove', moveHandler); diff --git a/Packages/ohif-select-tree/client/components/selectTree/selectTree.js b/Packages/ohif-select-tree/client/components/selectTree/selectTree.js index bd739f98f..f9f22850e 100644 --- a/Packages/ohif-select-tree/client/components/selectTree/selectTree.js +++ b/Packages/ohif-select-tree/client/components/selectTree/selectTree.js @@ -64,6 +64,9 @@ Template.selectTree.onRendered(() => { instance.component = component; + // Force to hardware acceleration to move element if browser supports translate property + instance.useTransform = OHIF.ui.styleProperty.check('transform', 'translate(1px, 1px)'); + // Set the margin to display the common section if (!$treeRoot.hasClass('started')) { const isthreeColumns = instance.data.threeColumns; @@ -73,7 +76,9 @@ Template.selectTree.onRendered(() => { } // Make the component respect the window boundaries - $treeRoot.bounded(); + if (rootComponent === component) { + $treeRoot.bounded(); + } // Check if the component will be rendered on a specific position const position = instance.data.position; @@ -99,7 +104,7 @@ Template.selectTree.onRendered(() => { }); // Update the component's viewport height - instance.updateHeight = searchTerm => { + instance.updateHeight = _.throttle(searchTerm => { let height; // Check if there's a search term @@ -111,10 +116,9 @@ Template.selectTree.onRendered(() => { height = rootInstance.$('.tree-options:last').data('height'); } - // Update the viewport's height and trigger the bounded event - rootInstance.$('.tree-options:first').first().height(height) - .on('transitionend', () => $treeRoot.trigger('spatialChanged')); - }; + // Update the viewport's height + rootInstance.$('.tree-options:first').first().height(height); + }, 100, { trailing: false }); // Update the opened node instance.updateOpen = () => { @@ -136,6 +140,11 @@ Template.selectTree.onRendered(() => { const height = $treeOptions.height(); $treeOptions.data('height', height); + $treeOptions.off('transitionend').on('transitionend', event => { + if (event.target !== event.currentTarget) return; + $treeRoot.trigger('spatialChanged'); + }); + instance.autorun(() => { // Run this computation everytime the current node is changed instance.data.currentNode.dep.depend(); @@ -208,6 +217,7 @@ Template.selectTree.events({ const eventComponent = $target.data('component'); const rootComponent = instance.data.root || component; const rootInstance = rootComponent.templateInstance; + const offsetTop = $target.closest('.wrapperLabel').offset().top; // Change the component's node component.node(eventComponent.value()); @@ -252,12 +262,45 @@ Template.selectTree.events({ // Get the position of the clicked element const position = $label.position(); + const getPosition = $element => { + if (instance.useTransform) { + const matrixToArray = str => str.match(/(-?[0-9\.]+)/g); + const transformMatrix = matrixToArray($element.css('transform')) || []; + return { + x: parseFloat(transformMatrix[4]) || 0, + y: parseFloat(transformMatrix[5]) || 0 + }; + } else { + return { + x: parseFloat($element.css('left')), + y: parseFloat($element.css('top')) + }; + } + }; + + const setPosition = ($element, position) => { + if (instance.useTransform) { + const translation = `translate(${position.x}px, ${position.y}px)`; + OHIF.ui.styleProperty.set($element[0], 'transform', translation); + } else { + $element.css('left', `${position.x}px`); + $element.css('top', `${position.y}px`); + } + }; + Meteor.defer(() => { const $treeNode = $label.parent().siblings('.select-tree'); // Do the transition from the clicked position to top $treeNode.css(position); setTimeout(() => $treeNode.css('top', 0)); + + const optionsTop = $target.closest('.tree-options').position().top; + const $treeRoot = $target.closest('.select-tree-root'); + const treeOffsetTop = $treeRoot.offset().top; + const treeRootPosition = getPosition($treeRoot); + treeRootPosition.y += offsetTop - treeOffsetTop - optionsTop; + setPosition($treeRoot, treeRootPosition); }); } },