diff --git a/LesionTracker/.meteor/packages b/LesionTracker/.meteor/packages index 2933bff58..16f8e2232 100644 --- a/LesionTracker/.meteor/packages +++ b/LesionTracker/.meteor/packages @@ -55,3 +55,4 @@ email peppelg:bootstrap-3-modal simple:reactive-method hangingprotocols +fastclick diff --git a/OHIFViewer/.meteor/packages b/OHIFViewer/.meteor/packages index c0d1eb642..51c8549f2 100644 --- a/OHIFViewer/.meteor/packages +++ b/OHIFViewer/.meteor/packages @@ -34,4 +34,5 @@ practicalmeteor:loglevel hangingprotocols reactive-dict gilbertwat:bootstrap3-daterangepicker -clinical:router \ No newline at end of file +clinical:router +fastclick diff --git a/Packages/cornerstone/client/jquery.hammer.js b/Packages/cornerstone/client/jquery.hammer.js new file mode 100644 index 000000000..a812c7609 --- /dev/null +++ b/Packages/cornerstone/client/jquery.hammer.js @@ -0,0 +1,33 @@ +(function(factory) { + if (typeof define === 'function' && define.amd) { + define(['jquery', 'hammerjs'], factory); + } else if (typeof exports === 'object') { + factory(require('jquery'), require('hammerjs')); + } else { + factory(jQuery, Hammer); + } +}(function($, Hammer) { + function hammerify(el, options) { + var $el = $(el); + if(!$el.data("hammer")) { + $el.data("hammer", new Hammer($el[0], options)); + } + } + + $.fn.hammer = function(options) { + return this.each(function() { + hammerify(this, options); + }); + }; + + // extend the emit method to also trigger jQuery events + Hammer.Manager.prototype.emit = (function(originalEmit) { + return function(type, data) { + originalEmit.call(this, type, data); + $(this.element).trigger({ + type: type, + gesture: data + }); + }; + })(Hammer.Manager.prototype.emit); +})); \ No newline at end of file diff --git a/Packages/cornerstone/client/measurementManager.js b/Packages/cornerstone/client/measurementManager.js deleted file mode 100644 index 961bcc9bf..000000000 --- a/Packages/cornerstone/client/measurementManager.js +++ /dev/null @@ -1,77 +0,0 @@ -(function($, cornerstoneTools) { - - 'use strict'; - - // This object manages a collection of measurements - function MeasurementManager() { - // Define some basic validator functions (everything is always valid) - this.singleMeasurementValidator = function() { - return {isValid: true}; - }; - - this.measurementSetValidator = function() { - return {isValid: true}; - }; - - var that = this; - that.measurements = []; - - // adds an element as both a source and a target - this.add = function(measurement, validateSingle, validateSet) { - var index = that.measurements.push(measurement); - - if (validateSingle === true) { - measurementValid = singleMeasurementValidator(measurement); - } - - if (validateSet === true) { - measurementSetValid = measurementSetValidator(measurement); - } - - // fire event - var eventDetail = { - index: index, - measurement: measurement, - measurementValid: measurementValid, - measurementSetValid: measurementSetValid - }; - - $(that).trigger('CornerstoneMeasurementAdded', eventDetail); - }; - - this.remove = function(index) { - var measurement = that.measurements[index]; - that.measurements.splice(index, 1); - // fire event - var eventDetail = { - index: index, - measurement: measurement - }; - $(that).trigger('CornerstoneMeasurementRemoved', eventDetail); - }; - - // Add set/get measurementValidator to run on each single measurement - // (e.g. length > 10 mm, location must be 30 mm from lymph node) - this.setSingleMeasurementValidator = function(validator) { - this.singleMeasurementValidator = validator; - }; - - this.getSingleMeasurementValidator = function(validator) { - return singleMeasurementValidator; - }; - - // Add set/get groupValidator to run on all of the measurements together - // (e.g. the number of measurments must be <= 2) - this.setMeasurementSetValidator = function(validator) { - this.measurementSetValidator = validator; - }; - - this.getMeasurementSetValidator = function(validator) { - return measurementSetValidator; - }; - } - - // module/private exports - cornerstoneTools.MeasurementManager = new MeasurementManager(); - -})($, cornerstoneTools); \ No newline at end of file diff --git a/Packages/cornerstone/client/measurementManagerExample.js b/Packages/cornerstone/client/measurementManagerExample.js deleted file mode 100644 index df52f4f1c..000000000 --- a/Packages/cornerstone/client/measurementManagerExample.js +++ /dev/null @@ -1,57 +0,0 @@ -// Example usage for something like RECIST -var tumourLengthMeasurementManager = cornerstoneTools.MeasurementManager; -function singleValidator(measurement) { - var result = { - isValid: true - }; - if (measurement.distance < 10) { - result.isValid = false; - result.details = 'Measurement distance must be less than 10 mm'; - } - return result; -} - -function setValidator(measurements) { - var result = { - isValid: true - }; - if (measurements.length > 2) { - result.isValid = false; - result.details = 'The number of measurements per image must be less than 2'; - } - return result; -} - -// Or a remote call -function remoteSetValidator(measurements) { - var deferred = $.Deferred(); - - var result = { - isValid: true, - promise: deferred.promise() - }; - - var xhr = new XMLHttpRequest(); - xhr.onreadystatechange = function() { - if (xhr.readyState === 4) { - if (xhr.status === 200) { - var response = JSON.parse(xhr.response); - if (response.isValid) { - deferred.resolve(xhr.responseText); - } else { - deferred.reject(xhr.responseText); - } - } else { - // The request didn't succeed - deferred.reject(xhr.responseText); - } - } - }; - xhr.open("POST", "/urlToValidateRECIST", true); - xhr.send(measurements); - - return result; -} - -tumourLengthMeasurementManager.setSingleMeasurementValidator(singleValidator); -tumourLengthMeasurementManager.setMeasurementSetValidator(setValidator); diff --git a/Packages/cornerstone/package.js b/Packages/cornerstone/package.js index 1c7961310..a63763939 100644 --- a/Packages/cornerstone/package.js +++ b/Packages/cornerstone/package.js @@ -28,11 +28,7 @@ Package.onUse(function(api) { api.addFiles('client/hammer.js', 'client', { bare: true }); - - api.addFiles('client/measurementManager.js', 'client', { - bare: true - }); - api.addFiles('client/measurementManagerExample.js', 'client', { + api.addFiles('client/jquery.hammer.js', 'client', { bare: true }); @@ -41,5 +37,4 @@ Package.onUse(function(api) { api.export('cornerstoneTools', 'client'); api.export('cornerstoneWADOImageLoader', 'client'); api.export('dicomParser', ['client', 'server']); -}); - +}); \ No newline at end of file diff --git a/Packages/worklist/client/components/worklistStudy/worklistStudy.js b/Packages/worklist/client/components/worklistStudy/worklistStudy.js index ef51972b3..717b1a5ee 100644 --- a/Packages/worklist/client/components/worklistStudy/worklistStudy.js +++ b/Packages/worklist/client/components/worklistStudy/worklistStudy.js @@ -3,7 +3,7 @@ WorklistSelectedStudies = new Meteor.Collection(null); WorklistSelectedStudies._debugName = 'WorklistSelectedStudies'; function handleShiftClick(studyRow, data) { - log.info('shiftKey'); + //log.info('shiftKey'); var studyInstanceUid = studyRow.attr('studyInstanceUid'); // Select all rows in between these two rows @@ -60,7 +60,7 @@ function handleShiftClick(studyRow, data) { } function handleCtrlClick(studyRow, data) { - log.info('ctrlKey'); + //log.info('ctrlKey'); var studyInstanceUid = studyRow.attr('studyInstanceUid'); if (studyRow.hasClass('active')) { @@ -82,6 +82,23 @@ function handleCtrlClick(studyRow, data) { } } +Template.worklistStudy.onRendered(function() { + var instance = this; + var elem = instance.$('tr.worklistStudy').get(0); + + // Enable HammerJS to allow touch support + var mc = new Hammer.Manager(elem); + var doubleTapRecognizer = new Hammer.Tap({ + event: 'doubletap', + taps: 2, + interval: 500, + threshold: 30, + posThreshold: 30 + }); + + mc.add(doubleTapRecognizer); +}); + Template.worklistStudy.events({ 'click tr.worklistStudy': function(e) { var studyRow = $(e.currentTarget); @@ -96,7 +113,7 @@ Template.worklistStudy.events({ handleCtrlClick(studyRow, data); } else { // Select a single study - log.info('Regular click'); + //log.info('Regular click'); // Clear all selected studies WorklistSelectedStudies.remove({}); @@ -104,7 +121,7 @@ Template.worklistStudy.events({ // Set the previous study to the currently clicked-on study Worklist.previouslySelected = studyRow; - log.info('Worklist PreviouslySelected set: ' + studyRow.index()); + //log.info('Worklist PreviouslySelected set: ' + studyRow.index()); // Set the current study as selected WorklistSelectedStudies.insert(data); @@ -123,8 +140,8 @@ Template.worklistStudy.events({ middleClickOnStudy(data); } }, - 'dblclick tr.worklistStudy': function(e) { - if (e.which !== 1) { + 'dblclick tr.worklistStudy, doubletap tr.worklistStudy': function(e) { + if (e.which !== undefined && e.which !== 1) { return; } @@ -135,7 +152,7 @@ Template.worklistStudy.events({ dblClickOnStudy(data); } }, - 'contextmenu tr.worklistStudy': function(e, template) { + 'contextmenu tr.worklistStudy, press tr.worklistStudy': function(e, template) { $(e.currentTarget).addClass('active'); if (openStudyContextMenu && typeof openStudyContextMenu === 'function') { diff --git a/Packages/worklist/package.js b/Packages/worklist/package.js index c84fee2f0..ada554254 100644 --- a/Packages/worklist/package.js +++ b/Packages/worklist/package.js @@ -20,6 +20,9 @@ Package.onUse(function (api) { api.use('dimseservice'); api.use('orthanc-remote'); + // TODO: Replace with NPM dependency + api.use('cornerstone'); // Only for HammerJS + // This sets the default logging level of the package using the // loglevel package. It can be overridden in the JavaScript // console for debugging purposes