/**
* Program: models.js
* @date 8/11/2020
* @author Stephan K Eisenbarth
* Organization: VA CART
* Bleeding Risk: Colin O'Donnell
* Syntax Scrore: Thomas Glorioso
* 30-Day Mortality: Colin O'Donnell
* CIN: Sharon E. Davis
* Description: JavaScript file containing call functions and variables for the various CART predicitve models (Bleeding Risk, Syntax Score, 30-Day Mortality)
*/
/* QUICK SEARCH - Used to jump to specific area of this file
GENERALCODE Basic variabls and functions code Area
WEBLOADCODE Webpage loading code Area
BLEEDRISKCODE Bleeding Risk Model JavaScript code Area
VASYNTAXCODE VA Syntax Score Model JavaScript code Area
30DAYMORTALITYCODE 30-Day Mortality Model JavaScript code Area
CINCODE CIN Model Javascript code area
*/
/*=============================================================================================================
============================================ WEB PAGE CODE ===================================================
=============================================================================================================*/
// GENERALCODE
var currModel = "bleeding_Area"; // Current model being displayed
var e = 2.71828; // Specified value of e for calculations
var prevModel = null; // Previous model that needs a field calculated from a different model
var updateInput = null; // Previous model field that needs to be updated by a calculation from from a different model
// 2D String array containing the different model information (index 0 = String containing the model top tab button DOM ID, 1 = String DOM element ID containing the specific model's inputs, 2 = boolean flag for whether the specific model's input form has been changed by user [true] or not [false], 3 = String containing the parent result DOM ID, 4 = String containing the DOM ID used to display the specific model resultsm 5 = boolean flag whether to show results for model [true] for not [false])
var modelTrgtArr = {
bleeding_Area: {modelBtn: "bleedingBtn", inputArea: "bleeding_Area", parResArea: "procComplicaArea", modelResArea: "resultsArea_bleedingRisk", hasInputChange: false, showResults: false},
syntax_Area: {modelBtn: "syntaxBtn", inputArea: "syntax_Area", parResArea: "procMortalArea", modelResArea: "resultsArea_syntax", hasInputChange: false, showResults: false},
mortality_Area: {modelBtn: "mortalityBtn", inputArea: "mortality_Area", parResArea: "procMortalArea", modelResArea: "resultsArea_mortalityArea", hasInputChange: false, showResults: false} ,
cin_Area: {modelBtn: "cinBtn", inputArea: "cin_Area", parResArea: "procMortalArea", modelResArea: "resultsArea_cinArea", hasInputChange: false, showResults: false}
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 3/12/2020
* Description: Used by the top tab model option buttons. Changes the displayed CART model by hiding all other models but the selected one
* @param trgt String containing the ID of the model changing button that was clicked
*/
function gotoModel (trgt) {
if (trgt != null) {
prevModel = null;
updateInput = null;
changeModel (trgt);
}
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 3/12/2020
* Description: Changes the displayed CART model by hiding all other models but the selected
* @param trgt String containing the ID of the model changing button that was clicked
*/
function changeModel (trgt) {
if (trgt != null) {
hideResultsArea ();
showModelInputAreas (true);
if (trgt == "bleedingBtn" || trgt == "bleeding_Area") {
// Bleeding Risk - show input area
if (prevModel != null) {
document.getElementById ("calcBRBtn").value="Calculate Bleeding Risk";
}
else {
document.getElementById ("calcBRBtn").value="Calculate Model(s)";
}
document.getElementById ("typeOModelArea").innerHTML = "VA CART Bleeding Risk Calculator";
currModel = "bleeding_Area";
}
if (trgt == "syntaxBtn" || trgt == "syntax_Area") {
// Syntax - show input area
if (prevModel != null) {
document.getElementById ("calcBRBtn").value="Calculate VA Syntax Score";
}
else {
document.getElementById ("calcBRBtn").value="Calculate Model(s)";
}
document.getElementById ("typeOModelArea").innerHTML = "VA Syntax Score";
currModel = "syntax_Area";
}
if (trgt == "mortalityBtn" || trgt == "mortality_Area") {
// 30 Day Mortality After PCI Risk - show input area
if (prevModel != null) {
document.getElementById ("calcBRBtn").value="Calculate Mortality Model";
}
else {
document.getElementById ("calcBRBtn").value="Calculate Model(s)";
}
document.getElementById ("typeOModelArea").innerHTML = "VA Mortality Model";
currModel = "mortality_Area";
if (check4UserChanges ("syntax_Area") == true) {
var tmpArr = processForm_Syntax ();
if (tmpArr != null && tmpArr.length > 0 && tmpArr [0] != null) {
var totVal = 0
if (tmpArr.length > 1) {
for (var i = 0; i < tmpArr.length; i++) {
totVal += tmpArr [i];
}
}
else if (tmpArr.length == 1) {
totVal = tmpArr [0];
}
getParElement ("mortality_Area", "syntaxScoreFld").value = totVal;
}
}
}
if (trgt == "cinBtn" || trgt == "cin_Area") {
// CIN - show input area
if (prevModel != null) {
document.getElementById ("calcBRBtn").value="Calculate CIN Model";
}
else {
document.getElementById ("calcBRBtn").value="Calculate Model(s)";
}
document.getElementById ("typeOModelArea").innerHTML = "VA Nephropathy Model";
currModel = "cin_Area";
if (check4UserChanges ("syntax_Area") == true) {
var tmpArr = processForm_Syntax ();
if (tmpArr != null && tmpArr.length > 0 && tmpArr [0] != null) {
var totVal = 0
if (tmpArr.length > 1) {
for (var i = 0; i < tmpArr.length; i++) {
totVal += tmpArr [i];
}
}
else if (tmpArr.length == 1) {
totVal = tmpArr [0];
}
getParElement ("mortality_Area", "syntaxScoreFld").value = totVal;
}
}
}
updateNavButtonStyle (trgt);
focusFirstInput();
// Change all show results flags to false
for (key in modelTrgtArr) {
modelTrgtArr [key]["showResults"] = false;
}
}
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 3/12/2020
* Description: Changes current model to the next model in order
*/
function nextModel () {
if (currModel == "bleeding_Area") {
changeModel (modelTrgtArr ["syntax_Area"]["modelBtn"]);
}
else if (currModel == "syntax_Area") {
changeModel (modelTrgtArr ["mortality_Area"]["modelBtn"]);
}
else if (currModel == "mortality_Area") {
changeModel (modelTrgtArr ["cin_Area"]["modelBtn"]);
}
else if (currModel == "cin_Area") {
changeModel (modelTrgtArr ["bleeding_Area"]["modelBtn"]);
}
prevModel = null;
updateInput = null;
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 10/12/2022
* Description: Changes the look and feel of navigation buttons based on the specified String target
* @param trgt String containing the ID of the model container or the model navigation button to change button style for
*/
function updateNavButtonStyle (trgt) {
var btn = null;
for (key in modelTrgtArr) {
btn = document.getElementById (modelTrgtArr [key]["modelBtn"]);
if (trgt == modelTrgtArr [key]["modelBtn"] || trgt == modelTrgtArr [key]["inputArea"]) {
document.getElementById (modelTrgtArr [key]["inputArea"]).style.display="block";
btn.style.borderBottom = "solid 2px";
btn.style.borderLeft = "solid 2px";
btn.style.fontWeight = "bold";
}
else {
document.getElementById (modelTrgtArr [key]["inputArea"]).style.display="none";
btn.style.border = "solid 1px";
btn.style.fontWeight = "normal";
}
}
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 10/12/2022
* Description: Changes the cursor focus to the first input of the current model's input form
*/
function focusFirstInput () {
if (isEmpty (currModel) == false) {
var par = document.getElementById (currModel);
if (currModel == "bleeding_Area") {
if (check4UserChanges("bleeding_Area") == false) {
par.querySelector ("#heightFld").focus ();
}
}
else if (currModel == "syntax_Area") {
if (check4UserChanges("syntax_Area") == false) {
par.querySelector ("#corDomin").focus ();
}
}
else if (currModel == "mortality_Area") {
if (check4UserChanges("mortality_Area") == false) {
par.querySelector ("#ageFld").focus ();
}
}
else if (currModel == "cin_Area") {
if (check4UserChanges("cin_Area") == false) {
par.querySelector ("#ageFld").focus ();
}
}
}
else {
document.getElementById ("bleeding_Area").querySelector ("#heightFld").focus ();
}
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 3/12/2020
* Description: Returns boolean flag for whether any items have user specified content in the specified String container
* @param trgt String containing the ID of the model container to check if inputs have user specified content
*/
function check4UserChanges (trgt) {
var isC = false;
if (trgt != null) {
var x = document.getElementById (trgt);
if (x != null) {
var tmpArr = x.querySelectorAll ('input, select');
if (tmpArr != null && tmpArr.length > 0) {
for (var i = 0; i < tmpArr.length; i++) {
if (tmpArr [i].type === 'checkbox' && tmpArr [i].checked == true) {
isC = true;
i = tmpArr.length;
}
else if (tmpArr [i].type == 'text' && isEmpty (tmpArr [i].value) == false) {
isC = true;
i = tmpArr.length;
}
else if (tmpArr [i].type == 'select-one' && isEmpty (tmpArr [i].value) == false) {
isC = true;
i = tmpArr.length;
}
}
}
}
}
return isC;
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 11/21/2019
* Description: Processes the current form
*/
function processForm () {
var didP = false;
var modelCnt = 0;
if (modelTrgtArr ["bleeding_Area"]["hasInputChange"] == true) {
if (check4UserChanges ("bleeding_Area") == true) {
if (currModel == "bleeding_Area" || prevModel == null) {
var tmpArr = processForm_BleedingRisk (modelTrgtArr["bleeding_Area"]["inputArea"]);
if (tmpArr != null && tmpArr.length > 0 && tmpArr [0] != null) {
if (prevModel != null && updateInput != null) {
getParElement (prevModel, updateInput).value = tmpArr [0];
getParElement (prevModel, updateInput).focus ();
}
didP = true;
// Change the model's results view flag to true
modelTrgtArr ["bleeding_Area"]["showResults"] = true;
}
else {
didP = false;
}
}
modelCnt ++;
}
}
else if (modelTrgtArr ["bleeding_Area"]["hasInputChange"] == false && currModel == "bleeding_Area") {
if (confirm ("Bleeding Risk Model inputs have not been changed so model's calculation will be skipped") == false) {
gotoModel (currModel);
didP = false;
modelCnt ++;
}
}
var x = document.getElementById ("rightPane");
var rowCnt = x.getElementsByTagName ("table") [0].rows;
if ((didP == true || modelCnt == 0) && modelTrgtArr ["syntax_Area"]["hasInputChange"] == true) {
if (check4UserChanges ("syntax_Area") == true || rowCnt.length > 1) {
if (currModel == "syntax_Area" || prevModel == null) {
var tmpArr = processForm_Syntax ();
if (tmpArr != null && tmpArr.length > 0 && tmpArr [0] != null) {
if (prevModel != null && updateInput != null) {
var totVal = 0
if (tmpArr.length > 1) {
for (var i = 0; i < tmpArr.length; i++) {
totVal += tmpArr [i];
}
}
else if (tmpArr.length == 1) {
// Change the model's results view flag to true
totVal = tmpArr [0];
}
getParElement (prevModel, updateInput).value = totVal;
getParElement (prevModel, updateInput).focus ();
}
didP = true;
// Change the model's results view flag to true
modelTrgtArr ["syntax_Area"]["showResults"] = true;
}
else {
didP = false;
}
}
modelCnt ++;
}
}
else if (modelTrgtArr ["syntax_Area"]["hasInputChange"] == false && currModel == "syntax_Area") {
if (confirm ("VA Syntax Model inputs have not been changed so model's calculation will be skipped") == false) {
gotoModel (currModel);
didP = false;
modelCnt ++;
}
}
if ((didP == true || modelCnt == 0) && modelTrgtArr ["mortality_Area"]["hasInputChange"] == true) {
if (check4UserChanges ("mortality_Area") == true) {
if (currModel == "mortality_Area" || prevModel == null) {
var tmpArr = processForm_30DayMortalityRiskPCI (modelTrgtArr["mortality_Area"]["inputArea"]);
if (tmpArr != null && tmpArr.length > 0 && tmpArr [0] != null) {
if (prevModel != null && updateInput != null) {
getParElement (prevModel, updateInput).value = tmpArr [0];
getParElement (prevModel, updateInput).focus ();
}
didP = true;
// Change the model's results view flag to true
modelTrgtArr ["mortality_Area"]["showResults"] = true;
}
else {
didP = false;
}
}
modelCnt ++;
}
}
else if (modelTrgtArr ["mortality_Area"]["hasInputChange"] == false && currModel == "mortality_Area") {
if (confirm("VA Mortality Model inputs have not been changed so model's calculation will be skipped") == false) {
gotoModel (currModel);
didP = false;
modelCnt ++;
}
}
if ((didP == true || modelCnt == 0) && modelTrgtArr ["cin_Area"]["hasInputChange"] == true) {
if (check4UserChanges ("cin_Area") == true) {
if (currModel == "cin_Area" || prevModel == null) {
var tmpArr = processForm_CIN (modelTrgtArr["cin_Area"]["inputArea"]);
if (tmpArr != null && tmpArr.length > 0 && tmpArr [0] != null) {
if (prevModel != null && updateInput != null) {
getParElement (prevModel, updateInput).value = tmpArr [0];
getParElement (prevModel, updateInput).focus ();
}
didP = true;
// Change the model's results view flag to true
modelTrgtArr ["cin_Area"]["showResults"] = true;
}
else {
didP = false;
}
}
modelCnt ++;
}
}
else if (modelTrgtArr ["cin_Area"]["hasInputChange"] == false && currModel == "cin_Area") {
if (confirm("VA CIN Model inputs have not been changed so model's calculation will be skipped") == false) {
gotoModel (currModel);
didP = false;
modelCnt ++;
}
}
if (modelCnt == 0) {
// None of the model forms are filled out
alert ("None of the model forms have been filled out. Nothing to calculate.");
focusFirstInput ();
}
else if (didP == true) {
if (prevModel != null || updateInput != null) {
changeModel (prevModel);
}
else {
document.body.scrollTop = document.documentElement.scrollTop = 0;
showModelInputAreas (false);
document.getElementById ("calcBRBtn").value="Calculate Model(s)";
document.getElementById ("back2ModelsBtn").style.display = "inline";
// Display results area(s)
for (key in modelTrgtArr) {
if (modelTrgtArr [key]["showResults"] == true) {
document.getElementById (modelTrgtArr [key]["parResArea"]).style.display = "inline";
document.getElementById (modelTrgtArr [key]["modelResArea"]).style.display = "inline";
}
}
prevModel = null;
updateInput = null;
}
}
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 3/19/2018
* Description: Performs process if the Enter keyboard key was pressed, if so run calculation
* @param e event driving this keyboard check
*/
function check4Enter (e) {
if(e.keyCode == 13) {
// Enter keyboard key being pressed
processForm ();
return false;
}
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 5/15/2019
* Description: Fades outs (or hides over time) the hint notification box
* @param elemID String containing the element ID to fade in or out
*/
function fadeElementOut (elemID) {
var op = 1; // initial opacity
document.getElementById (elemID).style.opacity = 1;
document.getElementById (elemID).style.filter = "alpha(opacity=100)";
var timer = setInterval(function () {
if (op <= 0.1){
clearInterval(timer);
document.getElementById(elemID).style.display = "none";
}
document.getElementById (elemID).style.opacity = op;
document.getElementById (elemID).style.filter = "alpha(opacity=" + op * 100 + ")";
op -= op * 0.1;
}, 20);
}
/**
* @author Stephan K Eisenbarth
* @date 10/12/2022
* Description: Hides or shows the model inputs and calculate button based on the specified boolean flag
* @param shldHide boolean flag for whether to show the model input areas (true) or hide them (false)
*/
function showModelInputAreas (shldShow) {
var dspStyle = "inline";
if (shldShow == false) {
dspStyle = "none";
}
document.getElementById ("modAreas").style.display = dspStyle;
document.getElementById ("calcBRBtn").style.display = dspStyle;
document.getElementById ("nxtModBtn").style.display = dspStyle;
}
/**
* @author Stephan K Eisenbarth
* @date 10/12/2022
* Description: Hides the results area based on the specified boolean flag
*/
function hideResultsArea () {
for (key in modelTrgtArr) {
document.getElementById (modelTrgtArr [key]["parResArea"]).style.display = "none";
document.getElementById (modelTrgtArr [key]["modelResArea"]).style.display = "none";
}
document.getElementById ("back2ModelsBtn").style.display = "none";
document.body.scrollTop = document.documentElement.scrollTop = 0;
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 10/12/2022
* Description: Changes the view to show the model selections and model inputs
*/
function back2Models () {
changeModel (currModel);
}
/*=============================================================================================================
============================================ GENERAL CODE ==================================================
=============================================================================================================*/
/**
* @author Stephan K Eisenbarth
* @date 4/30/2018
* Description: Ensure that age value is valid
* @param min integer containing the minimum age allowed
* @param max integer containing the maximum age allowed
* @return ok boolean flag for whether the age is valid (true) or not (false)
*/
function checkVal_Age (min, max) {
var ok = true;
var x = getElementFromCurrModel ("ageFld");
if (x != null && isEmpty (x.value) == false) {
var tmpOut = null;
if (isInteger (x.value)) {
if (x.value < min) {
tmpOut = "Invalid age entry, value cannot be less " + min + " (years of age)";
}
else if (x.value > max) {
tmpOut = "Invalid age entry, value cannot be over " + max + " (years of age)";
}
}
else {
tmpOut = "Invalid age entry, value must be a whole number (without decimal)";
}
if (tmpOut != null) {
ok = false;
alert (tmpOut);
x.focus ();
x.select();
}
}
return ok;
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 4/30/2018
* Description: Returns boolean flag for whether the Height value is valid
* @return ok boolean flag for whether the is valid (true) or not (false)
*/
function checkVal_Height () {
var ok = true;
var x = getElementFromCurrModel ("heightFld");
if (x != null && isEmpty (x.value) == false) {
var tmpOut = null;
if (isInteger (x.value)) {
if (x.value < 48) {
tmpOut = "Invalid Height entry, value cannot be less 48 (inches)";
}
else if (x.value > 84) {
tmpOut = "Invalid Height entry, value cannot be over 84 (inches)";
}
}
else {
tmpOut = "Invalid Height entry, value must be a whole number (without decimal)";
}
if (tmpOut != null) {
ok = false;
alert (tmpOut);
x.focus ();
x.select();
}
}
return ok;
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 4/30/2018
* Description: Returns boolean flag for whether the Height value is valid
* @return ok boolean flag for whether the is valid (true) or not (false)
*/
function checkVal_Weight () {
var ok = true;
var x = getElementFromCurrModel ("weightLbsFld");
if (x != null && isEmpty (x.value) == false) {
var tmpOut = null;
if (isInteger (x.value)) {
if (x.value < 73) {
tmpOut = "Invalid Weight entry, value cannot be less 73 (pounds)";
}
else if (x.value > 400) {
tmpOut = "Invalid Weight entry, value cannot be over 400 (pounds)";
}
}
else {
tmpOut = "Invalid Weight entry, value must be a whole number (without decimal)";
}
if (tmpOut != null) {
ok = false;
alert (tmpOut);
x.focus ();
x.select();
}
}
return ok;
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 4/30/2018
* Description: Returns boolean flag for whether the Hemoglobin value is valid
* @return ok boolean flag for whether the is valid (true) or not (false)
*/
function checkVal_Hemoglobin () {
var ok = true;
var x = getElementFromCurrModel ("HgBFld");
if (x != null && isEmpty (x.value) == false) {
var tmpOut = null;
if (isDouble (x.value)) {
if (x.value < 2.7) {
tmpOut = "Invalid Hemoglobin entry, value cannot be less 2.7 (g/dl)";
}
else if (x.value > 22) {
tmpOut = "Invalid Hemoglobin entry, value cannot be over 22 (g/dl)";
}
}
else {
tmpOut = "Invalid Hemoglobin entry, value must be a number (with or without decimal)";
}
if (tmpOut != null) {
ok = false;
alert (tmpOut);
x.focus ();
x.select();
}
}
return ok;
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 4/30/2018
* Description: Returns boolean flag for whether INR value is valid
* @return ok boolean flag for whether the is valid (true) or not (false)
*/
function checkVal_INR () {
var ok = true;
var x = getElementFromCurrModel ("inrFld");
if (x != null && isEmpty (x.value) == false) {
var tmpOut = null;
if (isDouble (x.value)) {
if (x.value < 0.7) {
tmpOut = "Invalid INR entry, value cannot be less 0.7";
}
else if (x.value > 18.0) {
tmpOut = "Inv alid INR entry, value cannot be over 18.0";
}
}
else {
tmpOut = "Invalid INR entry, value must be a number (with or without decimal)";
}
if (tmpOut != null) {
ok = false;
alert (tmpOut);
x.focus ();
x.select();
}
}
return ok;
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 4/30/2018
* Description: Returns boolean flag for whether the Troponin value is valid
* @return ok boolean flag for whether the is valid (true) or not (false)
*/
function checkVal_Troponin () {
var ok = true;
var x = getElementFromCurrModel ("troponinFld");
if (x != null && isEmpty (x.value) == false) {
var tmpOut = null;
if (isDouble (x.value)) {
if (x.value < 0) {
tmpOut = "Invalid Troponin entry, value cannot be less 0 (ng/ml)";
}
else if (x.value > 991) {
tmpOut = "Invalid Troponin entry, value cannot be over 991 (ng/ml)";
}
}
else {
tmpOut = "Invalid Troponin entry, value must be a number (with or without decimal)";
}
if (tmpOut != null) {
ok = false;
alert (tmpOut);
x.focus ();
x.select();
}
}
return ok;
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 3/14/2018
* Description: Returns a double containing the BSA (body suface area) value, based on the specified int height (in inches) and int weight (in pounds)
* @param heightInInches int containing the height in inches
* @param weightInLbls int containing the weight in pounds
* @return outBSA Double containing the calculated value based on the specified int height (in inches) and int weight (in pounds)
*/
function getBSA (heightInInches, weightInLbls) {
var outBSA = -1;
if (heightInInches > -1) {
if (weightInLbls > -1) {
var wghtComp = parseInt(weightInLbls)/2.2046;
wghtComp = Math.pow(wghtComp, 0.425);
var hghtComp = parseInt(heightInInches)*2.54;
hghtComp = Math.pow(hghtComp, 0.725);
outBSA = 0.007184 *(wghtComp*hghtComp);
}
}
return outBSA;
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 12/3/2019
* Description: Returns an int containing the selected height in inches (combining feet and inches into one value)
* @return outHeight int containing the selected height in inches (combining feet and inches into one value)
*/
function getHeightInInches () {
var outHeight = -1;
var x = getElementFromCurrModel ("feetMenu");
if (x == null || isEmpty (x.value) == true) {
alert ("Height in feet cannot be empty");
x.focus ();
}
else {
var y = document.getElementById ("inchesMenu");
if (y == null || isEmpty (y.value) == true) {
alert ("Height in inches cannot be empty");
y.focus ();
}
else {
outHeight = (parseInt (x.value)*12) + (parseInt (y.value));
}
}
return outHeight;
}
/**
* @author Stephan K Eisenbarth
* @date 3/14/2018
* Description: returns the BMI (body mass index) value, as a Double, based on the specified int height (in inches) and int weight (in pounds)
* @param heightInInches int containing the height in inches
* @param weightElem DOM object containing the weight of person (in pounds)
* @return outBMI Double containing the calculated value based on the specified int height (in inches) and int weight (in pounds)
*/
function getBMI (heightInInches, weightElem) {
var outBMI = -1;
if (heightInInches > -1) {
if (weightElem.value == "") {
alert ("Weight (in pounds) cannot be empty");
weightElem.focus ();
}
else {
outBMI = 703 *(weightElem/(heightInInches*heightInInches));
}
}
return outBMI;
}
/**
* @author Stephan K Eisenbarth
* @date 3/14/2018
* Description: returns the MACD 2021 version contrast dosage based on the specified Weight in kilograms and Serum Creatinine
* @param weightKG Double containing the weight in kilograms
* @param serumCreatin Double containing the Serum Creatinine
* @return outMACD Double containing the calculated MACD 2021 version contrast dose based on the specified Weight in kilograms and Serum Creatinine
*/
function getMACD2021 (weightKG, serumCreatin) {
var outMACD = -1;
if (weightKG != null) {
if (serumCreatin != null) {
if (weightKG > -1) {
if (serumCreatin > -1) {
outMACD = 2.5*weightKG/serumCreatin;
}
else {
alert ("Serum Creatinine must be a positive number");
}
}
else {
alert ("Weight (in pounds) must be a positive number");
}
}
else {
alert ("Serum Creatinine cannot be empty");
}
}
else {
alert ("Weight (in pounds) cannot be empty");
}
return outMACD;
}
/**
* @author Stephan K Eisenbarth
* @date 3/14/2018
* Description: returns the estimated glomerular filtration rate (eGFR)
* @param weightKG Double containing the weight in kilograms
* @param serumCreatin Double containing the Serum Creatinine
* @param isFemale boolean flag for whether the patient is female (true) or male (false)
* @param age int containing the age in years of the patient
* @return outeGFR Double containing the calculated eGFR
*/
function get_eGFR (serumCreatin, isFemale, age) {
var outeGFR = -1;
if (serumCreatin != null) {
if (isFemale != null) {
if (age != null) {
if (typeof isFemale == "string") {
if (isFemale.toLowerCase() == "female" || isFemale.toLowerCase() == "fem" || isFemale.toLowerCase() == "f" || isFemale.toLowerCase() == "t" || isFemale.toLowerCase() == "true" || isFemale.toLowerCase() == "yes" || isFemale.toLowerCase() == "y") {
isFemale = true;
}
else {
isFemale = false;
}
}
var k = 0.9;
var alpha = -0.411;
var femMod = 1;
if (isFemale == true) {
k = 0.7;
alpha = -0.329;
femMod = 1.018;
}
outeGFR = 141*Math.pow(Math.min(serumCreatin/k, 1), alpha)*Math.pow(Math.max(serumCreatin/k, 1), -1.209)*Math.pow(0.993, age)*femMod;
}
else {
alert ("Age cannot be empty");
}
}
else {
alert ("Is female cannot be empty");
}
}
else {
alert ("Serum Creatinine cannot be empty");
}
return outeGFR;
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 4/30/2018
* Description: Ensures only one status checkbox can be checked (all others will be unchecked)
* @param trgtID String containing the element ID that is checked (so all others are unchecked)
*/
function checkStatusVal (trgtID) {
var elemArr = document.getElementById ("statusDiv").getElementsByTagName("input");
for (var i = 0; i < elemArr.length; i++) {
if (elemArr [i].type == 'checkbox' && elemArr [i].id != trgtID) {
elemArr [i].checked = false;
changeCheckMark (elemArr [i].id);
}
}
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 4/30/2018
* Description: Ensures only one status checkbox can be checked (all others will be unchecked)
* @param trgtID String containing the element ID that is checked (so all others are unchecked)
*/
function checkIndicationVal (trgtID) {
var elemArr = document.getElementById ("indicationDiv").getElementsByTagName("input");
for (var i = 0; i < elemArr.length; i++) {
if (elemArr [i].type == 'checkbox' && elemArr [i].id != trgtID) {
elemArr [i].checked = false;
changeCheckMark (elemArr [i].id);
}
}
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 3/14/2018
* Description: Changes whether the YES OR NO check mark is visible or hidden based on the checkbox being checked or not
* @param trgt String containing the ID of the checkbox associated with the YES and NO check marks
*/
function changeCheckMark (trgt) {
if (getElementFromCurrModel (trgt).checked == true) {
getElementFromCurrModel (trgt + '_YES').style.visibility ='visible';
getElementFromCurrModel (trgt + '_NO').style.visibility ='hidden';
}
else {
getElementFromCurrModel (trgt + '_YES').style.visibility ='hidden';
getElementFromCurrModel (trgt + '_NO').style.visibility ='visible';
}
updateSimilarInput (getElementFromCurrModel (trgt));
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 3/14/2018
* Description: Changes whether the YES OR NO check mark is visible or hidden based on the checkbox being checked or not
* @param trgt String containing the ID of the checkbox associated with the YES and NO check marks
*/
function changeCheckMarkOtherModel (trgtModel, trgt) {
if (getParElement (trgtModel, trgt).checked == true) {
getParElement (trgtModel, trgt + '_YES').style.visibility ='visible';
getParElement (trgtModel, trgt + '_NO').style.visibility ='hidden';
}
else {
getParElement (trgtModel, trgt + '_YES').style.visibility ='hidden';
getParElement (trgtModel, trgt + '_NO').style.visibility ='visible';
}
}
/**
* @author Stephan K Eisenbarth
* @date 3/14/2018
* Description: Removes white space from the start and end of the specified String
* @param trgt String to remove white space from start and end
* @return outVal String containing the specified target String with all white space remove from the start and end
*/
function trimWhtSpc (trgt) {
var outVal = null;
if (trgt != null) {
outVal = trgt;
while (outVal.charAt (0) == " " || outVal.substring (0,1) == "\n" || outVal.substring (0,1) == "\t") {
if (outVal.charAt (0) == " ") {
outVal = outVal.substring (1, outVal.length);
}
else if (outVal.substring (0,1) == "\n") {
outVal = outVal.substring (2, outVal.length);
}
else if (outVal.substring (0,1) == "\t") {
outVal = outVal.substring (2, outVal.length);
}
}
while (outVal.charAt (outVal.length - 1) == " " || outVal.substring (outVal.length - 1) == "\n" || outVal.substring (outVal.length - 1) == "\t") {
if (outVal.charAt (outVal.length - 1) == " " || outVal.charAt (outVal.length - 1) == " ") {
outVal = outVal.substring (0, outVal.length - 1);
}
else if (outVal.substring (outVal.length - 1) == "\n") {
outVal = outVal.substring (0, outVal.length - 2);
}
else if (outVal.substring (outVal.length - 1) == "\t") {
outVal = outVal.substring (0, outVal.length - 2);
}
}
}
return outVal;
// return trgt.replace(/^\s+|\s+$/gm,'');
}
/**
* @author Stephan K Eisenbarth
* @date 7/17/2019
* Description: Replaces all occurances of the specified target string from the specified value string with the specified String
* @param val String to replace text within (what String is having things replaced within)
* @param trgt String to be found and be replaced
* @param rep String to replace targeted text
* @return outStr String containing the specified String trgt replaced with the specified String rep value in the specified String val
*/
function replaceAll (val, trgt, rep) {
var outStr = val;
if (val != null && trgt != null) {
if (val.length >= trgt.length) {
if (val.indexOf (trgt) > -1) {
var i =0;
var strt = 0;
var end = 0;
var tmpStr = val;
while (i < val.length) {
strt = tmpStr.indexOf (trgt);
end = strt + trgt.length;
if (strt == 0) {
tmpStr = tmpStr.substring (0 + trgt.length) + rep;
}
else if (strt > -1){
tmpStr = tmpStr.substring (0, strt) + rep + tmpStr.substring (end);
}
i = i + trgt.length;
}
outStr = tmpStr;
}
}
}
return outStr;
}
/**
* Display Function...
* @author Stephan K Eisenbarth
* @date 3/14/2018
* Description: Displays the contents of the specified Array to the internet browser console (for debugging)
* @param trgt String containing the array object to display contents of
*/
function dspArr (trgt) {
if (trgt != null && trgt.length > 0) {
var outStr = "";
for (var i = 0; i < trgt.length; i++) {
outStr += "[" + i + "]->" + trgt [i] + "\n";
}
console.log (outStr);
}
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 12/2/2019
* Description: Returns an array containing the reuslts of Matrix multiplication of the 2 specified arrays
* @param arr1 String array containing the first array to multiply to the second array
* @param arr2 String array containing the second array to multiply to the first array
* @return outArr Array of doubles containing the matrix multiplication of the 2 specified arrays
*/
function runMatrixMultiplication (arr1, arr2) {
var outArr = null;
var res = "";
if (arr1 != null && arr1[0] != null && arr2 != null && arr2[0] != null ) {
// Check if first array is larger in size then second array, if so swap them
if (arr1.length > arr2.length && isArray (arr2[0]) == false) {
var tmpArr = arr2;
arr2 = arr1;
arr1 = tmpArr;
}
else if (arr1.length > arr2.length && isArray (arr1[0]) == true && isArray (arr2[0]) == true && arr1.length == arr2[0].length) {
var tmpArr = arr2;
arr2 = arr1;
arr1 = tmpArr;
}
else if (arr1.length == arr2.length && isArray (arr1[0]) == true && isArray (arr2[0]) == false) {
if (arr1[0].length > arr2.length) {
var tmpArr = arr2;
arr2 = arr1;
arr1 = tmpArr;
}
else if (arr1[0].length ==1) {
var tmpArr = arr2;
arr2 = arr1;
arr1 = tmpArr;
}
}
else if (arr1.length < arr2.length && isArray (arr1[0]) == true && isArray (arr2[0]) == false && arr1[0].length == arr2.length) {
var tmpArr = arr2;
arr2 = arr1;
arr1 = tmpArr;
}
var tmpOut = 0.0;
var finalStr = "";
if (isArray (arr1 [0]) == false && isArray(arr2 [0]) == false) {
// Both arrays are single dimensions single dimension array * single dimension array
if (arr1.length == arr2.length) {
for (var i = 0; i < arr1.length; i++) {
tmpOut += parseFloat(arr1 [i]) * parseFloat(arr2 [i]);
finalStr += "," + tmpOut;
}
finalStr = "[" + finalStr.substring (1) + "]";
res += finalStr;
}
else if (arr1.length == 1 && arr2 != null && arr2[0] != null && isArray(arr2 [0]) == false) {
for (var i = 0; i < arr2.length; i++) {
tmpOut += parseFloat(arr1 [0]) * parseFloat(arr2 [i]);
finalStr += "," + tmpOut;
}
finalStr = "[" + finalStr.substring (1) + "]";
res += finalStr;
}
}
else if (isArray(arr1 [0]) == false && isArray(arr2 [0]) == true) {
// First array is single dimension array * 2D array
if (arr1.length == arr2.length) {
// 2nd array is a 2D array but has only 1 item per row
if (arr2[0].length == 1) {
for (var i = 0; i < arr1.length; i++) {
tmpOut += parseFloat(arr1 [i]) * parseFloat(arr2 [i][0]);
}
res += "[" + tmpOut + "]";
}
else {
var ok = true;
var cnt = 0;
var arr2Cnt = 0;
while (ok == true) {
cnt = 0;
tmpOut = parseFloat(arr1 [cnt ++]) * parseFloat(arr2 [0][arr2Cnt]);
for (var x = 1; x < arr2.length; x++) {
tmpOut += parseFloat(arr1 [cnt ++]) * parseFloat(arr2 [x][arr2Cnt]);
}
tmpOut = tmpOut.toFixed (10);
finalStr += "," + tmpOut;
arr2Cnt ++;
if (arr2Cnt >= arr2.length) {
ok = false;
}
}
finalStr = "[" + finalStr.substring (1) + "]";
res += finalStr;
}
}
else if (arr1.length == 1 && arr2 != null && arr2[0] != null && isArray(arr2 [0]) == true) {
var tmpFinalStr = "";
for (var i = 0; i < arr2.length; i++) {
tmpFinalStr = "";
for (var x = 0; x < arr2.length; x++) {
tmpOut = parseFloat(arr1 [0]) * parseFloat(arr2 [i][x]);
tmpFinalStr += "," + tmpOut;
}
finalStr += "[" + tmpFinalStr.substring (1) + "]";
}
finalStr = "[" + finalStr + "]";
res += finalStr;
}
}
else if (isArray(arr1 [0]) == true && isArray(arr2 [0]) == true) {
// Both arrays are 2D array * 2D array
if (arr1[0].length == arr2.length) {
var cnt = 0;
var tmpOut = 0;
var tmpRes = "";
for (var i = 0; i < arr1.length; i++) {
cnt = 0;
finalStr = "";
while (cnt < arr2[0].length) {
tmpOut = 0;
for (var x = 0; x < arr2.length; x ++) {
tmpOut += parseFloat(arr1 [i][x]) * parseFloat(arr2 [x][cnt]);
}
finalStr += "," + tmpOut;
cnt ++
}
tmpRes += ",[" + finalStr.substring (1) + "]";
}
res += "[" + tmpRes.substring (1) + "]";
}
}
}
outArr = (res.substring (1, res.length - 1)).split (",");
return outArr;
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 11/22/2019
* Description: Returns a float containing the upper confiendence level given the calculated risk and the final result of calculated risk
* @param tmpCALC Calculated modifyer array and covariate array
* @param tmpStndrdErr Calculated final results for the standard error
* @return CALC_UL float containing the upper confiendence level given the calculated risk and the final result of calculated risk
*/
function getUpperConfidenceLevel (tmpCALC, tmpStndrdErr) {
var CALC_UL = 0.0;
var tmpUL = tmpCALC + 1.96 * tmpStndrdErr;
CALC_UL = Math.pow (e, tmpUL)/(1+Math.pow (e, tmpUL));
return CALC_UL;
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 11/22/2019
* Description: Returns a float containing the lower confiendence level given the calculated risk and the final result of calculated risk
* @param tmpCALC Calculated modifyer array and covariate array
* @param tmpStndrdErr Calculated final results for the standard error
* @return CALC_LL float containing the lower confiendence level given the calculated risk and the final result of calculated risk
*/
function getLowerConfidenceLevel (tmpCALC, tmpStndrdErr) {
var CALC_LL = 0.0;
var tmpLL = tmpCALC - 1.96 * tmpStndrdErr;
CALC_LL = Math.pow (e, tmpLL)/(1+Math.pow (e, tmpLL));
return CALC_LL;
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 3/18/2021
* Description: Returns the DOM element from the specified String parent container using the specified String child ID
* @param parID String containing the DOM element parent container ID
* @param elemID String containing the DOM element to get from the specified String parent container ID
* @return outElem DOM object to get
*/
function getParElement (parID, elemID) {
var outElem = null;
if (isEmpty (parID) == false) {
if (isEmpty (elemID) == false) {
var outElem = null;
var elms = document.getElementById(parID).getElementsByTagName("*");
for (var i = 0; i < elms.length; i++) {
if (elms[i].id === elemID) {
outElem = elms[i];
i = elms.length;
}
}
}
}
return outElem;
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 3/18/2021
* Description: returns the DOM input specified by the String element ID from the current model's form
* @param elem DOM element to find matching elements
*/
function getElementFromCurrModel (elemID) {
var outElem = null;
outElem = getParElement (currModel, elemID);
return outElem;
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 10/20/2022
* Description: Returns the specific String target ID DOM element from the specified String parent form ID
* @param parFormID String containing the parent form that contains the target DOM element to return
* @param trgtID String containing the DOM element, from the specified String parent form ID, to be returned
*/
function getElemInput (parFormID, trgtID) {
var outElem = null;
if (isEmpty (parFormID) == false) {
if (isEmpty (trgtID) == false) {
outElem = document.forms[parFormID][trgtID];
}
}
return outElem;
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 3/18/2021
* Description: Sets all input type objects within all models to the same value as the specified DOM object
* @param elem DOM element to find matching elements
*/
function updateSimilarInput (elem) {
if (elem != null) {
var cMade = false;
for (key in modelTrgtArr) {
cMade = false;
if (currModel != modelTrgtArr [key]["inputArea"]) {
var x = getParElement (modelTrgtArr [key]["inputArea"], elem.id);
if (x != null) {
if (elem.type && elem.type === 'checkbox') {
x.checked = elem.checked;
changeCheckMarkOtherModel (modelTrgtArr [key]["inputArea"], x.id);
}
else {
x.value = elem.value;
}
cMade = true
}
if (cMade == true) {
// Verify change actually updated a field not emptied it
if (x.type && x.type === 'checkbox' && x.checked == true) {
cMade = true;
}
else if (isEmpty (x.value) == false) {
cMade = true;
}
else {
cMade = false;
}
}
}
modelTrgtArr [currModel]["hasInputChange"] = true;
}
}
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 12/10/2019
* Description: Changes the current model to a different specified String needed model ID to collect the new model's calculation to populate the specified target input String ID
* @param neededModel String containing the model that a value is needed from
* @param neededModel String containing the model that a value is needed from
*/
function getValueFromModel (neededModel, trgtInput) {
if (isEmpty (neededModel) == false) {
if (isEmpty (trgtInput) == false) {
prevModel = currModel;
updateInput = trgtInput;
changeModel (neededModel);
}
}
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 12/10/2019
* Description: Shows specific hint based on the specified DOM object
* @param elemID String containing the DOM object's ID that called the hint to be shown
*/
function showHint (elemID, parID) {
if (isEmpty (elemID) == false) {
// Change style of the individual Hint display area
var bodyRect = document.body.getBoundingClientRect();
// var elemRect = document.getElementById (elemID).getBoundingClientRect();
var elem = getParElement (parID, elemID);
if (elem != null) {
var elemRect = elem.getBoundingClientRect();
var outStr = null;
if (elemID == "hintBtn_statusMenu") {
outStr = "PCI Status" +
"
" +
"Indicate the status of the diagnostic catheterization at the time the operator decides to perform the catheterization.";
}
else if (elemID == "hintBtn_indicaMenu") {
outStr = "Indication" +
"
" +
"Primary indication for the procedure (if none then select Other).";
}
else if (elemID == "hintBtn_CGS") {
outStr = "Cardiogenic Shock (CGS)" +
"
" +
"The value of this field is used to determine if the patient has been in a state of cardiogenic shock within 24 hours of the procedure.";
}
else if (elemID == "hintBtn_PAD") {
outStr = "Peripheral Artery Disease (PAD)" +
"
" +
"The presence of concomitant peripheral artery disease, including disease of the subclavian, femoral or upper and lower extremity vasculature.";
}
else if (elemID == "hintBtn_AFIB") {
outStr = "AFIB" +
"
" +
"Indicate if the patient has been diagnosed with atrial fibrillation, a cardiac arrhythmia arising from the atrium with a rate >300 bpm and irregularly irregular ventricular response in the presence of conduction.";
}
else if (elemID == "hintBtn_CKD") {
outStr = "Chronic Kidney Disease (CKD)" +
"
" +
"The value of this field is used to determine if the patient has ever had Renal Insufficiency at the time this assessment was performed.";
}
else if (elemID == "hintBtn_HgBFld") {
outStr = "Hemoglobin" +
"
" +
"The amount of hemoglobin, a protein inside red blood cells that carries oxygen from the lungs to tissues and organs in the body and carries carbon dioxide back to the lungs, observed immediately prior to the procedure.";
}
else if (elemID == "hintBtn_inrFld") {
outStr = "International Normalized Ratio (INR)" +
"
" +
"INR ratio observed immediately prior to the procedure. Found using the results of the prothrombin time (PT) test. This measures the time it takes for your blood to clot. INR is an international standard for the PT.";
}
else if (elemID == "hintBtn_troponinFld") {
outStr = "Troponin" +
"
" +
"The troponin value observed immediately prior to the procedure.";
}
else if (elemID == "hintBtn_PriorCABG") {
outStr = "Previous Coronary Artery Bypass Graft (CABG)" +
"
" +
"The value of this field is used to determine if the patient has ever had a Coronary Artery Bypass Graft (CABG) at the time this assessment was performed.";
}
else if (elemID == "hintBtn_COPD") {
outStr = "Chronic Obstructive Pulmonary Disease (COPD)" +
"
" +
"The value of this field is used to determine if the patient has ever had Chronic Lung Disease at the time this assessment was performed.";
}
else if (elemID == "hintBtn_PriorValvDz") {
outStr = "Prior Valve Intervention" +
"
" +
"Indicate if the patient had a previous surgical replacement and/or repair of a cardiac valve. Note that this also include percutaneous valve procedures and valvuloplasty.";
}
else if (elemID == "hintBtn_PriorCHF") {
outStr = "Prior Congestive Heart Failure (CHF)" +
"
" +
"The value of this field is used to determine if the patient has ever been diagnosed with Heart Failure (HF) at the time this assessment was performed.";
}
else if (elemID == "hintBtn_PriorStroke_TIA") {
outStr = "Transient Ischemic Attack" +
"
" +
"A temporary period of symptoms like those of a stroke. A TIA usually lasts only a few minutes and doesn't cause permanent damage.";
}
else if (elemID == "hintBtn_syntaxFld") {
outStr = "VA Syntax Score" +
"
" +
"An anatomical scoring system for coronary artery disease complexity adapted from the SYNTAX score and validated for VA patients.";
}
if (isEmpty (outStr) == false) {
document.getElementById ("hintTxtArea").innerHTML = outStr;
}
document.getElementById("hintArea").style.display = "block";
document.getElementById("hintArea").style.top = elemRect.top - 30;
document.getElementById("hintArea").style.left = elemRect.left - bodyRect.left + 20;
document.getElementById("hintArea").style.opacity = 1;
document.getElementById("hintArea").style.filter = "alpha(opacity=100)";
}
}
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 7/17/2019
* Description: Returns boolean for whether the specified String is empty or not
* @trgt String to check if it is empty or not
* @return isE boolean for whether the specified String is empty or not
*/
function isEmpty (trgt) {
var isE = true;
if (trgt != null && trgt != "" && trgt != "" && trgt != "NULL" && (trimWhtSpc (trgt)).length > 0) {
isE = false;
}
return isE;
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 3/14/2018
* Description: Returns boolean flag for whether the specified String is an integer (no decimal) or not
* @param trgt String containing the value to check if it is an integer or not
* @return isI boolean flag for whether the specified String is an integer (no decimal) or not
*/
function isInteger (trgt) {
var isI = false;
if (isEmpty (trgt) == false) {
var pattern =/^\d+$/;
isI = pattern.test(trgt);
}
return isI;
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 3/14/2018
* Description: Returns boolean flag if the specific DOM object's value is an integer
* @param trgt DOM object's value is an integer
*/
function valInteger (trgt) {
if (trgt != null && isEmpty (trgt.value) == false) {
if (isInteger (trgt.value) == false) {
alert ("Invalid entry, field requires a positive whole number (no decimals)");
trgt.focus();
}
}
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 3/14/2018
* Description: Returns boolean flag for whether the specified String is a double (can contain decimal) or not
* @param trgt String containing the value to check if it is a double or not
* @return isD boolean flag for whether the specified String is a double (can contain decimal) or not
*/
function isDouble (trgt) {
var isD = false;
if (trgt != null) {
var reg = new RegExp(/^\d+\.?\d*$|^\d*\.?\d+$/);
isD = reg.test(trgt);
}
return isD;
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 3/14/2018
* Description: Returns boolean flag if the specific DOM object's value is a double (can contain a decimal)
* @param trgt DOM object's value is a double (can contain a decimal)
*/
function valDouble (trgt) {
if (trgt != null && isEmpty (trgt.value) == false) {
if (isDouble (trgt.value) == false) {
alert ("Invalid entry, field requires a positive number that can have decimals");
trgt.focus();
}
}
}
/**
* Accessor Function...
* @author Stephan K Eisenbarth
* @date 3/14/2018
* Description: Returns boolean flag for whether specified item is an array object or not
* @param trgt Object to check if it is an array object or not
* @return boolean flag for whether specified target object is an array or not
*/
function isArray (trgt) {
return Object.prototype.toString.call(trgt) === '[object Array]';
}
/**
* Display function...
* @author Stephan K Eisenbarth
* @date 1/15/2020
* Description: Breaks up the specified large console.log (or console.debug) print statement into multiple console outputs (to get around Internet Explorer's max number of bytes per console display)
* @author Stephan K Eisenbarth
*/
function showBigDebug (trgtStr) {
if (trgtStr != null && trgtStr != "") {
var arr = trgtStr.split ("\n");
if (arr != null) {
for (var x = 0; x < arr.length; x ++) {
console.log (arr [x]);
}
}
}
}
/********************************************************************************************
************************************ WEBPAGE LOADING *************************************
********************************************************************************************/
//
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 4/7/2020
* Description: Performs text based processing on the specified String
* @param procStr String containing the model values to process
* Example: models.html?cartversion=V4+%20(4.5.01h)&model=syntax&version=1.0&syntaxscore=14.5
* cartversion => the version number of CART application calling this webpage
* model => the specific model being called by CART application
* version => specific model version CART application is trying to show
* syntaxscore => Value (or score) to display for the model
*/
function processTextBased (procStr) {
if (isEmpty (procStr) == false) {
var procArr = null;
if (procStr.indexOf ("&") > -1) {
// More than 1 model included in text based command
procArr = procStr.split ("&");
}
else {
procArr = [procStr];
}
var urlType = null;
textValsArr = null;
for (var i = 0; i < procArr.length; i++) {
if ((procArr [i].toLowerCase ()).indexOf ("cartversion") == 0) {
// CART Application version information
var verInfo = procArr [i].substring (procArr [i].indexOf ("=") + 1, procArr [i].length);
document.getElementById ("cartAppVerArea").innerHTML = "CART App: " + replaceAll(verInfo, "%20", " ");
document.getElementById ("cartAppVerArea").style.display="block";
}
else if ((procArr [i].toLowerCase ()).indexOf ("model") == 0) {
var verInfo = procArr [i].substring (procArr [i].indexOf ("=") + 1, procArr [i].length);
document.getElementById ("cartAppVerArea").innerHTML += "
Model: " + replaceAll(verInfo, "%20", " ");
urlType = verInfo.replace ("%20", "");
}
else if ((procArr [i].toLowerCase ()).indexOf ("version") == 0) {
var verInfo = procArr [i].substring (procArr [i].indexOf ("=") + 1, procArr [i].length);
document.getElementById ("cartAppVerArea").innerHTML += " " + replaceAll(verInfo, "%20", " ");
}
else if (isEmpty (urlType) == false) {
procArr [i] = procArr [i].substring (procArr [i].indexOf ("=") + 1, procArr [i].length);
if (isEmpty (procArr [i]) == false) {
document.getElementById ("modAreas").style.display="none";
textValsArr = procArr [i].split (",");
if (urlType.toLowerCase () == "syntax") {
if (textValsArr.length == 1) {
console.log ("Show syntax");
showResults_syntax (textValsArr);
}
else if (textValsArr.length > 1) {
}
document.getElementById ("procMortalArea").style.display="inline";
document.getElementById ("resultsArea_syntax").style.display="inline";
}
else if (urlType.toLowerCase () == "bleeding") {
if (textValsArr.length == 1) {
showResults_bleeding (textValsArr);
}
else if (textValsArr.length > 1) {
setBleedingInputs (parFormID, textValsArr);
calcBleedRisk (parFormID);
}
document.getElementById ("procComplicaArea").style.display="inline";
document.getElementById ("resultsArea_bleedingRisk").style.display="inline";
}
document.getElementById ("btnArea").style.display="none";
document.getElementById ("btnNote").style.display="none";
document.getElementById ("topTabs").style.display="none";
}
}
}
}
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 3/14/2018
* Description: Clears the contents of all input fields
*/
function clearForm () {
var x = document.getElementById ("modAreas");
var tmpArr = x.querySelectorAll ('input, select');
if (tmpArr != null && tmpArr.length > 0) {
for (var i = 0; i < tmpArr.length; i++) {
if (tmpArr [i].type == 'checkbox') {
tmpArr [i].checked = false;
}
else if (tmpArr [i].type == 'text') {
tmpArr [i].value="";
}
else if (tmpArr [i].type == 'select-one') {
tmpArr [i].value="NULL";
}
}
}
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 3/14/2018
* Description: Adds test values to the GUI form on page loading
*/
function setGUITestVals () {
if (currModel == "bleeding_Area") {
document.getElementById ("heightFld").value="67";
document.getElementById ("weightLbsFld").value="142";
document.getElementById ("HgBFld").value="10.7";
document.getElementById ("inrFld").value="1.1";
document.getElementById ("troponinFld").value="0";
document.getElementById ("statusMenu").value="emergent";
document.getElementById ("indicaMenu").value="STEMI";
document.getElementById ("CKD").checked=true;
}
else if (currModel == "syntax_Area") {
var inputs = document.getElementsByTagName ("select");
if (inputs != null && inputs.length > 0) {
// Skip first item as that is drop down menu asking about dominance
var strtVal = 50;
var newVal = strtVal;
for (var i = 1; i < inputs.length; i ++) {
inputs [i].value = newVal;
if (newVal < 101) {
newVal += 3;
}
else {
inputs [i].value = "100";
newVal = strtVal;
}
}
}
}
else if (currModel == "mortality_Area") {
document.getElementById ("statusMenu").value="elective";
document.getElementById ("CGS").checked=false;
document.getElementById ("syntaxScoreFld").value="3.0910425";
document.getElementById ("HgBFld").value="13.1";
document.getElementById ("CHF").checked=true;
document.getElementById ("ageFld").value="66";
document.getElementById ("PriorCABG").checked=false;
document.getElementById ("inrFld").value="0.33647224";
document.getElementById ("COPD").checked=false;
document.getElementById ("indicaMenu").value="NSTEMI";
document.getElementById ("PriorValvDz").checked=true;
document.getElementById ("heightFld").value="59";
document.getElementById ("weightLbsFld").value="105";
document.getElementById ("AFIB").checked=false;
document.getElementById ("CKD").checked=false;
}
}
/**
* Modifier Function...
* @author Stephan K Eisenbarth
* @date 3/14/2018
* Description: Performs processes on the web page loading
* @param type String for what type of startup to show (empty = normal GUI, 'TEST' = math test no GUI, 'GUITEST' = GUI based test)
*/
function startup (type) {
if (type == "TEST") {
// Perform testing on the math, no GUI user input
runTestData_bleeding ();
showResults_syntax ([20]);
}
else if (type == "CIN") {
setCINTest ();
}
else {
var queryString = window.location.search;
if (isEmpty (queryString) == false) {
// Variables were passed to the webpage in the URL
if (queryString.toLowerCase() == "?goto=bleeding") {
// Show the Bleeding Risk Model webpage onload
changeModel ("bleedingBtn");
}
else if (queryString.toLowerCase() == "?goto=syntax") {
// Show the Syntax Score Model webpage onload
changeModel ("syntaxBtn");
}
else if (queryString.toLowerCase() == "?goto=mortality") {
// Show the 30 Day Mortality After PCI Risk Model webpage onload
changeModel ("mortalityBtn");
}
else if (queryString.toLowerCase() == "?goto=cin") {
// Show the 30 Day Mortality After PCI Risk Model webpage onload
changeModel ("cinBtn");
}
else if (queryString.substring (0,1) == "?") {
// Parameter values used to populate a specific model's input fields
queryString = queryString.substring (1);
processTextBased (trimWhtSpc (queryString));
}
}
else {
changeModel ("bleedingBtn");
clearForm ();
}
}
}