517 lines
14 KiB
JavaScript
517 lines
14 KiB
JavaScript
import * as dicomViewer from "./dicomViewer.js"
|
|
|
|
window.marked_answers = {
|
|
"correct": [],
|
|
"half-correct": [],
|
|
"incorrect": [],
|
|
}
|
|
|
|
window.control_pressed = false;
|
|
|
|
|
|
$(document).ready(function () {
|
|
$("table thead th input").click((e) => {
|
|
let status = e.currentTarget.checked;
|
|
$("table tbody input").prop("checked", status);
|
|
})
|
|
|
|
$(".answer-list li").each(function (index, element) {
|
|
$(element).append($("<span class='google-link' title='search for answer with google'><a href='https://www.google.com/search?q=" + $(element).text() + "' target='_blank'>G</a></span>"));
|
|
});
|
|
|
|
$(".answer-list span.answer").each(function (index, element) {
|
|
console.log(element);
|
|
|
|
$(element).click(function (e) {
|
|
|
|
var classes = ['answer correct', 'answer half-correct', 'answer incorrect'];
|
|
$(element).each(function () {
|
|
this.className = classes[($.inArray(this.className, classes) + 1) % classes.length];
|
|
});
|
|
|
|
prepAnswerData();
|
|
|
|
|
|
|
|
});
|
|
});
|
|
prepAnswerData();
|
|
|
|
if ($(".post-form").length > 0) {
|
|
$(".post-form").get(0).addEventListener("submit", function (e) {
|
|
if ($(".not-marked").length > 0 && e.submitter.name != "skip") {
|
|
e.preventDefault(); // before the code
|
|
alert("Ensure all answers are marked first");
|
|
}
|
|
|
|
});
|
|
}
|
|
|
|
let dicom_images = document.getElementsByClassName("dicom-image");
|
|
if (dicom_images.length) {
|
|
|
|
for (let element of dicom_images) {
|
|
setUpDicom(element)
|
|
}
|
|
|
|
}
|
|
|
|
|
|
loadDicomViewer();
|
|
|
|
if ($("#question-mark-list").length) {
|
|
$(".show-all-button").click(() => {
|
|
$("#question-mark-list li").show();
|
|
});
|
|
$(".show-unmarked-button").click(() => {
|
|
$("#question-mark-list li").each((n, el) => {
|
|
// Can't seem to get django to output this as a int....
|
|
if (parseInt(el.dataset.markcount) < 1) {
|
|
$(el).hide();
|
|
}
|
|
})
|
|
});
|
|
|
|
}
|
|
|
|
$(document).keydown(keyDownHandler);
|
|
$(document).keyup(keyUpHandler);
|
|
|
|
$("#button-select-add-exam").click(function (evt) {
|
|
// Find selected objects
|
|
|
|
|
|
|
|
var jqxhr = $.get(evt.target.dataset.exam_list_url, function (data) {
|
|
console.log(data);
|
|
$("#exam-options").empty();
|
|
data.forEach((obj, n) => {
|
|
$("#exam-options").append($(document.createElement('button')).prop({
|
|
type: 'button',
|
|
innerHTML: obj.name,
|
|
class: '',
|
|
|
|
}).data("exam-id", obj.id).click((evt) => {
|
|
addToExam(evt)
|
|
}))
|
|
})
|
|
})
|
|
.done(function () {
|
|
//alert( "second success" );
|
|
})
|
|
.fail(function () {
|
|
//alert( "error" );
|
|
})
|
|
.always(function () {
|
|
//alert( "finished" );
|
|
});
|
|
|
|
return;
|
|
|
|
|
|
function addToExam(evt) {
|
|
|
|
let ids = []
|
|
$("table input:checked").each((n, el) => {
|
|
ids.push(el.value)
|
|
})
|
|
|
|
// if no question selected
|
|
if (ids.length < 1) {
|
|
toastr.info('No question selected.');
|
|
return
|
|
}
|
|
let post_url = document.getElementById("button-select-add-exam").dataset.exam_json_edit_url;
|
|
let type = document.getElementById("button-select-add-exam").dataset.type;
|
|
let csrf = document.getElementById("button-select-add-exam").dataset.csrf;
|
|
$.ajax({
|
|
url: post_url,
|
|
data: {
|
|
csrfmiddlewaretoken: csrf,
|
|
add_exam_questions: JSON.stringify(ids),
|
|
type: type,
|
|
exam_id: $(evt.target).data("exam-id"),
|
|
},
|
|
type: "POST",
|
|
dataType: "json",
|
|
})
|
|
// $.ajax().done(), $.ajax().fail(), $ajax().always() are upto you. Add/change accordingly
|
|
.done(function (data) {
|
|
console.log(data);
|
|
|
|
if (data.status == "success") {
|
|
toastr.info('Questions added to exams.')
|
|
}
|
|
})
|
|
.always(function () {
|
|
console.log('[Done]');
|
|
$("#exam-options").empty();
|
|
})
|
|
}
|
|
});
|
|
|
|
|
|
});
|
|
|
|
window.loadDicomViewerEvent = new Event('loadDicomViewer');
|
|
window.addEventListener('loadDicomViewer', function (e) {
|
|
//console.log("listen", e.detail)
|
|
let images = [];
|
|
//console.log($("#image_form_set img"));
|
|
$(e.detail).each((n, el) => {
|
|
images.push($(el).attr("src"));
|
|
});
|
|
//console.log("listen2", images)
|
|
loadDicomViewer(images);
|
|
}, false);
|
|
|
|
window.loadDicomViewerEvent = new Event('loadDicomViewerUrls');
|
|
window.addEventListener('loadDicomViewerUrls', function (e) {
|
|
|
|
loadDicomViewer(e.detail.images, e.detail.annotations);
|
|
}, false);
|
|
|
|
function loadDicomViewer(images_to_load, annotations_to_load) {
|
|
console.log("loadDicomViewer", images_to_load);
|
|
let single_dicom = document.getElementById("single-dicom-viewer");
|
|
if (single_dicom) {
|
|
|
|
let images = single_dicom.dataset.images;
|
|
|
|
if (images_to_load != undefined) {
|
|
images = images_to_load;
|
|
//} else if (images.indexOf(",") > 0) {
|
|
} else if (images == undefined || images == "") {
|
|
// No images to load
|
|
return
|
|
} else {
|
|
images = JSON.parse(images);
|
|
}
|
|
|
|
console.log(images);
|
|
|
|
let annotations = single_dicom.dataset.annotations;
|
|
if (annotations_to_load != undefined) {
|
|
annotations = annotations_to_load;
|
|
} else if (annotations && annotations.indexOf(",") > 0) {
|
|
annotations = JSON.parse(annotations);
|
|
} else {
|
|
annotations = undefined;
|
|
}
|
|
|
|
let load_as_stack;
|
|
if (images.length > 5) {
|
|
load_as_stack = true;
|
|
} else {
|
|
load_as_stack = false;
|
|
}
|
|
|
|
if (images) {
|
|
dicomViewer.loadCornerstone($(single_dicom), null, images, annotations, load_as_stack);
|
|
}
|
|
}
|
|
}
|
|
|
|
function prepAnswerData() {
|
|
//$("#id_correct").val($("li.correct").map(function() {
|
|
// ans = $(this).text();
|
|
// window.marked_answers["correct"].push(ans);
|
|
// return ans
|
|
//}).get().join('--//--'));
|
|
//$("#id_half_correct").val($("li.half-correct").map(function() {
|
|
// ans = $(this).text();
|
|
// window.marked_answers["half-correct"].push(ans);
|
|
// return ans;
|
|
//}).get().join('--//--'));
|
|
//$("#id_incorrect").val($("li.incorrect").map(function() {
|
|
// ans = $(this).text();
|
|
// window.marked_answers["incorrect"].push(ans);
|
|
// return ans;
|
|
//}).get().join('--//--'));
|
|
|
|
window.marked_answers["correct"] = [];
|
|
window.marked_answers["half-correct"] = [];
|
|
window.marked_answers["incorrect"] = [];
|
|
$("li span.correct").map(function () {
|
|
let ans = $(this).text();
|
|
window.marked_answers["correct"].push(ans);
|
|
})
|
|
$("li span.half-correct").map(function () {
|
|
let ans = $(this).text();
|
|
window.marked_answers["half-correct"].push(ans);
|
|
})
|
|
$("li span.incorrect").map(function () {
|
|
let ans = $(this).text();
|
|
window.marked_answers["incorrect"].push(ans);
|
|
})
|
|
$("#id_marked_answers").val(JSON.stringify(window.marked_answers));
|
|
}
|
|
|
|
function loadJsonToolStateOnCurrentImage(json) {
|
|
let el = document.getElementById("dicom-image");
|
|
|
|
const toolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager;
|
|
|
|
const c = cornerstone.getEnabledElement(el);
|
|
|
|
let image_id = c.image.imageId;
|
|
|
|
let tool_state_no_id = JSON.parse(json);
|
|
|
|
let tool_state = {};
|
|
tool_state[image_id] = tool_state_no_id;
|
|
|
|
toolStateManager.restoreToolState(tool_state);
|
|
|
|
cornerstone.reset(el);
|
|
|
|
return tool_state;
|
|
|
|
|
|
}
|
|
|
|
function setUpDicom(element) {
|
|
|
|
console.log("Dicom element found ", $(element));
|
|
|
|
$(element).bind('contextmenu', function (e) {
|
|
return false;
|
|
});
|
|
|
|
$(element).dblclick((evt) => {
|
|
element.requestFullscreen();
|
|
})
|
|
|
|
cornerstoneBase64ImageLoader.external.cornerstone = cornerstone;
|
|
cornerstoneWebImageLoader.external.cornerstone = cornerstone;
|
|
cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
|
|
|
|
cornerstoneTools.init();
|
|
const PanTool = cornerstoneTools.PanTool;
|
|
const ZoomTool = cornerstoneTools.ZoomTool;
|
|
const ZoomMouseWheelTool = cornerstoneTools.ZoomMouseWheelTool;
|
|
const WwwcTool = cornerstoneTools.WwwcTool;
|
|
const WwwcRegionTool = cornerstoneTools.WwwcRegionTool;
|
|
const RotateTool = cornerstoneTools.RotateTool;
|
|
const StackScrollTool = cornerstoneTools.StackScrollTool;
|
|
const MagnifyTool = cornerstoneTools.MagnifyTool;
|
|
const ArrowAnnotateTool = cornerstoneTools.ArrowAnnotateTool;
|
|
|
|
|
|
const imageIds = element.dataset.url.split(",");
|
|
|
|
console.log("Dicom - load imageId: ", imageIds);
|
|
|
|
cornerstone.enable(element);
|
|
cornerstone.loadAndCacheImage(imageIds[0]).then(function (image) {
|
|
cornerstone.displayImage(element, image);
|
|
|
|
cornerstoneTools.addToolForElement(element, PanTool);
|
|
cornerstoneTools.addToolForElement(element, ZoomTool);
|
|
cornerstoneTools.addToolForElement(element, ZoomMouseWheelTool);
|
|
cornerstoneTools.addToolForElement(element, WwwcTool);
|
|
cornerstoneTools.addToolForElement(element, WwwcRegionTool);
|
|
cornerstoneTools.addToolForElement(element, RotateTool);
|
|
cornerstoneTools.addToolForElement(element, StackScrollTool);
|
|
cornerstoneTools.addToolForElement(element, MagnifyTool);
|
|
|
|
cornerstoneTools.addToolForElement(element, ArrowAnnotateTool, {
|
|
configuration: {
|
|
getTextCallback: () => {},
|
|
changeTextCallback: () => {},
|
|
allowEmptyLabel: true,
|
|
renderDashed: false,
|
|
drawHandles: false,
|
|
drawHandlesOnHover: true,
|
|
},
|
|
});
|
|
|
|
|
|
|
|
// Enable our tools
|
|
// Avoid incorrect aspect ratio
|
|
cornerstoneTools.setToolActiveForElement(element, "Pan", {
|
|
mouseButtonMask: 1
|
|
});
|
|
cornerstoneTools.setToolActiveForElement(element, "Wwwc", {
|
|
mouseButtonMask: 2
|
|
});
|
|
cornerstoneTools.setToolActiveForElement(element, "ZoomMouseWheel", {
|
|
mouseButtonMask: 3
|
|
});
|
|
cornerstoneTools.setToolActiveForElement(element, "Zoom", {
|
|
mouseButtonMask: 4
|
|
});
|
|
|
|
if (element.dataset.edit_annotation == "true") {
|
|
cornerstoneTools.setToolActiveForElement(element, "ArrowAnnotate", {
|
|
mouseButtonMask: 2
|
|
});
|
|
} else {
|
|
cornerstoneTools.setToolEnabledForElement(element, "ArrowAnnotate");
|
|
}
|
|
|
|
if (element.dataset.annotations) {
|
|
loadJsonToolStateOnCurrentImage(element.dataset.annotations)
|
|
}
|
|
|
|
cornerstone.resize(element);
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
function keyUpHandler(e) {
|
|
if (e.key == "Control") {
|
|
dicomViewer.registerPrimaryDicomInterface(e);
|
|
window.control_pressed = false;
|
|
}
|
|
}
|
|
|
|
function keyDownHandler(e) {
|
|
// Ignore our custom keybindings if we are currently in a field that
|
|
// accepts some kind of input
|
|
if ($("*:focus:not(disabled)").is("textarea, input")) {
|
|
// unless a modifier key is pressed (not shift)
|
|
if (e.altKey ? true : false || e.ctrlKey ? true : false) {} else {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (e.key == "Control") {
|
|
if (window.control_pressed == false) {
|
|
window.control_pressed = true;
|
|
dicomViewer.registerAltDicomInterface(e);
|
|
}
|
|
}
|
|
|
|
var charCode = typeof e.which == "number" ? e.which : e.keyCode;
|
|
console.log(e, charCode);
|
|
|
|
function numberKeyPressed(e, x) {
|
|
if (e.altKey ? true : false) {
|
|
dicomViewer.selectThumb(x);
|
|
e.preventDefault();
|
|
} else {}
|
|
}
|
|
|
|
switch (charCode) {
|
|
case 13: // Return
|
|
if (e.shiftKey ? true : false) {
|
|
//$(".next-button:last").click();
|
|
} else {
|
|
//$(".check-button:last").click();
|
|
}
|
|
break;
|
|
case 32: // Space
|
|
if (e.shiftKey ? true : false) {
|
|
//$(".previous-button:last").click();
|
|
} else {
|
|
//$(".next-button:last").click();
|
|
}
|
|
e.preventDefault(); // Needed to stop the default action (scroll)
|
|
break;
|
|
case 46: // .
|
|
//toggleFlagged();
|
|
break;
|
|
|
|
// Numbers 1-9 select the corresponding answer (if it exists)
|
|
// TODO: fix for multi question questions
|
|
case 49: // 1
|
|
numberKeyPressed(e, 0);
|
|
break;
|
|
case 50: // 2
|
|
numberKeyPressed(e, 1);
|
|
break;
|
|
case 51: // 3
|
|
numberKeyPressed(e, 2);
|
|
break;
|
|
case 52: // 4
|
|
numberKeyPressed(e, 3);
|
|
break;
|
|
case 53: // 5
|
|
numberKeyPressed(e, 4);
|
|
break;
|
|
case 54: // 6
|
|
numberKeyPressed(e, 5);
|
|
break;
|
|
case 55: // 7
|
|
numberKeyPressed(e, 6);
|
|
break;
|
|
case 56: // 8
|
|
numberKeyPressed(e, 7);
|
|
break;
|
|
case 57: // 9
|
|
numberKeyPressed(e, 8);
|
|
break;
|
|
case 72: // H
|
|
previousQuestion();
|
|
break;
|
|
case 76: // L
|
|
//nextQuestion();
|
|
break;
|
|
|
|
case 102: // f
|
|
//$("#filter-toggle").click();
|
|
break;
|
|
case 103: // g
|
|
//$("#options").slideDown("slow");
|
|
//$("#goto-question-input").focus();
|
|
//e.preventDefault();
|
|
break;
|
|
|
|
// Vim like scrolling (incredibly important)
|
|
case 106: // j
|
|
//window.scrollBy(0, 25);
|
|
break;
|
|
case 107: // k
|
|
//window.scrollBy(0, -25);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
function create_popup_window(url, title) {
|
|
newwindow = window.open(url, title, 'height=800,width=600');
|
|
if (window.focus) {
|
|
newwindow.focus()
|
|
}
|
|
return false;
|
|
}
|
|
|
|
window.create_popup_window = create_popup_window
|
|
|
|
function delete_multiple(url, csrf_token) {
|
|
|
|
let answer_ids = [];
|
|
$("tbody input:checked").each((n, el) => {
|
|
answer_ids.push(el.value);
|
|
})
|
|
if (confirm(`Delete ${answer_ids.length} answers?`)) {
|
|
$.ajax({
|
|
url: url,
|
|
data: {
|
|
csrfmiddlewaretoken: csrf_token,
|
|
answer_ids: JSON.stringify(answer_ids) // true if checked else false
|
|
},
|
|
type: "POST",
|
|
dataType: "json",
|
|
})
|
|
// $.ajax().done(), $.ajax().fail(), $ajax().always() are upto you. Add/change accordingly
|
|
.done(function (data) {
|
|
console.log(data);
|
|
|
|
if (data.status == "success") {
|
|
toastr.info('Deleted.')
|
|
}
|
|
// show some message according to the response.
|
|
// For eg. A message box showing that the status has been changed
|
|
})
|
|
.always(function () {
|
|
console.log('[Done]');
|
|
})
|
|
}
|
|
|
|
}
|
|
window.delete_multiple = delete_multiple |