diff --git a/Packages/ohif-core/client/ui/draggable/draggable.js b/Packages/ohif-core/client/ui/draggable/draggable.js index 3bf8843d0..eb2490fde 100644 --- a/Packages/ohif-core/client/ui/draggable/draggable.js +++ b/Packages/ohif-core/client/ui/draggable/draggable.js @@ -1,3 +1,5 @@ +import { OHIF } from 'meteor/ohif:core'; + // Allow attaching to jQuery selectors $.fn.draggable = function(options) { makeDraggable(this, options); @@ -12,19 +14,33 @@ $.fn.draggable = function(options) { * @param element */ function makeDraggable(element, options) { - var container = $(window); - var diffX, - diffY, - wasNotDragged = true; + const $element = element; + + // Force to hardware acceleration to move element if browser supports translate property + const { styleProperty } = OHIF.ui; + const useTransform = styleProperty.check('transform', 'translate(1px, 1px)'); + + const $container = $(window); + let diffX; + let diffY; + let wasNotDragged = true; + + let lastCursor, lastOffset; + let lastTranslateX = 0; + let lastTranslateY = 0; options = options || {}; options.defaultElementCursor = options.defaultElementCursor || 'default'; // initialize dragged flag - element.data('wasDragged', false); + $element.data('wasDragged', false); + + function matrixToArray(str) { + return str.match(/(-?[0-9\.]+)/g); + } function getCursorCoords(e) { - var cursor = { + const cursor = { x: e.clientX, y: e.clientY }; @@ -33,12 +49,28 @@ function makeDraggable(element, options) { if (cursor.x === undefined) { cursor.x = e.originalEvent.touches[0].pageX; } + if (cursor.y === undefined) { cursor.y = e.originalEvent.touches[0].pageY; } + return cursor; } + function reposition(elementLeft, elementTop) { + if (useTransform) { + const translation = `translate(${elementLeft}px, ${elementTop}px)`; + styleProperty.set($element[0], 'transform', translation); + } else { + $element.css({ + left: elementLeft + 'px', + top: elementTop + 'px', + bottom: 'auto', // Setting these to empty doesn't seem to work in Firefox or Safari + right: 'auto' + }); + } + } + function startMoving(e) { // Prevent dragging dialog by clicking on slider // (could be extended for buttons, not sure it's necessary @@ -50,27 +82,31 @@ function makeDraggable(element, options) { if (e.button !== 0) return; // Stop the dragging if the element is being resized - if ($(element).hasClass('resizing')) { + if ($element.hasClass('resizing')) { return; } - var elementTop = parseFloat(element.offset().top), - elementLeft = parseFloat(element.offset().left); + let elementLeft = parseFloat($element.offset().left); + let elementTop = parseFloat($element.offset().top); - var cursor = getCursorCoords(e); - diffX = cursor.x - elementLeft; - diffY = cursor.y - elementTop; + const cursor = getCursorCoords(e); + if (useTransform) { + lastCursor = cursor; + lastOffset = $element.offset(); + const transformMatrix = matrixToArray($element.css('transform')) || []; + lastTranslateX = parseFloat(transformMatrix[4]) || lastTranslateX; + lastTranslateY = parseFloat(transformMatrix[5]) || lastTranslateX; + elementLeft = lastTranslateX; + elementTop = lastTranslateY; + } else { + diffX = cursor.x - elementLeft; + diffY = cursor.y - elementTop; + } - container.css('cursor', 'move'); - element.css('cursor', 'move'); + $container.css('cursor', 'move'); + $element.css('cursor', 'move'); - element.css({ - cursor: 'move', - left: elementLeft + 'px', - top: elementTop + 'px', - bottom: 'auto', // Setting these to empty doesn't seem to work in Firefox or Safari - right: 'auto' - }); + reposition(elementLeft, elementTop); $(document).on('mousemove', moveHandler); $(document).on('mouseup', stopMoving); @@ -80,15 +116,15 @@ function makeDraggable(element, options) { // let outside world know that the element in question has been dragged if (wasNotDragged) { - element.data('wasDragged', true); + $element.data('wasDragged', true); wasNotDragged = false; } } function stopMoving() { - container.css('cursor', 'default'); - element.css('cursor', options.defaultElementCursor); + $container.css('cursor', 'default'); + $element.css('cursor', options.defaultElementCursor); $(document).off('mousemove', moveHandler); $(document).off('touchmove', moveHandler); @@ -98,35 +134,57 @@ function makeDraggable(element, options) { // Prevent dialog box dragging whole page in iOS e.preventDefault(); - var elementWidth = parseFloat(element.outerWidth()), - elementHeight = parseFloat(element.outerHeight()), - containerWidth = parseFloat(container.width()), - containerHeight = parseFloat(container.height()); + const elementWidth = parseFloat($element.outerWidth()); + const elementHeight = parseFloat($element.outerHeight()); + const containerWidth = parseFloat($container.width()); + const containerHeight = parseFloat($container.height()); - var cursor = getCursorCoords(e); + const cursor = getCursorCoords(e); - var elementLeft = cursor.x - diffX; - var elementTop = cursor.y - diffY; + let elementLeft, elementTop; + if (useTransform) { + elementLeft = lastTranslateX - (lastCursor.x - cursor.x); + elementTop = lastTranslateY - (lastCursor.y - cursor.y); - elementLeft = Math.max(elementLeft, 0); - elementTop = Math.max(elementTop, 0); + const limitX = containerWidth - elementWidth; + const limitY = containerHeight - elementHeight; + const sumX = lastOffset.left + (elementLeft - lastTranslateX); + const sumY = lastOffset.top + (elementTop - lastTranslateY); - if (elementLeft + elementWidth > containerWidth) { - elementLeft = containerWidth - elementWidth; + if (sumX > limitX) { + elementLeft -= sumX - limitX; + } + + if (sumY > limitY) { + elementTop -= sumY - limitY; + } + + if (sumX < 0) { + elementLeft += 0 - sumX; + } + + if (sumY < 0) { + elementTop += 0 - sumY; + } + } else { + elementLeft = cursor.x - diffX; + elementTop = cursor.y - diffY; + + elementLeft = Math.max(elementLeft, 0); + elementTop = Math.max(elementTop, 0); + + if (elementLeft + elementWidth > containerWidth) { + elementLeft = containerWidth - elementWidth; + } + + if (elementTop + elementHeight > containerHeight) { + elementTop = containerHeight - elementHeight; + } } - if (elementTop + elementHeight > containerHeight) { - elementTop = containerHeight - elementHeight; - } - - element.css({ - left: elementLeft + 'px', - top: elementTop + 'px', - bottom: 'auto', // Setting these to empty doesn't seem to work in Firefox or Safari - right: 'auto' - }); + reposition(elementLeft, elementTop); } - element.on('mousedown', startMoving); - element.on('touchstart', startMoving); -}; + $element.on('mousedown', startMoving); + $element.on('touchstart', startMoving); +} diff --git a/Packages/ohif-core/client/ui/index.js b/Packages/ohif-core/client/ui/index.js index 76df02b1c..b5252c371 100644 --- a/Packages/ohif-core/client/ui/index.js +++ b/Packages/ohif-core/client/ui/index.js @@ -10,3 +10,4 @@ import './notifications/notifications.js'; import './popover/display.js'; import './resizable/resizable.js'; import './unsavedChanges/unsavedChanges.js'; +import './styleProperty.js'; diff --git a/Packages/ohif-core/client/ui/styleProperty.js b/Packages/ohif-core/client/ui/styleProperty.js new file mode 100644 index 000000000..5dcca1d64 --- /dev/null +++ b/Packages/ohif-core/client/ui/styleProperty.js @@ -0,0 +1,68 @@ +import { OHIF } from 'meteor/ohif:core'; + +/* + * https://github.com/swederik/dragula/blob/ccc15d75186f5168e7abadbe3077cf12dab09f8b/styleProperty.js + */ +(function() { + 'use strict'; + + const browserProps = {}; + + function eachVendor(prop, fn) { + const prefixes = ['Webkit', 'Moz', 'ms', 'O']; + fn(prop); + for (let i = 0; i < prefixes.length; i++) { + fn(prefixes[i] + prop.charAt(0).toUpperCase() + prop.slice(1)); + } + } + + function check(property, testValue) { + const sandbox = document.createElement('iframe'); + const element = document.createElement('p'); + + document.body.appendChild(sandbox); + sandbox.contentDocument.body.appendChild(element); + const support = set(element, property, testValue); + + // We have to do this because remove() is not supported by IE11 and below + sandbox.parentElement.removeChild(sandbox); + return support; + } + + function checkComputed(el, prop) { + const computed = window.getComputedStyle(el).getPropertyValue(prop); + return ((computed !== void 0) && computed.length > 0 && computed !== 'none'); + } + + function set(el, prop, value) { + let match = false; + + if (browserProps[prop] === void 0) { + eachVendor(prop, function(vendorProp) { + if (el.style[vendorProp] !== void 0 && match === false) { + el.style[vendorProp] = value; + if (checkComputed(el, vendorProp)) { + match = true; + browserProps[prop] = vendorProp; + } + } + }); + } else { + el.style[browserProps[prop]] = value; + return true; + } + + return match; + } + + const styleProperty = { + check, + set + }; + + OHIF.ui.styleProperty = styleProperty; +}()); + +const { styleProperty } = OHIF.ui; + +export { styleProperty }; diff --git a/Packages/ohif-design/styles/components/dialog.styl b/Packages/ohif-design/styles/components/dialog.styl index 824ec41df..a753c6712 100644 --- a/Packages/ohif-design/styles/components/dialog.styl +++ b/Packages/ohif-design/styles/components/dialog.styl @@ -1,11 +1,11 @@ @import "{ohif:design}/app" .viewerDialogs>.dialog-animated - &:not(.dialog-closed):not(.dialog-open) - display: none + &:not(.dialog-closed):not(.dialog-open) + display: none - &.dialog-closed - animateSlideOutUp() + &.dialog-closed + animateFadeOut() - &.dialog-open - animateSlideInDown() \ No newline at end of file + &.dialog-open + animateFadeIn() diff --git a/Packages/ohif-measurements/client/components/measurementTable/measurementTableHUD/measurementTableHUD.styl b/Packages/ohif-measurements/client/components/measurementTable/measurementTableHUD/measurementTableHUD.styl index 50f8872ef..0bd9c0716 100644 --- a/Packages/ohif-measurements/client/components/measurementTable/measurementTableHUD/measurementTableHUD.styl +++ b/Packages/ohif-measurements/client/components/measurementTable/measurementTableHUD/measurementTableHUD.styl @@ -1,4 +1,4 @@ -@import "{ohif:design}/app" +@require '{ohif:design}/app' $borderColor = rgba(77, 99, 110, 0.81) @@ -14,7 +14,7 @@ $borderColor = rgba(77, 99, 110, 0.81) right: 3px top: auto width: 318px - z-index: 10000 + z-index: 1 .measurementTableView .scrollable margin-left: 0 diff --git a/Packages/ohif-viewerbase/client/components/viewer/cineDialog/cineDialog.js b/Packages/ohif-viewerbase/client/components/viewer/cineDialog/cineDialog.js index 074f50ac4..f634a6104 100644 --- a/Packages/ohif-viewerbase/client/components/viewer/cineDialog/cineDialog.js +++ b/Packages/ohif-viewerbase/client/components/viewer/cineDialog/cineDialog.js @@ -2,7 +2,6 @@ import { Template } from 'meteor/templating'; import { SimpleSchema } from 'meteor/aldeed:simple-schema'; import { Session } from 'meteor/session'; import { Tracker } from 'meteor/tracker'; -import { Random } from 'meteor/random'; import { _ } from 'meteor/underscore'; import { $ } from 'meteor/jquery'; import { OHIF } from 'meteor/ohif:core'; diff --git a/Packages/ohif-viewerbase/client/lib/styleProperty.js b/Packages/ohif-viewerbase/client/lib/styleProperty.js deleted file mode 100644 index 86464272a..000000000 --- a/Packages/ohif-viewerbase/client/lib/styleProperty.js +++ /dev/null @@ -1,60 +0,0 @@ -/* -https://github.com/swederik/dragula/blob/ccc15d75186f5168e7abadbe3077cf12dab09f8b/styleProperty.js - */ -'use strict'; -var browserProps = {}; - -function eachVendor(prop, fn) { - var prefixes = ['Webkit', 'Moz', 'ms', 'O']; - var i = 0; - var l = prefixes.length; - fn(prop); - for (; i < l; i++) { - fn(prefixes[i] + prop.charAt(0).toUpperCase() + prop.slice(1)); - } -} - -function check(property, testValue) { - var sandbox = document.createElement('iframe'); - var el = document.createElement('p'); - var support; - - document.body.appendChild(sandbox); - sandbox.contentDocument.body.appendChild(el); - support = set(el, property, testValue); - - // We have to do this because remove() is not supported by IE11 and below - sandbox.parentElement.removeChild(sandbox); - return support; -} - -function checkComputed(el, prop) { - var computed = window.getComputedStyle(el).getPropertyValue(prop); - return ((computed !== void 0) && computed.length > 0 && computed !== 'none'); -} - -function set(el, prop, value) { - var match = false; - if (browserProps[prop] === void 0) { - eachVendor(prop, function(vendorProp) { - if (el.style[vendorProp] !== void 0 && match === false) { - el.style[vendorProp] = value; - if (checkComputed(el, vendorProp)) { - match = true; - browserProps[prop] = vendorProp; - } - } - }); - } else { - el.style[browserProps[prop]] = value; - return true; - } - return match; -} - -const styleProperty = { - check, - set, -}; - -export { styleProperty }; \ No newline at end of file diff --git a/Packages/ohif-viewerbase/client/lib/thumbnailDragHandlers.js b/Packages/ohif-viewerbase/client/lib/thumbnailDragHandlers.js index b1434d91b..6a84a90d1 100644 --- a/Packages/ohif-viewerbase/client/lib/thumbnailDragHandlers.js +++ b/Packages/ohif-viewerbase/client/lib/thumbnailDragHandlers.js @@ -1,6 +1,5 @@ import { $ } from 'meteor/jquery'; import { OHIF } from 'meteor/ohif:core'; -import { styleProperty } from './styleProperty' const cloneElement = (element, targetId) => { // Clone the DOM element @@ -32,7 +31,7 @@ const thumbnailDragStartHandler = (event, data) => { // Force to hardware acceleration to move element // if browser supports translate property - const useTransform = styleProperty.check('transform', 'translate(1px, 1px)'); + const useTransform = OHIF.ui.styleProperty.check('transform', 'translate(1px, 1px)'); // Clone the image thumbnail const targetId = 'DragClone'; @@ -55,8 +54,7 @@ const thumbnailDragStartHandler = (event, data) => { if (event.type === 'touchstart') { cursorX = event.originalEvent.touches[0].pageX; cursorY = event.originalEvent.touches[0].pageY; - } - else { + } else { cursorX = event.pageX; cursorY = event.pageY; @@ -97,7 +95,7 @@ const thumbnailDragStartHandler = (event, data) => { top: cursorY - diff.y, }); } else { - const viewerHeight= $('#viewer').height(); + const viewerHeight = $('#viewer').height(); const headerHeight = $('.header').outerHeight(); const heightDiff = viewerHeight + headerHeight; @@ -108,7 +106,7 @@ const thumbnailDragStartHandler = (event, data) => { const positionY = cursorY - diff.y - heightDiff; const translation = `translate(${positionX}px, ${positionY}px)`; - styleProperty.set($clone.get(0), 'transform', translation); + OHIF.ui.styleProperty.set($clone.get(0), 'transform', translation); } }; @@ -119,8 +117,7 @@ const thumbnailDragHandler = event => { if (event.type === 'touchmove') { cursorX = event.originalEvent.changedTouches[0].pageX; cursorY = event.originalEvent.changedTouches[0].pageY; - } - else { + } else { cursorX = event.pageX; cursorY = event.pageY; } @@ -131,7 +128,7 @@ const thumbnailDragHandler = event => { // Force to hardware acceleration to move element // if browser supports translate property - const useTransform = styleProperty.check('transform', 'translate(1px, 1px)'); + const useTransform = OHIF.ui.styleProperty.check('transform', 'translate(1px, 1px)'); $clone.css({ visibility: 'visible', @@ -152,7 +149,7 @@ const thumbnailDragHandler = event => { const positionY = cursorY - diff.y - heightDiff; const translation = `translate(${positionX}px, ${positionY}px)`; - styleProperty.set($clone.get(0), 'transform', translation); + OHIF.ui.styleProperty.set($clone.get(0), 'transform', translation); } // Identify the element below the current cursor position @@ -172,12 +169,10 @@ const thumbnailDragHandler = event => { // If we're dragging over a non-empty viewport, fade it and change the cursor style $viewportsDraggedOver.find('canvas').not('.magnifyTool').addClass('faded'); document.body.style.cursor = 'copy'; - } - else if (elemBelow.classList.contains('imageViewerViewport') && elemBelow.classList.contains('empty')) { + } else if (elemBelow.classList.contains('imageViewerViewport') && elemBelow.classList.contains('empty')) { // If we're dragging over an empty viewport, just change the cursor style document.body.style.cursor = 'copy'; - } - else { + } else { // Otherwise, keep the cursor as no-drop style document.body.style.cursor = 'no-drop'; } @@ -224,17 +219,15 @@ const thumbnailDragEndHandler = (event, data, handlers) => { let element; const $viewportsDraggedOver = $(elemBelow).closest('.imageViewerViewport'); - + if ($viewportsDraggedOver.length) { // If we're dragging over a non-empty viewport, retrieve it element = $viewportsDraggedOver.get(0); - } - else if (elemBelow.classList.contains('imageViewerViewport') && + } else if (elemBelow.classList.contains('imageViewerViewport') && elemBelow.classList.contains('empty')) { // If we're dragging over an empty viewport, retrieve that instead element = elemBelow; - } - else { + } else { // Otherwise, stop here return false; } @@ -259,4 +252,4 @@ const thumbnailDragHandlers = { thumbnailDragHandler }; -export { thumbnailDragHandlers }; \ No newline at end of file +export { thumbnailDragHandlers };