add ability to load local (online) packets

This commit is contained in:
ross
2020-04-27 23:19:20 +01:00
parent 9793252f3a
commit 514887dded
3 changed files with 302 additions and 228 deletions
+28
View File
@@ -736,3 +736,31 @@ select option:disabled {
.feedback { .feedback {
padding-top: 0.8rem; padding-top: 0.8rem;
} }
#localFileloader {
padding: 20px;
}
#packet-list {
padding: 20px;
}
.packet-button {
display:inline-block;
padding:0.35em 1.2em;
border:0.1em solid #FFFFFF;
margin:0 0.3em 0.3em 0;
border-radius:0.12em;
box-sizing: border-box;
text-decoration:none;
font-family:'Roboto',sans-serif;
font-weight:300;
color:#FFFFFF;
text-align:center;
transition: all 0.2s;
}
.packet-button:hover{
color:lightblue;
border-color:blue;
}
+96 -91
View File
@@ -1,111 +1,116 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" class="no-touch" lang="en"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" class="no-touch" lang="en">
<head> <head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"> <meta name="viewport"
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, width=device-width, height=device-height"> content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
<link type="text/css" rel="stylesheet" href="lib/jquery.modal.min.css"> <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, width=device-width, height=device-height">
<link type="text/css" rel="stylesheet" href="lib/cornerstone.min.css"> <link type="text/css" rel="stylesheet" href="lib/jquery.modal.min.css">
<link type="text/css" rel="stylesheet" href="css/main.css"> <link type="text/css" rel="stylesheet" href="lib/cornerstone.min.css">
<title>RTS</title> <link type="text/css" rel="stylesheet" href="css/main.css">
</head> <title>RTS</title>
</head>
<body> <body>
<div id="content"> <div id="content">
<div class="content-panel"> <div class="content-panel">
<div class="nav-bar"> <div class="nav-bar">
<button id="review-button" class="navigation nav-right"><b></b></button> <button id="review-button" class="navigation nav-right"><b></b></button>
<button id="submit-button" class="navigation nav-right"><b>submit</b></button> <button id="submit-button" class="navigation nav-right"><b>submit</b></button>
<button id="options-button" class="navigation nav-right">options</button> <button id="options-button" class="navigation nav-right">options</button>
<button id="review-overlay-button" class="navigation nav-right">review</button> <button id="review-overlay-button" class="navigation nav-right">review</button>
<!--<button id="logout-button" class="navigation nav-right">logout</button>--> <!--<button id="logout-button" class="navigation nav-right">logout</button>-->
<div class="app-name nav-left">RTS</div> <div class="app-name nav-left">RTS</div>
<div class="exam-name"></div> <div class="exam-name"></div>
<input type="button" class="navigation nav-left" value="previous" disabled="disabled"> <input type="button" class="navigation nav-left" value="previous" disabled="disabled">
<input type="button" class="navigation nav-left" value="next"> <input type="button" class="navigation nav-left" value="next">
</div>
<div class="main-panel">
<div class="question-list-panel" style="display: block;">
</div> </div>
<div class="main-panel"> <div class="exam-panel">
<div class="question-list-panel" style="display: block;"> <div class="exam-content-panel">
</div> <div class="question">
<div class="exam-panel"> <div class="title"><span style="font-weight:700;">1</span> </div>
<div class="exam-content-panel"> <div class="stem">
<div class="question"> <div id="thumbnails"></div>
<div class="title"><span style="font-weight:700;">1</span> </div>
<div class="stem">
<div id="thumbnails"></div>
</div>
<div class="thumbs">
</div>
</div> </div>
<div class="answers"> <div class="thumbs">
<div class="answer-title">Answer</div> </div>
<div class="answer-panel"> </div>
</div> <div class="answers">
<div class="answer-title">Answer</div>
<div class="answer-panel">
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="logout-background"> </div>
<div class="logout-panel"> <div class="logout-background">
<div class="logout-title">Ready to logout?</div> <div class="logout-panel">
<div class="logout-text"></div> <div class="logout-title">Ready to logout?</div>
<button class="navigation logout-cancel">continue exam</button> <div class="logout-text"></div>
<button class="navigation logout-okay">logout now</button> <button class="navigation logout-cancel">continue exam</button>
</div> <button class="navigation logout-okay">logout now</button>
</div>
<div id="options-panel" class="fullscreen-overlay">
<a href="#" id="overlay-close" class="close" ></a>
<div id="localFileloader">
<form id="jsonFile" name="jsonFile" enctype="multipart/form-data" method="post">
<fieldset>
<h2>Load local question set</h2>
<input type='file' id='fileinput'>
<input type='button' id='btn-local-file-load' value='Load' onclick='loadLocalQuestionSet();'>
</fieldset>
</form>
</div>
</div>
<div id="review-overlay" class="fullscreen-overlay">
<a href="#" id="review-overlay-close" class="close" ></a>
<ul id='review-answer-list'></ul>
<div id="review-score"></div>
</div> </div>
</div> </div>
</div> <div id="options-panel" class="fullscreen-overlay">
<a href="#" id="overlay-close" class="close"></a>
<div id="localFileloader">
<form id="jsonFile" name="jsonFile" enctype="multipart/form-data" method="post">
<div id="finish-dialog" class="dialog modal"> <fieldset>
<h3 class="dialog-title">Finish exam and review?</h3> <h2>Load local question set</h2>
<div class="dialog-text"> <input type='file' id='fileinput'>
<button id="finish-exam" class="navigation dialog-yes">Finish and review</button> <input type='button' id='btn-local-file-load' value='Load'
<button id="finish-cancel" class="navigation dialog-cancel">Continue exam</button> onclick='loadLocalQuestionSet();'>
</fieldset>
</form>
</div>
<div id="packet-list">
<p>Available Packets:</p>
</div>
</div>
<div id="review-overlay" class="fullscreen-overlay">
<a href="#" id="review-overlay-close" class="close"></a>
<ul id='review-answer-list'></ul>
<div id="review-score"></div>
</div> </div>
</div> </div>
</div>
<div id="login-dialog" class="dialog modal"> <div id="finish-dialog" class="dialog modal">
<h3 class="dialog-title">Select exam</h3> <h3 class="dialog-title">Finish exam and review?</h3>
Candidate number: <input type="text" id="candidate-number" name="candidate" required size="10"> <div class="dialog-text">
<div class="dialog-text"> <button id="finish-exam" class="navigation dialog-yes">Finish and review</button>
<button id="start-exam-button" class="navigation dialog-yes">Start</button> <button id="finish-cancel" class="navigation dialog-cancel">Continue exam</button>
</div>
</div> </div>
</div>
<script src="lib/jquery-3.4.1.min.js" type="text/javascript"></script> <div id="login-dialog" class="dialog modal">
<script src="lib/hammer.js"></script> <h3 class="dialog-title">Select exam</h3>
<script src="lib/cornerstone.js"></script> Candidate number: <input type="text" id="candidate-number" name="candidate" required size="10">
<script src="lib/dicomParser.min.js"></script> <div class="dialog-text">
<script src="lib/cornerstoneMath.min.js"></script> <button id="start-exam-button" class="navigation dialog-yes">Start</button>
<script src="lib/cornerstoneTools.js"></script> </div>
<script src="lib/cornerstoneWebImageLoader.min.js"></script> </div>
<script src="lib/cornerstoneWADOImageLoader.js"></script>
<script src="lib/cornerstone-base64-image-loader.umd.js"></script>
<script src="lib/dexie.js"></script>
<script src="lib/jquery.modal.min.js"></script>
<script src="packets/rr1" defer="defer"></script>
<script src="js/main.js" defer="defer"></script>
</body> <script src="lib/jquery-3.4.1.min.js" type="text/javascript"></script>
<script src="lib/hammer.js"></script>
<script src="lib/cornerstone.js"></script>
<script src="lib/dicomParser.min.js"></script>
<script src="lib/cornerstoneMath.min.js"></script>
<script src="lib/cornerstoneTools.js"></script>
<script src="lib/cornerstoneWebImageLoader.min.js"></script>
<script src="lib/cornerstoneWADOImageLoader.js"></script>
<script src="lib/cornerstone-base64-image-loader.umd.js"></script>
<script src="lib/dexie.js"></script>
<script src="lib/jquery.modal.min.js"></script>
<!-- <script src="packets/rr1" defer="defer"></script> -->
<script src="js/main.js" defer="defer"></script>
</html> </body>
</html>
+178 -137
View File
@@ -4,6 +4,8 @@ var eid = 5678;
var exam_mode = false; var exam_mode = false;
var packet_list = [];
//var questions = null //var questions = null
var question_order = []; var question_order = [];
var number_of_questions = null; var number_of_questions = null;
@@ -18,10 +20,50 @@ var dfile = null;
var a = null; var a = null;
var b = null; var b = null;
loadPacketList();
function loadPacketList() {
var jqxhr = $.getJSON("packets/packets.json", function (data) {
packet_list = data.packets;
packet_list.forEach(function (packet) {
$("#packet-list").append($("<div class='packet-button'>" + packet + "</div>").click(function () {
loadPacketFromAjax("packets/" + packet);
}));
})
$("#options-panel").show();
})
.done(function () {
})
.fail(function () {
console.log("No packet list available");
showLoginDialog();
})
.always(function () {
});
//setUpPacket(questions);
}
function loadPacketFromAjax(path) {
console.log("loading packet from " + path)
var jqxhr = $.getJSON(path, function (data) {
setUpPacket(data);
$("#options-panel").hide();
})
.done(function () {
})
.fail(function () {
console.log("Unable to load packet at: " + path);
})
}
function setUpQuestions() { function setUpQuestions() {
if (questions == undefined) { return }
// Set an order for the questions // Set an order for the questions
question_order = []; question_order = [];
Object.keys(questions).forEach(function(e) { Object.keys(questions).forEach(function (e) {
question_order.push(e); question_order.push(e);
// Make sure answers are arrays // Make sure answers are arrays
@@ -33,6 +75,7 @@ function setUpQuestions() {
question_order = shuffleArray(question_order); question_order = shuffleArray(question_order);
number_of_questions = Object.keys(questions).length; number_of_questions = Object.keys(questions).length;
review = false; review = false;
console.log(question_order)
// Horrible way to get type of questions // Horrible way to get type of questions
// We assume they are all of the same type.... // We assume they are all of the same type....
@@ -126,7 +169,6 @@ function setUpPacket(data) {
setUpQuestions(); setUpQuestions();
} }
setUpPacket(questions);
function loadQuestion(n, section = 1, force_reload = false) { function loadQuestion(n, section = 1, force_reload = false) {
// Make sure we have an integer // Make sure we have an integer
@@ -153,7 +195,7 @@ function loadQuestion(n, section = 1, force_reload = false) {
} else { } else {
$(".navigation[value='previous']") $(".navigation[value='previous']")
.removeAttr("disabled") .removeAttr("disabled")
.click(function() { .click(function () {
loadQuestion(n - 1); loadQuestion(n - 1);
}); });
} }
@@ -163,7 +205,7 @@ function loadQuestion(n, section = 1, force_reload = false) {
} else { } else {
$(".navigation[value='next']") $(".navigation[value='next']")
.removeAttr("disabled") .removeAttr("disabled")
.click(function() { .click(function () {
loadQuestion(n + 1); loadQuestion(n + 1);
}); });
} }
@@ -204,8 +246,8 @@ function loadQuestion(n, section = 1, force_reload = false) {
thumbnails.append( thumbnails.append(
'<div class="figure" id="figure-' + '<div class="figure" id="figure-' +
id + id +
'"><div class="figcaption">...</div></div>' '"><div class="figcaption">...</div></div>'
); );
thumbnail = $(".figure .thumbnail").get(id); thumbnail = $(".figure .thumbnail").get(id);
@@ -229,14 +271,14 @@ function loadQuestion(n, section = 1, force_reload = false) {
// otherwise try to load it as a dicom // otherwise try to load it as a dicom
} else { } else {
// convert the data url to a file // convert the data url to a file
urltoFile(based_img, "dicom", "application/dicom").then(function( urltoFile(based_img, "dicom", "application/dicom").then(function (
dfile dfile
) { ) {
// load the file using cornerstoneWADO file loader // load the file using cornerstoneWADO file loader
const imageId = cornerstoneWADOImageLoader.wadouri.fileManager.add( const imageId = cornerstoneWADOImageLoader.wadouri.fileManager.add(
dfile dfile
); );
cornerstone.loadAndCacheImage(imageId).then(function(image) { cornerstone.loadAndCacheImage(imageId).then(function (image) {
img = $("<div></div>").get(0); img = $("<div></div>").get(0);
img.id = "thumb-" + id; img.id = "thumb-" + id;
img.class = "thumbnail"; img.class = "thumbnail";
@@ -257,7 +299,7 @@ function loadQuestion(n, section = 1, force_reload = false) {
} }
$(".thumbs .figure").each(function handleThumbnailClicks(id, thumbnail) { $(".thumbs .figure").each(function handleThumbnailClicks(id, thumbnail) {
thumbnail.onclick = function(event) { thumbnail.onclick = function (event) {
view(event, this); view(event, this);
}; };
}); });
@@ -289,8 +331,8 @@ function loadQuestion(n, section = 1, force_reload = false) {
$(".question").append( $(".question").append(
'<div class= "canvas-panel"><div id="dicom-image" data-figure="' + '<div class= "canvas-panel"><div id="dicom-image" data-figure="' +
figure_to_load + figure_to_load +
'"></div></div>' '"></div></div>'
); );
images = current_question.images[figure_to_load.split("-")[1]]; images = current_question.images[figure_to_load.split("-")[1]];
@@ -331,7 +373,7 @@ function loadQuestion(n, section = 1, force_reload = false) {
imageIds imageIds
}; };
//cornerstone.loadAndCacheImage(imageIds[0]).then(function(image) { //cornerstone.loadAndCacheImage(imageIds[0]).then(function(image) {
cornerstone.loadAndCacheImage(imageIds[0]).then(function(image) { cornerstone.loadAndCacheImage(imageIds[0]).then(function (image) {
loadMainImage(image, stack); loadMainImage(image, stack);
}); });
} }
@@ -346,20 +388,20 @@ function loadQuestion(n, section = 1, force_reload = false) {
case "rapid": { case "rapid": {
ap.append( ap.append(
'<div class="answer-item"><div class="answer-label-outer"><p class="answer-label-inner"><span class="answer-label-number">' + '<div class="answer-item"><div class="answer-label-outer"><p class="answer-label-inner"><span class="answer-label-number">' +
display_n + display_n +
'.1</span><span style="flex:1">Case normal/abnormal</span><button class="flag" data-qid="' + '.1</span><span style="flex:1">Case normal/abnormal</span><button class="flag" data-qid="' +
n + n +
'" data-qidn=1 style="margin-right:0">⚐</button></p></div><select class="rapid-option-answer" id="rapid-option" data-answer-section-qidn=1><option selected="selected" disabled="disabled" id="rapid-option-not-answered">--- Not Answered ---</option><option>Abnormal</option><option>Normal</option></select></div>' '" data-qidn=1 style="margin-right:0">⚐</button></p></div><select class="rapid-option-answer" id="rapid-option" data-answer-section-qidn=1><option selected="selected" disabled="disabled" id="rapid-option-not-answered">--- Not Answered ---</option><option>Abnormal</option><option>Normal</option></select></div>'
); );
ap.append( ap.append(
'<div class="answer-item" id="rapid-text" style="display: none;"><div class="answer-label-outer"><p class="answer-label-inner"><span class="answer-label-number">' + '<div class="answer-item" id="rapid-text" style="display: none;"><div class="answer-label-outer"><p class="answer-label-inner"><span class="answer-label-number">' +
display_n + display_n +
'.2</span><span style="flex:1">Reason</span><button class="flag" data-qid="' + '.2</span><span style="flex:1">Reason</span><button class="flag" data-qid="' +
n + n +
'" data-qidn=2 style="margin-right:0">⚐</button></p></div><textarea class="long-answer" name="Reason" data-answer-section-qidn=2 style="overflow: hidden scroll; overflow-wrap: break-word;"></textarea></div>' '" data-qidn=2 style="margin-right:0">⚐</button></p></div><textarea class="long-answer" name="Reason" data-answer-section-qidn=2 style="overflow: hidden scroll; overflow-wrap: break-word;"></textarea></div>'
); );
// Handle changing display of optional answer fields and saving of data // Handle changing display of optional answer fields and saving of data
$("#rapid-option").change(function(evt) { $("#rapid-option").change(function (evt) {
if (evt.target.value == "Abnormal") { if (evt.target.value == "Abnormal") {
$("#rapid-text").css("display", "block"); $("#rapid-text").css("display", "block");
} else { } else {
@@ -376,7 +418,7 @@ function loadQuestion(n, section = 1, force_reload = false) {
}); });
// Save long answers on textchange // Save long answers on textchange
$(".long-answer").change(function(evt) { $(".long-answer").change(function (evt) {
// ignore blank text and delete any stored value // ignore blank text and delete any stored value
if (evt.target.value.length < 1) { if (evt.target.value.length < 1) {
db.answers.delete([cid, eid, qid, "2"]); db.answers.delete([cid, eid, qid, "2"]);
@@ -406,7 +448,7 @@ function loadQuestion(n, section = 1, force_reload = false) {
db.answers db.answers
.get({ cid: cid, eid: eid, qid: qid, qidn: "1" }) .get({ cid: cid, eid: eid, qid: qid, qidn: "1" })
.then(function(answer) { .then(function (answer) {
if (answer != undefined) { if (answer != undefined) {
$("#rapid-option option:contains(" + answer.ans + ")").prop( $("#rapid-option option:contains(" + answer.ans + ")").prop(
"selected", "selected",
@@ -419,20 +461,20 @@ function loadQuestion(n, section = 1, force_reload = false) {
$("#rapid-option-not-answered").remove(); $("#rapid-option-not-answered").remove();
} }
}) })
.catch(function(error) { .catch(function (error) {
console.log("error-", error); console.log("error-", error);
}) })
.then( .then(
db.answers db.answers
.get({ cid: cid, eid: eid, qid: qid, qidn: "2" }) .get({ cid: cid, eid: eid, qid: qid, qidn: "2" })
.then(function(answer) { .then(function (answer) {
if (answer != undefined) { if (answer != undefined) {
console.log(answer); console.log(answer);
$(".long-answer").text(answer.ans); $(".long-answer").text(answer.ans);
} }
markAnswer(qid, "rapid"); markAnswer(qid, "rapid");
}) })
.catch(function(error) { .catch(function (error) {
console.log("error-", error); console.log("error-", error);
}) })
); );
@@ -446,15 +488,15 @@ function loadQuestion(n, section = 1, force_reload = false) {
case "anatomy": { case "anatomy": {
ap.append( ap.append(
'<div class="answer-item" id="anatomy-text"><div class="answer-label-outer"><p class="answer-label-inner"><span class="answer-label-number">' + '<div class="answer-item" id="anatomy-text"><div class="answer-label-outer"><p class="answer-label-inner"><span class="answer-label-number">' +
display_n + display_n +
'.1</span><span style="flex:1">' + '.1</span><span style="flex:1">' +
current_question.question + current_question.question +
'</span><button class="flag" data-qid="' + '</span><button class="flag" data-qid="' +
n + n +
'" data-qidn=1 style="margin-right:0">⚐</button></p></div><textarea class="long-answer" name="Reason" data-answer-section-qidn=1 style="overflow: hidden scroll; overflow-wrap: break-word;"></textarea></div>' '" data-qidn=1 style="margin-right:0">⚐</button></p></div><textarea class="long-answer" name="Reason" data-answer-section-qidn=1 style="overflow: hidden scroll; overflow-wrap: break-word;"></textarea></div>'
); );
$(".long-answer").change(function(evt) { $(".long-answer").change(function (evt) {
// ignore blank text and delete any stored value // ignore blank text and delete any stored value
if (evt.target.value.length < 1) { if (evt.target.value.length < 1) {
db.answers.delete([cid, eid, qid, "1"]); db.answers.delete([cid, eid, qid, "1"]);
@@ -480,13 +522,13 @@ function loadQuestion(n, section = 1, force_reload = false) {
db.answers db.answers
.get({ cid: cid, eid: eid, qid: qid, qidn: "1" }) .get({ cid: cid, eid: eid, qid: qid, qidn: "1" })
.then(function(answer) { .then(function (answer) {
if (answer != undefined) { if (answer != undefined) {
$(".long-answer").text(answer.ans); $(".long-answer").text(answer.ans);
} }
markAnswer(qid, "anatomy"); markAnswer(qid, "anatomy");
}) })
.catch(function(error) { .catch(function (error) {
console.log(error); console.log(error);
}); });
@@ -499,42 +541,42 @@ function loadQuestion(n, section = 1, force_reload = false) {
case "long": { case "long": {
ap.append( ap.append(
'<div class="answer-item"><div class="answer-label-outer"><p class="answer-label-inner"><span class="answer-label-number">' + '<div class="answer-item"><div class="answer-label-outer"><p class="answer-label-inner"><span class="answer-label-number">' +
display_n + display_n +
'.1</span><span style="flex:1">Observations</span><button class="flag" data-qid="' + '.1</span><span style="flex:1">Observations</span><button class="flag" data-qid="' +
n + n +
'" data-qidn=1 style="margin-right:0">⚐</button></p></div><textarea class="long-answer" data-qidn=1 name="Observations" style="overflow-x: hidden; overflow-wrap: break-word; height: 80px;"></textarea></div>' '" data-qidn=1 style="margin-right:0">⚐</button></p></div><textarea class="long-answer" data-qidn=1 name="Observations" style="overflow-x: hidden; overflow-wrap: break-word; height: 80px;"></textarea></div>'
); );
ap.append( ap.append(
'<div class="answer-item"><div class="answer-label-outer"><p class="answer-label-inner"><span class="answer-label-number">' + '<div class="answer-item"><div class="answer-label-outer"><p class="answer-label-inner"><span class="answer-label-number">' +
display_n + display_n +
'.2</span><span style="flex:1">Interpretation</span><button class="flag" data-qid="' + '.2</span><span style="flex:1">Interpretation</span><button class="flag" data-qid="' +
n + n +
'" data-qidn=2 style="margin-right:0">⚐</button></p></div><textarea class="long-answer" data-qidn=2 name="Interpretation" style="overflow-x: hidden; overflow-wrap: break-word; , trueheight: 80px;"></textarea></div>' '" data-qidn=2 style="margin-right:0">⚐</button></p></div><textarea class="long-answer" data-qidn=2 name="Interpretation" style="overflow-x: hidden; overflow-wrap: break-word; , trueheight: 80px;"></textarea></div>'
); );
ap.append( ap.append(
'<div class="answer-item"><div class="answer-label-outer"><p class="answer-label-inner"><span class="answer-label-number">' + '<div class="answer-item"><div class="answer-label-outer"><p class="answer-label-inner"><span class="answer-label-number">' +
display_n + display_n +
'.3</span><span style="flex:1">Principle Diagnosis</span><button class="flag" data-qid="' + '.3</span><span style="flex:1">Principle Diagnosis</span><button class="flag" data-qid="' +
n + n +
'" data-qidn=3 style="margin-right:0">⚐</button></p></div><textarea class="long-answer" data-qidn=3 name="Principle Diagnosis" style="overflow-x: hidden; overflow-wrap: break-word; height: 80px;"></textarea></div>' '" data-qidn=3 style="margin-right:0">⚐</button></p></div><textarea class="long-answer" data-qidn=3 name="Principle Diagnosis" style="overflow-x: hidden; overflow-wrap: break-word; height: 80px;"></textarea></div>'
); );
ap.append( ap.append(
'<div class="answer-item"><div class="answer-label-outer"><p class="answer-label-inner"><span class="answer-label-number">' + '<div class="answer-item"><div class="answer-label-outer"><p class="answer-label-inner"><span class="answer-label-number">' +
display_n + display_n +
'.4</span><span style="flex:1">Differential Diagnosis</span><button class="flag" data-qid="' + '.4</span><span style="flex:1">Differential Diagnosis</span><button class="flag" data-qid="' +
n + n +
'" data-qidn=4 style="margin-right:0">⚐</button></p></div><textarea class="long-answer" data-qidn=4 name="Differential Diagnosis" style="overflow-x: hidden; overflow-wrap: break-word; height: 80px;"></textarea></div>' '" data-qidn=4 style="margin-right:0">⚐</button></p></div><textarea class="long-answer" data-qidn=4 name="Differential Diagnosis" style="overflow-x: hidden; overflow-wrap: break-word; height: 80px;"></textarea></div>'
); );
ap.append( ap.append(
'<div class="answer-item"><div class="answer-label-outer"><p class="answer-label-inner"><span class="answer-label-number">' + '<div class="answer-item"><div class="answer-label-outer"><p class="answer-label-inner"><span class="answer-label-number">' +
display_n + display_n +
'.5</span><span style="flex:1">Management (if appropriate)</span><button class="flag" data-qid="' + '.5</span><span style="flex:1">Management (if appropriate)</span><button class="flag" data-qid="' +
n + n +
'" data-qidn=5 style="margin-right:0">⚐</button></p></div><textarea class="long-answer" data-qidn=5 name="Management (if appropriate)" style="overflow-x: hidden; overflow-wrap: break-word; height: 80px;"></textarea></div>' '" data-qidn=5 style="margin-right:0">⚐</button></p></div><textarea class="long-answer" data-qidn=5 name="Management (if appropriate)" style="overflow-x: hidden; overflow-wrap: break-word; height: 80px;"></textarea></div>'
); );
// Save long answers on textchange // Save long answers on textchange
$(".long-answer").change(function(evt) { $(".long-answer").change(function (evt) {
qidn = evt.target.dataset.qidn.toString(); qidn = evt.target.dataset.qidn.toString();
// ignore blank text and delete any stored value // ignore blank text and delete any stored value
@@ -569,7 +611,7 @@ function loadQuestion(n, section = 1, force_reload = false) {
for (var qidn_count = 1; qidn_count < 6; qidn_count++) { for (var qidn_count = 1; qidn_count < 6; qidn_count++) {
db.answers db.answers
.get({ cid: cid, eid: eid, qid: qid, qidn: qidn_count.toString() }) .get({ cid: cid, eid: eid, qid: qid, qidn: qidn_count.toString() })
.then(function(answer) { .then(function (answer) {
if (answer != undefined) { if (answer != undefined) {
$(".long-answer") $(".long-answer")
.eq(parseInt(answer.qidn) - 1) .eq(parseInt(answer.qidn) - 1)
@@ -577,7 +619,7 @@ function loadQuestion(n, section = 1, force_reload = false) {
} }
//markAnswer(qid, "anatomy"); //markAnswer(qid, "anatomy");
}) })
.catch(function(error) { .catch(function (error) {
console.log(error); console.log(error);
}); });
} }
@@ -599,7 +641,7 @@ function loadQuestion(n, section = 1, force_reload = false) {
function setFocus(section) { function setFocus(section) {
// Horrible (but it works) // Horrible (but it works)
setTimeout(function() { setTimeout(function () {
// In pratique it selects the end of a textarea but I'm not sure if I can be bothered... // In pratique it selects the end of a textarea but I'm not sure if I can be bothered...
$("*[data-answer-section-qidn=" + section + "]").focus(); $("*[data-answer-section-qidn=" + section + "]").focus();
}, 200); }, 200);
@@ -612,16 +654,16 @@ function updateReviewPanel() {
db.answers db.answers
.where({ cid: cid, eid: eid }) .where({ cid: cid, eid: eid })
.toArray() .toArray()
.then(function(answers) { .then(function (answers) {
$(".question-list-panel div") $(".question-list-panel div")
.slice(1) .slice(1)
.attr("class", "question-list-item"); .attr("class", "question-list-item");
answers.forEach(function(answer, n) { answers.forEach(function (answer, n) {
$( $(
"#question-list-item-" + "#question-list-item-" +
question_order.indexOf(answer.qid) + question_order.indexOf(answer.qid) +
"-" + "-" +
answer.qidn answer.qidn
).addClass("question-saved-localdb"); ).addClass("question-saved-localdb");
if (question_type == "rapid" && answer.qidn == "1") { if (question_type == "rapid" && answer.qidn == "1") {
@@ -638,26 +680,26 @@ function updateReviewPanel() {
}); });
//$(".long-answer").text(answer.ans); //$(".long-answer").text(answer.ans);
}) })
.catch(function(error) { .catch(function (error) {
console.log("error - ", error); console.log("error - ", error);
}); });
db.flags db.flags
.where({ cid: cid, eid: eid }) .where({ cid: cid, eid: eid })
.toArray() .toArray()
.then(function(answers) { .then(function (answers) {
answers.forEach(function(answer, n) { answers.forEach(function (answer, n) {
$( $(
"#question-list-item-" + "#question-list-item-" +
question_order.indexOf(answer.qid) + question_order.indexOf(answer.qid) +
"-" + "-" +
answer.qidn + answer.qidn +
" span" " span"
).css("visibility", "visible"); ).css("visibility", "visible");
}); });
//$(".long-answer").text(answer.ans); //$(".long-answer").text(answer.ans);
}) })
.catch(function(error) { .catch(function (error) {
console.log("error - ", error); console.log("error - ", error);
}); });
} }
@@ -672,18 +714,18 @@ function createReviewPanel() {
qn = n - 1; qn = n - 1;
el = $( el = $(
'<div id="question-list-item-' + '<div id="question-list-item-' +
qn + qn +
"-" + "-" +
qidn + qidn +
'" data-qid=' + '" data-qid=' +
qn + qn +
' data-qidn="' + ' data-qidn="' +
qidn + qidn +
'" class="question-list-item">' + '" class="question-list-item">' +
n + n +
"." + "." +
qidn + qidn +
'<span class="question-list-flag">⚑</span></div>' '<span class="question-list-flag">⚑</span></div>'
); );
$(".question-list-panel").append(el); $(".question-list-panel").append(el);
// return the new element so it can be hidden if necessary // return the new element so it can be hidden if necessary
@@ -710,7 +752,7 @@ function createReviewPanel() {
} }
} }
$(".question-list-item").click(function(evt) { $(".question-list-item").click(function (evt) {
loadQuestion($(this).attr("data-qid"), $(this).attr("data-qidn")); loadQuestion($(this).attr("data-qid"), $(this).attr("data-qidn"));
}); });
} }
@@ -989,10 +1031,10 @@ function onImageRendered(e) {
$("option[value=scroll").prop("hidden", false); $("option[value=scroll").prop("hidden", false);
$("option[value=scroll").text( $("option[value=scroll").text(
"scroll (" + "scroll (" +
(stack.currentImageIdIndex + 1) + (stack.currentImageIdIndex + 1) +
"/" + "/" +
stack.imageIds.length + stack.imageIds.length +
")" ")"
); );
// Temp way to enable CT window presets // Temp way to enable CT window presets
@@ -1024,19 +1066,19 @@ function disableFullscreen(dicom_element) {
// Register Key Event Listener // Register Key Event Listener
window.addEventListener("keydown", keydown_handler); window.addEventListener("keydown", keydown_handler);
$("#submit-button").click(function(evt) { $("#submit-button").click(function (evt) {
submitAnswers(); submitAnswers();
}); });
$("#review-button").click(function(evt) { $("#review-button").click(function (evt) {
$(".question-list-panel").toggle(); $(".question-list-panel").toggle();
}); });
$("#options-button").click(function(evt) { $("#options-button").click(function (evt) {
$("#options-panel").toggle(); $("#options-panel").toggle();
}); });
$("#review-overlay-button").click(function(evt) { $("#review-overlay-button").click(function (evt) {
if (review == true) { if (review == true) {
reviewQuestions(); reviewQuestions();
} else { } else {
@@ -1044,21 +1086,21 @@ $("#review-overlay-button").click(function(evt) {
} }
}); });
$("#finish-exam").click(function(evt) { $("#finish-exam").click(function (evt) {
review = true; review = true;
reviewQuestions(); reviewQuestions();
$.modal.close(); $.modal.close();
}); });
$("#finish-cancel").click(function(evt) { $("#finish-cancel").click(function (evt) {
$.modal.close(); $.modal.close();
}); });
$("#overlay-close").click(function(evt) { $("#overlay-close").click(function (evt) {
$("#options-panel").hide(); $("#options-panel").hide();
}); });
$("#review-overlay-close").click(function(evt) { $("#review-overlay-close").click(function (evt) {
$("#review-overlay").hide(); $("#review-overlay").hide();
}); });
@@ -1130,9 +1172,9 @@ function reviewQuestions() {
db.answers db.answers
.where({ cid: cid, eid: eid }) .where({ cid: cid, eid: eid })
.toArray() .toArray()
.then(function(answers) { .then(function (answers) {
current_answers = {}; current_answers = {};
answers.forEach(function(arr, n) { answers.forEach(function (arr, n) {
answer = arr["ans"]; answer = arr["ans"];
if (answer == undefined) { if (answer == undefined) {
answer = "Not answered"; answer = "Not answered";
@@ -1142,23 +1184,23 @@ function reviewQuestions() {
}); });
correct_count = 0; correct_count = 0;
question_order.forEach(function(qid, n) { question_order.forEach(function (qid, n) {
$("#review-answer-list").append( $("#review-answer-list").append(
"<li id='review-answer-" + "<li id='review-answer-" +
qid + qid +
"'><a href='#' data-qid=" + "'><a href='#' data-qid=" +
n + n +
">Question " + ">Question " +
(n + 1) + (n + 1) +
":</a> <span>Not answered</span></li>" ":</a> <span>Not answered</span></li>"
); );
$("#review-answer-list a").click(function(evt) { $("#review-answer-list a").click(function (evt) {
loadQuestion(this.dataset.qid); loadQuestion(this.dataset.qid);
$("#review-overlay").hide(); $("#review-overlay").hide();
}); });
db.user_answers db.user_answers
.get({ qid: qid }) .get({ qid: qid })
.then(function(answers) { .then(function (answers) {
question_answers = questions[qid]["answers"]; question_answers = questions[qid]["answers"];
if (answers == undefined) { if (answers == undefined) {
} else { } else {
@@ -1193,20 +1235,20 @@ function reviewQuestions() {
if (normal) { if (normal) {
el.html( el.html(
"<span class='" + "<span class='" +
c + c +
"'>Answer: " + "'>Answer: " +
user_answer + user_answer +
" (Normal)</span>" " (Normal)</span>"
); );
} else { } else {
el.html( el.html(
"<span class='" + "<span class='" +
c + c +
"'>Answer: " + "'>Answer: " +
user_answer + user_answer +
" (Abnormal: " + " (Abnormal: " +
question_answers.join(", ") + question_answers.join(", ") +
")</span>" ")</span>"
); );
} }
} }
@@ -1278,12 +1320,12 @@ function reviewQuestions() {
"Score: " + correct_count + " out of " + question_order.length "Score: " + correct_count + " out of " + question_order.length
); );
}) })
.catch(function(error) { .catch(function (error) {
console.log("error-", error); console.log("error-", error);
}); });
}); });
}) })
.catch(function(error) { .catch(function (error) {
console.log("error - ", error); console.log("error - ", error);
}); });
} }
@@ -1324,9 +1366,9 @@ function markAnswer(qid, type) {
db.user_answers db.user_answers
.get({ qid: qid }) .get({ qid: qid })
.then(function(answers) { .then(function (answers) {
if (answers != undefined) { if (answers != undefined) {
answers.ans.forEach(function(answer, n) { answers.ans.forEach(function (answer, n) {
ul.append("<li>" + answer + "</li>"); ul.append("<li>" + answer + "</li>");
if (compareString(answer, user_answer)) { if (compareString(answer, user_answer)) {
textarea.removeClass("incorrect").addClass("correct"); textarea.removeClass("incorrect").addClass("correct");
@@ -1334,7 +1376,7 @@ function markAnswer(qid, type) {
}); });
} }
current_question.answers.forEach(function(answer, n) { current_question.answers.forEach(function (answer, n) {
ul.append("<li>" + answer + "</li>"); ul.append("<li>" + answer + "</li>");
if (compareString(answer, user_answer)) { if (compareString(answer, user_answer)) {
textarea.removeClass("incorrect").addClass("correct"); textarea.removeClass("incorrect").addClass("correct");
@@ -1351,7 +1393,7 @@ function markAnswer(qid, type) {
if (allow_self_marking) { if (allow_self_marking) {
$(".answer-panel").append( $(".answer-panel").append(
$("<button id='mark-correct'>Mark Correct</button>").click( $("<button id='mark-correct'>Mark Correct</button>").click(
function() { function () {
markCorrect(qid, user_answer); markCorrect(qid, user_answer);
} }
) )
@@ -1360,7 +1402,7 @@ function markAnswer(qid, type) {
} }
} }
}) })
.catch(function(error) { .catch(function (error) {
console.log("error-", error); console.log("error-", error);
}); });
addFeedback(); addFeedback();
@@ -1375,8 +1417,8 @@ function addFeedback() {
$(".answer-panel").append( $(".answer-panel").append(
$( $(
"<div class='feedback'><h4>Feedback</h4>" + "<div class='feedback'><h4>Feedback</h4>" +
current_question.feedback + current_question.feedback +
"</div>" "</div>"
) )
); );
} }
@@ -1389,7 +1431,7 @@ function markCorrect(qid, user_answer) {
db.user_answers db.user_answers
.get({ qid: qid }) .get({ qid: qid })
.then(function(answers) { .then(function (answers) {
if (answers == undefined) { if (answers == undefined) {
new_answers = []; new_answers = [];
} else { } else {
@@ -1399,7 +1441,7 @@ function markCorrect(qid, user_answer) {
new_answers.push(user_answer); new_answers.push(user_answer);
db.user_answers.put({ qid: qid, ans: new_answers }); db.user_answers.put({ qid: qid, ans: new_answers });
}) })
.catch(function(error) { .catch(function (error) {
console.log("error-", error); console.log("error-", error);
}); });
@@ -1426,7 +1468,7 @@ function answerInArray(arr, ans) {
function addFlagEvents() { function addFlagEvents() {
// Bind flag change events // Bind flag change events
$("button.flag").click(function(event) { $("button.flag").click(function (event) {
el = $(this); el = $(this);
nqid = el.attr("data-qid"); nqid = el.attr("data-qid");
qid = question_order[nqid]; qid = question_order[nqid];
@@ -1454,24 +1496,24 @@ function addFlagEvents() {
function loadFlagsFromDb(n) { function loadFlagsFromDb(n) {
db.flags db.flags
.get({ cid: cid, eid: eid, qid: qid, qidn: n }) .get({ cid: cid, eid: eid, qid: qid, qidn: n })
.then(function(answer) { .then(function (answer) {
if (answer != undefined) { if (answer != undefined) {
$("button.flag, button.flag-selected") $("button.flag, button.flag-selected")
.eq(parseInt(answer.qidn) - 1) .eq(parseInt(answer.qidn) - 1)
.toggleClass("flag flag-selected"); .toggleClass("flag flag-selected");
} }
}) })
.catch(function(error) { .catch(function (error) {
console.log(error); console.log(error);
}); });
} }
function urltoFile(url, filename, mimeType) { function urltoFile(url, filename, mimeType) {
return fetch(url) return fetch(url)
.then(function(res) { .then(function (res) {
return res.arrayBuffer(); return res.arrayBuffer();
}) })
.then(function(buf) { .then(function (buf) {
return new File([buf], filename, { type: mimeType }); return new File([buf], filename, { type: mimeType });
}); });
} }
@@ -1506,7 +1548,7 @@ function loadMainImage(image, stack) {
element.scrollIntoView(false); element.scrollIntoView(false);
//element.scrollTo(0); //element.scrollTo(0);
$(element).dblclick(function() { $(element).dblclick(function () {
if ($(".canvas-panel").length == 0) { if ($(".canvas-panel").length == 0) {
// already fullscreen (disable it) // already fullscreen (disable it)
disableFullscreen(this); disableFullscreen(this);
@@ -1549,12 +1591,11 @@ function showLoginDialog() {
$("#login-dialog").modal(); $("#login-dialog").modal();
} }
$("#start-exam-button").click(function(evt) { $("#start-exam-button").click(function (evt) {
cid = parseInt($("#candidate-number").val()); cid = parseInt($("#candidate-number").val());
$.modal.close(); $.modal.close();
}); });
showLoginDialog();
function manualPanDicom(x, y) { function manualPanDicom(x, y) {
dicom_element = document.getElementById("dicom-image"); dicom_element = document.getElementById("dicom-image");