diff --git a/js/main.js b/js/main.js index f9de5cb..c7f413b 100644 --- a/js/main.js +++ b/js/main.js @@ -498,95 +498,11 @@ function loadQuestion(n, section = 1, force_reload = false) { $(".thumbs .figure").each(function handleThumbnailClicks(id, thumbnail) { thumbnail.onclick = function (event) { - view(event, this); + viewer.openMainImage(current_question, event, this); }; }); - /** - * View cornstone image - * @param {*} t - * @param {*} source - */ - function view(t, source) { - /** - * Load image - * @param {*} images - list of images - */ - async function load(images) { - const imageIds = []; - for (let i = 0; i < images.length; i++) { - const data_url = images[i]; - // check stack type - if (data_url.startsWith("data:image")) { - const imageId = "base64://" + data_url.split(",")[1]; - imageIds.push(imageId); - } else if (data_url.startsWith("data:application/dicom")) { - // stack = stack.split(";")[1]; - - const dfile = await helper.urltoFile( - data_url, - "dicom", - "application/dicom" - ); - - const imageId = cornerstoneWADOImageLoader.wadouri.fileManager.add( - dfile - ); - imageIds.push(imageId); - // cornerstone.loadImage(imageId).then(function(image) { - // tempFunction(image); - // }); - } - } - const stack = { - currentImageIdIndex: 0, - imageIds, - }; - cornerstone.loadAndCacheImage(imageIds[0]).then(function (image) { - viewer.loadMainImage(image, stack); - }); - } - - if (current_question) { - // Check if the figure is already loaded (or if another one is) - const open_figure = $("#dicom-image").data("figure"); - const figure_to_load = source.id; - - if (open_figure != undefined) { - // No full size figure / dicom loaded yet - if (figure_to_load == open_figure) { - return; - } else { - el = document.getElementById("dicom-image"); - if (el != undefined) { - cornerstone.disable(el); - $(".canvas-panel").remove(); - } - } - } - - $(".figure-open").removeClass("figure-open").addClass("figure"); - - source.className = "figure-open"; - - $(".question").append( - '
' - ); - - let images = current_question.images[figure_to_load.split("-")[1]]; - // images = current_question.images - - // Make sure we have an array - if (!Array.isArray(images)) { - images = [images]; - } - - load(images); - } - } // Answer setup const ap = $(".answer-panel"); @@ -1026,160 +942,6 @@ function createQuestionListPanel() { }); } -/** - * Handle key button events - * These are the same as in the RCR pratique implementation - * @param {*} event - KeyEvent - */ -function keydown_handler(event) { - const target_element = event.target.tagName; - - // Catch all keypresses unless user is typing - if (target_element == "INPUT" || target_element == "TEXTAREA") { - return; - } - const sel = $(".control-overlay").get(0); - switch (event.code) { - case "KeyP": - sel.selectedIndex = viewer.find_option(sel, "pan"); - viewer.changeControlSelection(); - break; - case "KeyZ": - sel.selectedIndex = viewer.find_option(sel, "zoom"); - viewer.changeControlSelection(); - break; - case "KeyR": - sel.selectedIndex = viewer.find_option(sel, "rotate"); - viewer.changeControlSelection(); - break; - case "KeyS": - sel.selectedIndex = viewer.find_option(sel, "scroll"); - viewer.changeControlSelection(); - break; - case "KeyW": - sel.selectedIndex = viewer.find_option(sel, "window"); - viewer.changeControlSelection(); - break; - case "KeyA": - sel.selectedIndex = viewer.find_option(sel, "abdomen"); - viewer.changeControlSelection(); - break; - case "KeyU": - sel.selectedIndex = viewer.find_option(sel, "pulmonary"); - viewer.changeControlSelection(); - break; - case "KeyB": - sel.selectedIndex = viewer.find_option(sel, "brain"); - viewer.changeControlSelection(); - break; - case "KeyO": - sel.selectedIndex = viewer.find_option(sel, "bone"); - viewer.changeControlSelection(); - break; - case "KeyE": - sel.selectedIndex = viewer.find_option(sel, "reset"); - // $("#dicom-image").get(0).scrollIntoView(false); - viewer.changeControlSelection(); - break; - // Escape and C do the same - case "KeyC": - case "Escape": - sel.selectedIndex = viewer.find_option(sel, "close"); - viewer.changeControlSelection(); - break; - case "Enter": - t.focus(); - break; - // TODO: implement arrow stuff - // - case "ArrowUp": { - // Arrow function depends on the currently selected option - switch (sel.options[sel.selectedIndex].value) { - case "pan": - viewer.manualPanDicom(0, -1); - break; - case "zoom": - // _this.current_dicom.current_view.pre_scale_at(1.01, 1.01, _this.current_dicom.cols / 2, _this.current_dicom.rows / 2); - viewer.manualZoomDicom(1); - break; - case "rotate": - viewer.manualRotateDicom(-1); - break; - case "scroll": - viewer.manualScrollDicom(-1); - break; - case "window": - viewer.manualWindowDicom(1, 0); - break; - } - break; - } - case "ArrowDown": { - switch (sel.options[sel.selectedIndex].value) { - case "pan": - viewer.manualPanDicom(0, 1); - break; - case "zoom": - viewer.manualZoomDicom(-1); - break; - case "rotate": - viewer.manualRotateDicom(1); - break; - case "scroll": - viewer.manualScrollDicom(1); - break; - case "window": - viewer.manualWindowDicom(-1, 0); - break; - } - break; - } - case "ArrowLeft": { - switch (sel.options[sel.selectedIndex].value) { - case "pan": - viewer.manualPanDicom(-1, 0); - break; - case "zoom": - viewer.manualZoomDicom(-1); - break; - case "rotate": - viewer.manualRotateDicom(1); - break; - case "scroll": - viewer.manualScrollDicom(1); - break; - case "window": - viewer.manualWindowDicom(0, -1); - break; - } - break; - } - case "ArrowRight": { - switch (sel.options[sel.selectedIndex].value) { - case "pan": - viewer.manualPanDicom(1, 0); - break; - case "zoom": - viewer.manualZoomDicom(1); - break; - case "rotate": - viewer.manualRotateDicom(-1); - break; - case "scroll": - viewer.manualScrollDicom(-1); - break; - case "window": - viewer.manualWindowDicom(0, 1); - break; - } - break; - } - } - event.preventDefault(); -} - -// Register Key Event Listener -window.addEventListener("keydown", keydown_handler); $("#btn-local-file-load").click(function (evt) { loadLocalQuestionSet(); @@ -2004,3 +1766,6 @@ function saveSession() { total_questions: window.number_of_questions, }); } + +// Register Key Event Listener +window.addEventListener("keydown", viewer.keydown_handler); \ No newline at end of file diff --git a/js/viewer.js b/js/viewer.js index 2cd5e41..13bfa22 100644 --- a/js/viewer.js +++ b/js/viewer.js @@ -328,3 +328,241 @@ export function changeControlSelection() { event.preventDefault(); } } + +/** + * Handle key button events + * These are the same as in the RCR pratique implementation + * @param {*} event - KeyEvent + */ +export function keydown_handler(event) { + const target_element = event.target.tagName; + + // Catch all keypresses unless user is typing + if (target_element == "INPUT" || target_element == "TEXTAREA") { + return; + } + const sel = $(".control-overlay").get(0); + switch (event.code) { + case "KeyP": + sel.selectedIndex = find_option(sel, "pan"); + changeControlSelection(); + break; + case "KeyZ": + sel.selectedIndex = find_option(sel, "zoom"); + changeControlSelection(); + break; + case "KeyR": + sel.selectedIndex = find_option(sel, "rotate"); + changeControlSelection(); + break; + case "KeyS": + sel.selectedIndex = find_option(sel, "scroll"); + changeControlSelection(); + break; + case "KeyW": + sel.selectedIndex = find_option(sel, "window"); + changeControlSelection(); + break; + case "KeyA": + sel.selectedIndex = find_option(sel, "abdomen"); + changeControlSelection(); + break; + case "KeyU": + sel.selectedIndex = find_option(sel, "pulmonary"); + changeControlSelection(); + break; + case "KeyB": + sel.selectedIndex = find_option(sel, "brain"); + changeControlSelection(); + break; + case "KeyO": + sel.selectedIndex = find_option(sel, "bone"); + changeControlSelection(); + break; + case "KeyE": + sel.selectedIndex = find_option(sel, "reset"); + // $("#dicom-image").get(0).scrollIntoView(false); + changeControlSelection(); + break; + // Escape and C do the same + case "KeyC": + case "Escape": + sel.selectedIndex = find_option(sel, "close"); + changeControlSelection(); + break; + case "Enter": + t.focus(); + break; + // TODO: implement arrow stuff + // + case "ArrowUp": { + // Arrow function depends on the currently selected option + switch (sel.options[sel.selectedIndex].value) { + case "pan": + manualPanDicom(0, -1); + break; + case "zoom": + // _this.current_dicom.current_view.pre_scale_at(1.01, 1.01, _this.current_dicom.cols / 2, _this.current_dicom.rows / 2); + manualZoomDicom(1); + break; + case "rotate": + manualRotateDicom(-1); + break; + case "scroll": + manualScrollDicom(-1); + break; + case "window": + manualWindowDicom(1, 0); + break; + } + break; + } + case "ArrowDown": { + switch (sel.options[sel.selectedIndex].value) { + case "pan": + manualPanDicom(0, 1); + break; + case "zoom": + manualZoomDicom(-1); + break; + case "rotate": + manualRotateDicom(1); + break; + case "scroll": + manualScrollDicom(1); + break; + case "window": + manualWindowDicom(-1, 0); + break; + } + break; + } + case "ArrowLeft": { + switch (sel.options[sel.selectedIndex].value) { + case "pan": + manualPanDicom(-1, 0); + break; + case "zoom": + manualZoomDicom(-1); + break; + case "rotate": + manualRotateDicom(1); + break; + case "scroll": + manualScrollDicom(1); + break; + case "window": + manualWindowDicom(0, -1); + break; + } + break; + } + case "ArrowRight": { + switch (sel.options[sel.selectedIndex].value) { + case "pan": + manualPanDicom(1, 0); + break; + case "zoom": + manualZoomDicom(1); + break; + case "rotate": + manualRotateDicom(-1); + break; + case "scroll": + manualScrollDicom(-1); + break; + case "window": + manualWindowDicom(0, 1); + break; + } + break; + } + } + event.preventDefault(); +} + +/** + * View cornstone image + * @param {*} t + * @param {*} source + */ +export function openMainImage(current_question, t, source) { + /** + * Load image + * @param {*} images - list of images + */ + async function load(images) { + const imageIds = []; + for (let i = 0; i < images.length; i++) { + const data_url = images[i]; + // check stack type + if (data_url.startsWith("data:image")) { + const imageId = "base64://" + data_url.split(",")[1]; + + imageIds.push(imageId); + } else if (data_url.startsWith("data:application/dicom")) { + // stack = stack.split(";")[1]; + + const dfile = await helper.urltoFile( + data_url, + "dicom", + "application/dicom" + ); + + const imageId = cornerstoneWADOImageLoader.wadouri.fileManager.add( + dfile + ); + imageIds.push(imageId); + // cornerstone.loadImage(imageId).then(function(image) { + // tempFunction(image); + // }); + } + } + const stack = { + currentImageIdIndex: 0, + imageIds, + }; + cornerstone.loadAndCacheImage(imageIds[0]).then(function (image) { + loadMainImage(image, stack); + }); + } + + if (current_question) { + // Check if the figure is already loaded (or if another one is) + const open_figure = $("#dicom-image").data("figure"); + const figure_to_load = source.id; + + if (open_figure != undefined) { + // No full size figure / dicom loaded yet + if (figure_to_load == open_figure) { + return; + } else { + el = document.getElementById("dicom-image"); + if (el != undefined) { + cornerstone.disable(el); + $(".canvas-panel").remove(); + } + } + } + + $(".figure-open").removeClass("figure-open").addClass("figure"); + + source.className = "figure-open"; + + $(".question").append( + '
' + ); + + let images = current_question.images[figure_to_load.split("-")[1]]; + // images = current_question.images + + // Make sure we have an array + if (!Array.isArray(images)) { + images = [images]; + } + + load(images); + } +}