Fix double-tap to open study (#20)
This commit is contained in:
parent
6f23c7163a
commit
c0fe9fff50
@ -55,3 +55,4 @@ email
|
|||||||
peppelg:bootstrap-3-modal
|
peppelg:bootstrap-3-modal
|
||||||
simple:reactive-method
|
simple:reactive-method
|
||||||
hangingprotocols
|
hangingprotocols
|
||||||
|
fastclick
|
||||||
|
|||||||
@ -34,4 +34,5 @@ practicalmeteor:loglevel
|
|||||||
hangingprotocols
|
hangingprotocols
|
||||||
reactive-dict
|
reactive-dict
|
||||||
gilbertwat:bootstrap3-daterangepicker
|
gilbertwat:bootstrap3-daterangepicker
|
||||||
clinical:router
|
clinical:router
|
||||||
|
fastclick
|
||||||
|
|||||||
33
Packages/cornerstone/client/jquery.hammer.js
Normal file
33
Packages/cornerstone/client/jquery.hammer.js
Normal file
@ -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);
|
||||||
|
}));
|
||||||
@ -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);
|
|
||||||
@ -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);
|
|
||||||
@ -28,11 +28,7 @@ Package.onUse(function(api) {
|
|||||||
api.addFiles('client/hammer.js', 'client', {
|
api.addFiles('client/hammer.js', 'client', {
|
||||||
bare: true
|
bare: true
|
||||||
});
|
});
|
||||||
|
api.addFiles('client/jquery.hammer.js', 'client', {
|
||||||
api.addFiles('client/measurementManager.js', 'client', {
|
|
||||||
bare: true
|
|
||||||
});
|
|
||||||
api.addFiles('client/measurementManagerExample.js', 'client', {
|
|
||||||
bare: true
|
bare: true
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -41,5 +37,4 @@ Package.onUse(function(api) {
|
|||||||
api.export('cornerstoneTools', 'client');
|
api.export('cornerstoneTools', 'client');
|
||||||
api.export('cornerstoneWADOImageLoader', 'client');
|
api.export('cornerstoneWADOImageLoader', 'client');
|
||||||
api.export('dicomParser', ['client', 'server']);
|
api.export('dicomParser', ['client', 'server']);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -3,7 +3,7 @@ WorklistSelectedStudies = new Meteor.Collection(null);
|
|||||||
WorklistSelectedStudies._debugName = 'WorklistSelectedStudies';
|
WorklistSelectedStudies._debugName = 'WorklistSelectedStudies';
|
||||||
|
|
||||||
function handleShiftClick(studyRow, data) {
|
function handleShiftClick(studyRow, data) {
|
||||||
log.info('shiftKey');
|
//log.info('shiftKey');
|
||||||
var studyInstanceUid = studyRow.attr('studyInstanceUid');
|
var studyInstanceUid = studyRow.attr('studyInstanceUid');
|
||||||
|
|
||||||
// Select all rows in between these two rows
|
// Select all rows in between these two rows
|
||||||
@ -60,7 +60,7 @@ function handleShiftClick(studyRow, data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleCtrlClick(studyRow, data) {
|
function handleCtrlClick(studyRow, data) {
|
||||||
log.info('ctrlKey');
|
//log.info('ctrlKey');
|
||||||
var studyInstanceUid = studyRow.attr('studyInstanceUid');
|
var studyInstanceUid = studyRow.attr('studyInstanceUid');
|
||||||
|
|
||||||
if (studyRow.hasClass('active')) {
|
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({
|
Template.worklistStudy.events({
|
||||||
'click tr.worklistStudy': function(e) {
|
'click tr.worklistStudy': function(e) {
|
||||||
var studyRow = $(e.currentTarget);
|
var studyRow = $(e.currentTarget);
|
||||||
@ -96,7 +113,7 @@ Template.worklistStudy.events({
|
|||||||
handleCtrlClick(studyRow, data);
|
handleCtrlClick(studyRow, data);
|
||||||
} else {
|
} else {
|
||||||
// Select a single study
|
// Select a single study
|
||||||
log.info('Regular click');
|
//log.info('Regular click');
|
||||||
|
|
||||||
// Clear all selected studies
|
// Clear all selected studies
|
||||||
WorklistSelectedStudies.remove({});
|
WorklistSelectedStudies.remove({});
|
||||||
@ -104,7 +121,7 @@ Template.worklistStudy.events({
|
|||||||
|
|
||||||
// Set the previous study to the currently clicked-on study
|
// Set the previous study to the currently clicked-on study
|
||||||
Worklist.previouslySelected = studyRow;
|
Worklist.previouslySelected = studyRow;
|
||||||
log.info('Worklist PreviouslySelected set: ' + studyRow.index());
|
//log.info('Worklist PreviouslySelected set: ' + studyRow.index());
|
||||||
|
|
||||||
// Set the current study as selected
|
// Set the current study as selected
|
||||||
WorklistSelectedStudies.insert(data);
|
WorklistSelectedStudies.insert(data);
|
||||||
@ -123,8 +140,8 @@ Template.worklistStudy.events({
|
|||||||
middleClickOnStudy(data);
|
middleClickOnStudy(data);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'dblclick tr.worklistStudy': function(e) {
|
'dblclick tr.worklistStudy, doubletap tr.worklistStudy': function(e) {
|
||||||
if (e.which !== 1) {
|
if (e.which !== undefined && e.which !== 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +152,7 @@ Template.worklistStudy.events({
|
|||||||
dblClickOnStudy(data);
|
dblClickOnStudy(data);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'contextmenu tr.worklistStudy': function(e, template) {
|
'contextmenu tr.worklistStudy, press tr.worklistStudy': function(e, template) {
|
||||||
$(e.currentTarget).addClass('active');
|
$(e.currentTarget).addClass('active');
|
||||||
|
|
||||||
if (openStudyContextMenu && typeof openStudyContextMenu === 'function') {
|
if (openStudyContextMenu && typeof openStudyContextMenu === 'function') {
|
||||||
|
|||||||
@ -20,6 +20,9 @@ Package.onUse(function (api) {
|
|||||||
api.use('dimseservice');
|
api.use('dimseservice');
|
||||||
api.use('orthanc-remote');
|
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
|
// This sets the default logging level of the package using the
|
||||||
// loglevel package. It can be overridden in the JavaScript
|
// loglevel package. It can be overridden in the JavaScript
|
||||||
// console for debugging purposes
|
// console for debugging purposes
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user