Updates to Lesion Tracker lesionTable and Packaging
This commit is contained in:
1 parent
4721400b34
commit
e2000480d3
36 files changed
+480
-176
No files matched your search
@@ -828,6 +828,14 @@ if (typeof cornerstoneTools === 'undefined') {
|
||||
data.active = !data.active;
|
||||
imageNeedsUpdate = true;
|
||||
}
|
||||
|
||||
//TODO: ayselafsar
|
||||
//Check hover event for lesion tool text
|
||||
if (mouseToolInterface.toolType === "lesion") {
|
||||
if ( mouseToolInterface.pointNearToolForText(eventData.element, data, coords) && !data.active) {
|
||||
data.active = !data.active;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle activation status changed, redraw the image
|
||||
@@ -892,6 +900,19 @@ if (typeof cornerstoneTools === 'undefined') {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: ayselafsar: Add check statement if mouse down location is on text callout. If so, call moveTextCallout function
|
||||
if(toolData !== undefined && mouseToolInterface.pointNearToolForText !== undefined) {
|
||||
for(i=0; i < toolData.data.length; i++) {
|
||||
data = toolData.data[i];
|
||||
if(mouseToolInterface.pointNearToolForText(eventData.element, data, coords)) {
|
||||
$(eventData.element).off('CornerstoneToolsMouseMove', mouseMoveCallback);
|
||||
cornerstoneTools.moveTextHandles(e, data, toolData, true);
|
||||
e.stopImmediatePropagation();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
///////// END DEACTIVE TOOL ///////
|
||||
@@ -6052,8 +6073,94 @@ if (typeof cornerstoneTools === 'undefined') {
|
||||
return true;
|
||||
}
|
||||
|
||||
//TODO:moveTextHandles-ayselafsar
|
||||
function moveTextHandles(e, data, toolData, deleteIfHandleOutsideImage, preventHandleOutsideImage)
|
||||
{
|
||||
var mouseEventData = e;
|
||||
var element = mouseEventData.element;
|
||||
|
||||
function mouseDragCallback(e, eventData)
|
||||
{
|
||||
for(var property in data.handles) {
|
||||
var handle = data.linkedTextCoords[property];
|
||||
handle.x += eventData.deltaPoints.image.x;
|
||||
handle.y += eventData.deltaPoints.image.y;
|
||||
if (preventHandleOutsideImage)
|
||||
{
|
||||
if (handle.x < 0)
|
||||
{
|
||||
handle.x = 0;
|
||||
}
|
||||
if (handle.x > eventData.image.width)
|
||||
{
|
||||
handle.x = eventData.image.width;
|
||||
}
|
||||
if (handle.y < 0)
|
||||
{
|
||||
handle.y = 0;
|
||||
}
|
||||
if (handle.y > eventData.image.height)
|
||||
{
|
||||
handle.y = eventData.image.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
cornerstone.updateImage(element);
|
||||
return false; // false = cases jquery to preventDefault() and stopPropagation() this event
|
||||
}
|
||||
|
||||
$(element).on("CornerstoneToolsMouseDrag", mouseDragCallback);
|
||||
|
||||
function mouseUpCallback(e, eventData) {
|
||||
data.moving = false;
|
||||
|
||||
$(element).off('CornerstoneToolsMouseDrag', mouseDragCallback);
|
||||
$(element).off('CornerstoneToolsMouseUp', mouseUpCallback);
|
||||
|
||||
// If any handle is outside the image, delete the tool data
|
||||
|
||||
if(deleteIfHandleOutsideImage === true) {
|
||||
var image = eventData.image;//.getEnabledElement(element).image;
|
||||
var handleOutsideImage = false;
|
||||
var rect = {
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: image.width,
|
||||
height: image.height
|
||||
};
|
||||
for(var property in data.handles) {
|
||||
var handle = data.handles[property];
|
||||
if(cornerstoneMath.point.insideRect(handle, rect) === false)
|
||||
{
|
||||
handleOutsideImage = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(handleOutsideImage)
|
||||
{
|
||||
// find this tool data
|
||||
var indexOfData = -1;
|
||||
for(var i = 0; i < toolData.data.length; i++) {
|
||||
if(toolData.data[i] === data)
|
||||
{
|
||||
indexOfData = i;
|
||||
}
|
||||
}
|
||||
if(indexOfData !== -1) {
|
||||
toolData.data.splice(indexOfData, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
cornerstone.updateImage(element);
|
||||
}
|
||||
$(element).on("CornerstoneToolsMouseUp",mouseUpCallback);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// module/private exports
|
||||
cornerstoneTools.moveAllHandles = moveAllHandles;
|
||||
cornerstoneTools.moveTextHandles = moveTextHandles;
|
||||
|
||||
})($, cornerstone, cornerstoneMath, cornerstoneTools);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ function setValidator(measurements) {
|
||||
|
||||
// Or a remote call
|
||||
function remoteSetValidator(measurements) {
|
||||
var deferred = $.Deferred;
|
||||
var deferred = $.Deferred();
|
||||
|
||||
var result = {
|
||||
isValid: true,
|
||||
@@ -33,8 +33,8 @@ function remoteSetValidator(measurements) {
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4) {
|
||||
if (xhr.status == 200) {
|
||||
if (xhr.readyState === 4) {
|
||||
if (xhr.status === 200) {
|
||||
var response = JSON.parse(xhr.response);
|
||||
if (response.isValid) {
|
||||
deferred.resolve(xhr.responseText);
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
var lineIndex = 0; //This holds drawn line index
|
||||
var cornerstoneTools = (function ($, cornerstone, cornerstoneMath, cornerstoneTools) {
|
||||
|
||||
"use strict";
|
||||
|
||||
if(cornerstoneTools === undefined) {
|
||||
cornerstoneTools = {};
|
||||
}
|
||||
|
||||
var toolType = "lesion";
|
||||
|
||||
///////// BEGIN ACTIVE TOOL ///////
|
||||
function createNewMeasurement(mouseEventData)
|
||||
{
|
||||
var element = mouseEventData.element;
|
||||
var lesionCounter = "";
|
||||
|
||||
//setting name of lesion
|
||||
$(element).on("LesionNameSet", function(e,counter){
|
||||
lesionCounter = counter;
|
||||
});
|
||||
|
||||
//Listens LesionToolModified event and calls measurementModified function when lesion measurement is changed or updated.
|
||||
$(element).on("LesionToolModified", measurementModified);
|
||||
$(element).trigger("LesionMeasurementCreated");
|
||||
|
||||
// create the measurement data for this tool with the end handle activated
|
||||
var measurementData = {
|
||||
visible : true,
|
||||
active : true,
|
||||
handles : {
|
||||
start : {
|
||||
x : mouseEventData.currentPoints.image.x,
|
||||
y : mouseEventData.currentPoints.image.y,
|
||||
highlight: true,
|
||||
active: false
|
||||
},
|
||||
end: {
|
||||
x : mouseEventData.currentPoints.image.x,
|
||||
y : mouseEventData.currentPoints.image.y,
|
||||
highlight: true,
|
||||
active: true
|
||||
}
|
||||
},
|
||||
index: lineIndex,
|
||||
measurementText: "",
|
||||
linkedTextCoords: {
|
||||
start : {
|
||||
x : mouseEventData.currentPoints.image.x,
|
||||
y : mouseEventData.currentPoints.image.y,
|
||||
highlight: true,
|
||||
active: false
|
||||
},
|
||||
end: {
|
||||
x : mouseEventData.currentPoints.image.x,
|
||||
y : mouseEventData.currentPoints.image.y,
|
||||
highlight: true,
|
||||
active: true
|
||||
},
|
||||
init: false
|
||||
},
|
||||
lesionName: "Target "+lesionCounter,
|
||||
isDeleted: false,
|
||||
lineNumber:"" //Indicates line number on image
|
||||
};
|
||||
lineIndex++;
|
||||
return measurementData;
|
||||
}
|
||||
///////// END ACTIVE TOOL ///////
|
||||
|
||||
function pointNearTool(element, data, coords)
|
||||
{
|
||||
var lineSegment = {
|
||||
start: cornerstone.pixelToCanvas(element, data.handles.start), end: cornerstone.pixelToCanvas(element, data.handles.end)
|
||||
};
|
||||
var distanceToPoint = cornerstoneMath.lineSegment.distanceToPoint(lineSegment, coords);
|
||||
return (distanceToPoint < 25);
|
||||
}
|
||||
|
||||
function pointNearToolForText(element, data, coords) {
|
||||
var lineSegment = {
|
||||
start: cornerstone.pixelToCanvas(element, data.linkedTextCoords.start), end: cornerstone.pixelToCanvas(element, data.linkedTextCoords.end)
|
||||
};
|
||||
|
||||
var distanceToPoint = cornerstoneMath.lineSegment.distanceToPoint(lineSegment, coords);
|
||||
return (distanceToPoint < 30);
|
||||
|
||||
}
|
||||
|
||||
|
||||
///////// BEGIN IMAGE RENDERING ///////
|
||||
function onImageRendered(e, eventData) {
|
||||
|
||||
// if we have no toolData for this element, return immediately as there is nothing to do
|
||||
var toolData = cornerstoneTools.getToolState(e.currentTarget, toolType);
|
||||
if (toolData === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we have tool data for this element - iterate over each one and draw it
|
||||
var context = eventData.canvasContext.canvas.getContext('2d');
|
||||
context.setTransform(1, 0, 0, 1, 0, 0);
|
||||
|
||||
var color;
|
||||
var lineWidth = cornerstoneTools.toolStyle.getToolWidth();
|
||||
var font = cornerstoneTools.textStyle.getFont();
|
||||
var config = cornerstoneTools.length.getConfiguration();
|
||||
|
||||
for (var i = 0; i < toolData.data.length; i++) {
|
||||
context.save();
|
||||
// configurable shadow
|
||||
if (config && config.shadow) {
|
||||
context.shadowColor = '#000000';
|
||||
context.shadowOffsetX = +1;
|
||||
context.shadowOffsetY = +1;
|
||||
}
|
||||
|
||||
var data = toolData.data[i];
|
||||
if (data.active) {
|
||||
color = cornerstoneTools.toolColors.getActiveColor();
|
||||
} else {
|
||||
color = cornerstoneTools.toolColors.getToolColor();
|
||||
}
|
||||
|
||||
// draw the line
|
||||
var handleStartCanvas = cornerstone.pixelToCanvas(eventData.element, data.handles.start);
|
||||
var handleEndCanvas = cornerstone.pixelToCanvas(eventData.element, data.handles.end);
|
||||
|
||||
context.beginPath();
|
||||
context.strokeStyle = color;
|
||||
context.lineWidth = lineWidth;
|
||||
context.moveTo(handleStartCanvas.x, handleStartCanvas.y);
|
||||
context.lineTo(handleEndCanvas.x, handleEndCanvas.y);
|
||||
context.stroke();
|
||||
|
||||
// draw the handles
|
||||
cornerstoneTools.drawHandles(context, eventData, data.handles, color);
|
||||
|
||||
//Set coordinates of text
|
||||
var linkedTextStartCanvas = cornerstone.pixelToCanvas(eventData.element, data.linkedTextCoords.start);
|
||||
var linkedTextEndCanvas = cornerstone.pixelToCanvas(eventData.element, data.linkedTextCoords.end);
|
||||
if(!data.linkedTextCoords.init){
|
||||
data.linkedTextCoords.start.x = data.handles.start.x + 50;
|
||||
data.linkedTextCoords.start.y = data.handles.start.y + 40;
|
||||
linkedTextStartCanvas = cornerstone.pixelToCanvas(eventData.element, data.linkedTextCoords.start);
|
||||
|
||||
//Set end point of linkedTextCoords
|
||||
data.linkedTextCoords.end.x = data.linkedTextCoords.start.x + 50;
|
||||
data.linkedTextCoords.end.y = data.linkedTextCoords.start.y + 30;
|
||||
linkedTextEndCanvas = cornerstone.pixelToCanvas(eventData.element, data.linkedTextCoords.end);
|
||||
|
||||
//initialized coordinates of text
|
||||
data.linkedTextCoords.init = true;
|
||||
}
|
||||
|
||||
//Draw linked line as dashed
|
||||
context.setLineDash([2,3]);
|
||||
context.beginPath();
|
||||
context.strokeStyle = color;
|
||||
context.lineWidth = 1 / eventData.viewport.scale;
|
||||
var mid = {
|
||||
x:(handleStartCanvas.x + handleEndCanvas.x) / 2, y:(handleStartCanvas.y + handleEndCanvas.y) / 2
|
||||
};
|
||||
|
||||
context.moveTo(mid.x, mid.y);
|
||||
context.lineTo(linkedTextStartCanvas.x + 20, linkedTextStartCanvas.y + 20);
|
||||
context.stroke();
|
||||
|
||||
// Draw the text
|
||||
context.fillStyle = color;
|
||||
context.font = font;
|
||||
var dx = (data.handles.start.x - data.handles.end.x) * (eventData.image.columnPixelSpacing || 1);
|
||||
var dy = (data.handles.start.y - data.handles.end.y) * (eventData.image.rowPixelSpacing || 1);
|
||||
var length = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
var suffix = ' mm';
|
||||
if (!eventData.image.rowPixelSpacing || !eventData.image.columnPixelSpacing) {
|
||||
suffix = ' pixels';
|
||||
}
|
||||
|
||||
var text = '' + length.toFixed(2) + suffix;
|
||||
var textCoords = {
|
||||
x: linkedTextStartCanvas.x, y: linkedTextStartCanvas.y
|
||||
};
|
||||
|
||||
cornerstoneTools.drawTextBox(context, data.lesionName, textCoords.x, textCoords.y, color);
|
||||
cornerstoneTools.drawTextBox(context, text, textCoords.x, textCoords.y + 20, color);
|
||||
|
||||
//Set measurement text to show lesion table
|
||||
data.measurementText = length.toFixed(2);
|
||||
$(eventData.enabledElement.element).trigger("LesionTextChanged",data);
|
||||
|
||||
context.restore();
|
||||
}
|
||||
|
||||
}
|
||||
///////// END IMAGE RENDERING ///////
|
||||
|
||||
//This function is called from cornerstone-viewport.html and updates lesion measurement and makes the lesion active
|
||||
function measurementModified(e, eventObject){
|
||||
var start = new Date();
|
||||
|
||||
var enabledElement = eventObject.enabledElement;
|
||||
var lineIndex = eventObject.lineIndex;
|
||||
var type = eventObject.type;
|
||||
|
||||
// if we have no toolData for this element, return immediately as there is nothing to do
|
||||
var toolData = cornerstoneTools.getToolState(e.currentTarget, toolType);
|
||||
if (toolData === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
//If type is delete, remove measurement
|
||||
if(type === "delete") {
|
||||
var deletedDataIndex = -1;
|
||||
|
||||
for (var i = 0; i < toolData.data.length; i++) {
|
||||
var data = toolData.data[i];
|
||||
|
||||
//When click a row of table measurements, measurement will be active and color will be green
|
||||
if (data.index === eventObject.lineIndex && eventObject.type !== "active") {
|
||||
data.visible = false;
|
||||
deletedDataIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (deletedDataIndex >= 0 && deletedDataIndex < toolData.data.length) {
|
||||
toolData.data.splice(deletedDataIndex, 1);
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < toolData.data.length; i++) {
|
||||
var data = toolData.data[i];
|
||||
|
||||
//When click a row of table measurements, measurement will be active and color will be green
|
||||
if (data.index === eventObject.lineIndex && eventObject.type === "active") {
|
||||
data.active = true;
|
||||
} else{
|
||||
data.active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enabledElement.image.render(enabledElement, true);
|
||||
|
||||
var context = enabledElement.canvas.getContext('2d');
|
||||
|
||||
var end = new Date();
|
||||
var diff = end - start;
|
||||
//console.log(diff + ' ms');
|
||||
|
||||
var eventData = {
|
||||
viewport : enabledElement.viewport,
|
||||
element : enabledElement.element,
|
||||
image : enabledElement.image,
|
||||
enabledElement : enabledElement,
|
||||
canvasContext: context,
|
||||
measurementText: "",
|
||||
renderTimeInMs : diff,
|
||||
lineIndex : lineIndex,
|
||||
type : type //Holds image will be deleted or active
|
||||
};
|
||||
|
||||
enabledElement.invalid = false;
|
||||
|
||||
onImageRendered(e, eventData);
|
||||
}
|
||||
|
||||
// module exports
|
||||
cornerstoneTools.lesion = cornerstoneTools.mouseButtonTool({
|
||||
createNewMeasurement : createNewMeasurement,
|
||||
onImageRendered: onImageRendered,
|
||||
pointNearTool : pointNearTool,
|
||||
pointNearToolForText: pointNearToolForText,
|
||||
toolType : toolType
|
||||
});
|
||||
cornerstoneTools.lesionTouch = cornerstoneTools.touchTool({
|
||||
createNewMeasurement: createNewMeasurement,
|
||||
onImageRendered: onImageRendered,
|
||||
pointNearTool: pointNearTool,
|
||||
pointNearToolForText: pointNearToolForText,
|
||||
toolType: toolType
|
||||
});
|
||||
return cornerstoneTools;
|
||||
}($, cornerstone, cornerstoneMath, cornerstoneTools));
|
||||
@@ -0,0 +1,3 @@
|
||||
<template name="lesionDialog">
|
||||
{{> lesionLocationDialog}}
|
||||
</template>
|
||||
@@ -0,0 +1,31 @@
|
||||
Template.lesionDialog.onRendered(function () {
|
||||
// Listen lesionMeaurementCreated Event and when this event is triggered, show lesionLocationDialog Box
|
||||
$(document).on("lesionMeasurementCreated",function(e,eventCaller,data){
|
||||
var element = data.element;
|
||||
var tabId = data.tabId;
|
||||
var viewports = $("#content"+tabId).find(".imageViewerViewport");
|
||||
var viewportIndex = $(viewports).index($(element));
|
||||
data.viewportIndex = viewportIndex;
|
||||
data.totalViewportCount = viewports.length;
|
||||
|
||||
//Set Lesion Table Data to insert into lesion table
|
||||
setLesionTableData(data);
|
||||
|
||||
// Check popup will shown or not
|
||||
var returnVal = lesionNumberIsAdded(data);
|
||||
if(!returnVal.isFound) {
|
||||
if( !Session.get("lesionLocationSelected") ) {
|
||||
$("#modal-dialog-container").css({
|
||||
"top": eventCaller.pageY,
|
||||
"left": eventCaller.pageX
|
||||
});
|
||||
|
||||
$("#lesionDialog").modal("show");
|
||||
}
|
||||
} else {
|
||||
// If lesionNumber is added before:
|
||||
data.rowIndex = returnVal.rowIndex;
|
||||
$(document).trigger("addLesionToExistedRow",data);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
<template name="lesionLocationDialog">
|
||||
<div class="modal fade" id="lesionDialog" style=" background-color: transparent;">
|
||||
<div id="modal-dialog-container" class="modal-dialog modal-sm" style="position: absolute; border: none; ">
|
||||
<div class="modal-content" style="padding: 10px;">
|
||||
<div class="dialogHeader">
|
||||
<div style="float:left;"><h4>Select Lesion Location</h4></div>
|
||||
<div style="float:right;"><button class="btn" id="btnCloseLesionPopup" style="outline: 0; border: none; background-color: transparent;"><i class="fa fa-close"></i></button></div>
|
||||
</div>
|
||||
<div class="dialogContent" style="margin-bottom: 20px;">
|
||||
<div class="lesionLocation">
|
||||
<label>Lesion Location</label>
|
||||
<select id="selectLesionLocation" style="margin-top:5px;">
|
||||
<option value="-1"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,49 @@
|
||||
//fill selectLesionLocation element
|
||||
var lesionLocationsArray = [
|
||||
{location:"Brain Brainstem",hasDescription:false, description:""},
|
||||
{location:"Brain Cerebellum Left",hasDescription:false, description:""},
|
||||
{location:"Brain Cerebrum Left",hasDescription:false, description:""},
|
||||
{location:"Brain Cerebrum Right",hasDescription:false, description:""},
|
||||
{location:"Brain Multiple Sites",hasDescription:false, description:""}
|
||||
];
|
||||
|
||||
Template.lesionLocationDialog.onRendered(function () {
|
||||
|
||||
function fillSelectLesionLocation () {
|
||||
var el = $("#selectLesionLocation");
|
||||
el.find('option:not(:first)').remove();
|
||||
$.each(lesionLocationsArray, function(key, value) {
|
||||
el.append("<option value='" + key+ "'>" + value.location + "</option>");
|
||||
});
|
||||
}
|
||||
|
||||
// Fill dropdown
|
||||
fillSelectLesionLocation();
|
||||
});
|
||||
|
||||
Template.lesionLocationDialog.events({
|
||||
'click button#btnCloseLesionPopup': function (e) {
|
||||
$("#lesionDialog").modal("hide");
|
||||
},
|
||||
|
||||
'change select#selectLesionLocation': function (e) {
|
||||
var el = $(e.target);
|
||||
var selectedLocationIndex = el.val()
|
||||
if(selectedLocationIndex !== "-1"){
|
||||
|
||||
var locationObj = lesionLocationsArray[selectedLocationIndex];
|
||||
|
||||
// Trigger location selected event
|
||||
$(document).trigger("lesionLocationSelected",locationObj);
|
||||
|
||||
// Set activeModule parameters in index.html
|
||||
$("#lesionDialog").modal("hide");
|
||||
|
||||
// Select first option
|
||||
el.val($("#selectLesionLocation option:first").val());
|
||||
|
||||
// Set lesion location selected session to prevent open
|
||||
Session.set("lesionLocationSelected", true);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
<template name="lesionTable">
|
||||
<div id="lesionTableContainer">
|
||||
<table class="table table-bordered lesionTable" id="tblLesion">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="thNumber">Lesion #</th>
|
||||
<th id="thTarget">Target</th>
|
||||
<th id="thLocation">Location</th>
|
||||
<!--Each time point name as a column-->
|
||||
{{ #each timepointNames }}
|
||||
{{ >lesionTableTimepointHeader }}
|
||||
{{ /each }}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ #each measurement }}
|
||||
{{ >lesionTableRow }}
|
||||
{{ /each }}
|
||||
<!--Each measurement as row-->
|
||||
<!--Each time point as a column-->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,187 @@
|
||||
measurements = new Meteor.Collection(null);
|
||||
|
||||
var test = {
|
||||
lesionNumber: 1,
|
||||
isTarget: true,
|
||||
location: 'Brain',
|
||||
timepoints: {
|
||||
"now": {
|
||||
imageId: "blah",
|
||||
timepointUid: "timepointX",
|
||||
date: 2010,
|
||||
isDirty: true,
|
||||
longestDiameter: 5
|
||||
},
|
||||
"earlier": {
|
||||
imageId: "blah2",
|
||||
timepointUid: "timepointy",
|
||||
date: 2010,
|
||||
isDirty: true,
|
||||
longestDiameter: 8
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
measurements.insert(test);
|
||||
|
||||
Template.lesionTable.helpers({
|
||||
'measurement': function() {
|
||||
return measurements.find();
|
||||
},
|
||||
'timepointNames': function() {
|
||||
return [
|
||||
{name: 'now'},
|
||||
{name: 'earlier'}
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
/*var lesionTableData;
|
||||
setLesionTableData = function (data) {
|
||||
lesionTableData = data;
|
||||
};
|
||||
|
||||
getLesionTableData = function () {
|
||||
return lesionTableData;
|
||||
};
|
||||
|
||||
lesionNumberIsAdded = function(data) {
|
||||
var tabId = data.tabId;
|
||||
var returnValue = {isFound: false, rowIndex : -1};
|
||||
$('#content'+tabId+' table tbody tr td.lesionNumber').each( function(){
|
||||
console.log($(this).text());
|
||||
var lesionNumber = parseInt($(this).text());
|
||||
|
||||
if(lesionNumber == data.lesionNumber) {
|
||||
var $tr = $(this).closest('tr');
|
||||
var rowIndex = $tr.index();
|
||||
returnValue.rowIndex = rowIndex;
|
||||
returnValue.isFound = true;
|
||||
}
|
||||
});
|
||||
|
||||
return returnValue;
|
||||
};
|
||||
|
||||
returnTblStr = function (obj) {
|
||||
// Get count of lds
|
||||
var tabId = obj.tabId;
|
||||
var lds = $("#content"+tabId).find(".lesionTable th.ld");
|
||||
|
||||
var rowStr = '<tr style="background-color: #b3b3b3;">' +
|
||||
'<td style="text-align:center;"><button type="button" class="btnRemove fa fa-times fa-lg" title="Remove"></button></td>' +
|
||||
'<td style="text-align:center;" class="lesionNumber">'+obj.lesionNumber+'</td>' +
|
||||
'<td style="text-align:center;">Y</td>';
|
||||
|
||||
// Add measurement to right column
|
||||
if(obj.totalViewportCount) {
|
||||
for(var i=0; i< lds.length; i++) {
|
||||
if(i === obj.viewportIndex) {
|
||||
rowStr += '<td>'+obj.lesionLocationObj.location+'</td><td id='+obj.lineIndex+' class="lesion" style="text-align: left;">'+obj.lesions+'</td>';
|
||||
|
||||
}else{
|
||||
rowStr += '<td>'+obj.lesionLocationObj.location+'</td><td class="lesion" style="text-align: left;"></td>';
|
||||
}
|
||||
}
|
||||
}
|
||||
rowStr += '</tr>';
|
||||
|
||||
return rowStr;
|
||||
};
|
||||
|
||||
//Link lesionLocationSelected event
|
||||
$(document).on("lesionLocationSelected",function(event,data ){
|
||||
var lesionData = getLesionTableData();
|
||||
lesionData.lesionLocationObj = data;
|
||||
var tabId = lesionData.tabId;
|
||||
//var el_index = lesionData.viewportIndex;
|
||||
var tableEl = $("#content"+tabId).find(".lesionTable");
|
||||
var tblStr = returnTblStr(lesionData);
|
||||
$(tableEl).append(tblStr);
|
||||
|
||||
});
|
||||
|
||||
//Link addLesionToExistedRow event
|
||||
$(document).on("addLesionToExistedRow",function(event,data ){
|
||||
// Get count of lds
|
||||
var tabId = data.tabId;
|
||||
var lds = $("#content"+tabId).find(".lesionTable th.ld");
|
||||
// Add measurement to right column
|
||||
for(var i=0; i< lds.length; i++) {
|
||||
if(i === data.viewportIndex) {
|
||||
var rowIndex = data.rowIndex + 1;
|
||||
var row = $("#content"+tabId).find(".lesionTable tr").eq(rowIndex);
|
||||
var cell = $(row).find("td.lesion").eq(data.viewportIndex);
|
||||
$(cell).attr("id", data.lineIndex);
|
||||
$(cell).html(data.lesions);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on("lesionTextChanged", function(event, data){
|
||||
var cellId = data.index;
|
||||
$("td#"+cellId).html(data.measurementText);
|
||||
});
|
||||
|
||||
|
||||
Template.lesionTable.onRendered( function () {
|
||||
|
||||
// TODO: Set lesion table as hiding-panel
|
||||
console.log(this);
|
||||
var template = this;
|
||||
var tabId = this.data.tabId;
|
||||
var viewports = $("#content"+tabId).find(".imageViewerViewport");
|
||||
var lesionTable = $("#content"+tabId).find(".lesionTable");
|
||||
|
||||
var viewportCount = viewports.length;
|
||||
|
||||
var lesionTableWidth = $(lesionTable).width();
|
||||
var viewportWidth = viewports.width();
|
||||
var ldColumnRatio = viewportWidth / lesionTableWidth * 100;
|
||||
|
||||
// Add LD column as viewportCount
|
||||
// Set lesion table columns width
|
||||
|
||||
if(viewportCount > 0) {
|
||||
if(viewportCount == 1) {
|
||||
$('#content'+tabId+' thead tr').append( $('<th />', {text : 'Location', width: ldColumnRatio/2+'%', class:'thLocation'}) )
|
||||
$('#content'+tabId+' thead tr').append( $('<th />', {text : 'LD', width: ldColumnRatio/2+'%', class:'ld'}) )
|
||||
|
||||
} else if(viewportCount == 2) {
|
||||
|
||||
for(var i = 0; i< viewportCount; i++) {
|
||||
$('#content'+tabId+' thead tr').append( $('<th />', {text : 'Location'+i, width: ldColumnRatio/2+'%', class:'thLocation'}) )
|
||||
$('#content'+tabId+' thead tr').append( $('<th />', {text : 'LD'+i, width: ldColumnRatio/2+'%', class:'ld'}) )
|
||||
}
|
||||
|
||||
} else if(viewportCount > 2) {
|
||||
// TODO: Set when viewport count is bigger than 2
|
||||
}
|
||||
}
|
||||
// TODO: When layout is changed, add and calculate new columns for measurement
|
||||
});
|
||||
|
||||
Template.lesionTable.events({
|
||||
'click button.btnRemove': function (e) {
|
||||
var el = $(e.target);
|
||||
},
|
||||
'click table tbody tr': function(e) {
|
||||
console.log(this);
|
||||
var row = e.currentTarget;
|
||||
var lesionCells = $(row).find("td.lesion");
|
||||
for(var i = 0; i< lesionCells.length; i++) {
|
||||
var cell = lesionCells[i];
|
||||
var idAttr = $(cell).attr("id");
|
||||
if(idAttr != undefined) {
|
||||
// TODO: Create eventObject and trigger LesionToolModified event
|
||||
var viewports = $(".imageViewerViewport");
|
||||
var eventObject = {
|
||||
enabledElement: cornerstone.getEnabledElement(viewports[0]),
|
||||
lineIndex: parseInt(idAttr),
|
||||
type: "active"
|
||||
};
|
||||
$(viewports[0]).trigger("LesionToolModified", eventObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
});*/
|
||||
@@ -0,0 +1,44 @@
|
||||
#lesionTableContainer
|
||||
width: 100%
|
||||
height: 25%
|
||||
|
||||
table.lesionTable
|
||||
thead
|
||||
th
|
||||
background-color: #424242
|
||||
font-style: italic
|
||||
color:white
|
||||
text-align: center
|
||||
height: 15px
|
||||
width: 20px
|
||||
|
||||
table.lesionTable > thead > tr > th {
|
||||
padding: 4px;
|
||||
margin: 0;
|
||||
height: 25px;
|
||||
line-height: 15px;
|
||||
}
|
||||
|
||||
table.lesionTable > tbody > tr > td {
|
||||
padding: 4px;
|
||||
margin: 0;
|
||||
height: 25px;
|
||||
line-height: 15px;
|
||||
}
|
||||
|
||||
table.lesionTable tbody tr:hover{
|
||||
background-color: #d1d1d1;
|
||||
}
|
||||
|
||||
table.lesionTable tbody tr{
|
||||
background-color: #b3b3b3;
|
||||
color: #424242;
|
||||
line-height: 14px;
|
||||
}
|
||||
|
||||
|
||||
.btnRemove{
|
||||
border: none;
|
||||
outline:none;
|
||||
background-color: transparent;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<template name="lesionTableRow">
|
||||
<tr>
|
||||
<th class='lesionNumber'>{{lesionNumber}}</th>
|
||||
<th class='target'>{{isTarget}}</th>
|
||||
<th class='location'>{{location}}</th>
|
||||
<!--Each time point as a column-->
|
||||
{{ #each timepoints}}
|
||||
{{ >lesionTableTimepointCell}}
|
||||
{{ /each }}
|
||||
</tr>
|
||||
</template>
|
||||
@@ -0,0 +1,10 @@
|
||||
Template.lesionTableRow.helpers({
|
||||
'timepoints': function() {
|
||||
var array = [];
|
||||
var timepoints = this.timepoints;
|
||||
Object.keys(timepoints).forEach(function(key) {
|
||||
array.push(timepoints[key]);
|
||||
});
|
||||
return array;
|
||||
},
|
||||
});
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
<template name="lesionTableTimepointCell">
|
||||
<td>{{longestDiameter}}</td>
|
||||
</template>
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
<template name="lesionTableTimepointHeader">
|
||||
<th>{{name}}</th>
|
||||
</template>
|
||||
@@ -0,0 +1,35 @@
|
||||
Package.describe({
|
||||
name: "lesiontracker",
|
||||
summary: "OHIF Lesion Tracker Tools",
|
||||
version: '0.0.1'
|
||||
});
|
||||
|
||||
Package.onUse(function (api) {
|
||||
api.versionsFrom('1.2.0.2');
|
||||
|
||||
api.use('standard-app-packages');
|
||||
api.use('jquery');
|
||||
api.use('stylus');
|
||||
|
||||
// Our custom package
|
||||
api.use('cornerstone');
|
||||
|
||||
api.addFiles('compatibility/lesionTool.js', 'client', {bare: true});
|
||||
|
||||
api.addFiles('components/lesionDialog/lesionDialog.html', 'client');
|
||||
api.addFiles('components/lesionDialog/lesionDialog.js', 'client');
|
||||
|
||||
api.addFiles('components/lesionLocationDialog/lesionLocationDialog.html', 'client');
|
||||
api.addFiles('components/lesionLocationDialog/lesionLocationDialog.js', 'client');
|
||||
|
||||
api.addFiles('components/lesionTable/lesionTable.html', 'client');
|
||||
api.addFiles('components/lesionTable/lesionTable.styl', 'client');
|
||||
api.addFiles('components/lesionTable/lesionTable.js', 'client');
|
||||
|
||||
api.addFiles('components/lesionTableRow/lesionTableRow.html', 'client');
|
||||
api.addFiles('components/lesionTableRow/lesionTableRow.js', 'client');
|
||||
|
||||
api.addFiles('components/lesionTableTimepointCell/lesionTableTimepointCell.html', 'client');
|
||||
|
||||
api.addFiles('components/lesionTableTimepointHeader/lesionTableTimepointHeader.html', 'client');
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
<template name="hidingPanel">
|
||||
<div class="hidingPanel">
|
||||
{{> studyBrowser}}
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,6 @@
|
||||
.hidingPanel
|
||||
width: 120px
|
||||
height: 100%
|
||||
padding-top: 35px
|
||||
position: relative
|
||||
float: left
|
||||
@@ -0,0 +1,39 @@
|
||||
(function($) {
|
||||
|
||||
|
||||
//Collapse the container
|
||||
function collapseContainer ( container ) {
|
||||
container.toggleClass("collapseHorizontal");
|
||||
var btnCollapse = container.find(".btnCollapse");
|
||||
}
|
||||
|
||||
//function add collapse button
|
||||
function addButtonCollapse ( container ) {
|
||||
var btnCollapse = document.createElement("button");
|
||||
btnCollapse.innerHTML = ">";
|
||||
$(btnCollapse).addClass ("btnCollapse");
|
||||
|
||||
btnCollapse.onclick = function() { // Note this is a function
|
||||
collapseContainer(container);
|
||||
};
|
||||
container.append(btnCollapse);
|
||||
}
|
||||
|
||||
$.fn.dockingContainer = function(options) {
|
||||
var self = this;
|
||||
var opts = $.extend( {}, $.fn.dockingContainer.defaults, options);
|
||||
|
||||
//Set container class
|
||||
this.addClass("dockingContainer");
|
||||
|
||||
//Add btnCollapse
|
||||
addButtonCollapse(this);
|
||||
return this;
|
||||
};
|
||||
|
||||
//Defaults
|
||||
$.fn.dockingContainer.defaults = {
|
||||
background: "black"
|
||||
};
|
||||
|
||||
}(jQuery));
|
||||
@@ -22,6 +22,9 @@ Package.onUse(function (api) {
|
||||
api.addFiles('components/basic/login/login.html', 'client');
|
||||
api.addFiles('components/basic/notFound/notFound.html', 'client');
|
||||
|
||||
api.addFiles('components/basic/hidingPanel/hidingPanel.html', 'client');
|
||||
api.addFiles('components/basic/hidingPanel/hidingPanel.styl', 'client');
|
||||
|
||||
// Study Browser components
|
||||
api.addFiles('components/studyBrowser/studyBrowser/studyBrowser.html', 'client');
|
||||
api.addFiles('components/studyBrowser/studyBrowser/studyBrowser.js', 'client');
|
||||
|
||||
Reference in new issue
Block a user