From 036298f87f7a9e43ab0ee61fa21d215c78b45f0a Mon Sep 17 00:00:00 2001 From: Stef van Buuren Date: Tue, 19 Mar 2024 22:51:28 +0100 Subject: [PATCH 01/26] Refactor start.js --- inst/www/js/start.js | 599 ++++++++++++++++++++----------------------- 1 file changed, 285 insertions(+), 314 deletions(-) diff --git a/inst/www/js/start.js b/inst/www/js/start.js index 763f2e3..e35ed32 100644 --- a/inst/www/js/start.js +++ b/inst/www/js/start.js @@ -1,352 +1,323 @@ // start.js -const localapp = false; -const urlParams = new URLSearchParams(window.location.search); -const user_txt = urlParams.get('txt'); -const user_session = urlParams.get('session'); -const user_chartcode = urlParams.get('chartcode'); -const protocol = window.location.protocol; -const hostname = window.location.hostname; -const host = protocol + '//' + hostname; -const pathname = window.location.pathname.slice(0,-5); - -// This path is used by javascript calls into OpenCPU -// Use double // to support CORS -if (localapp) -{ - ocpu.seturl("../R"); -} else { - ocpu.seturl('//' + hostname + pathname + '/ocpu/library/james/R'); -} -// internal constants -const slider_values = { - "0_2": ["0w","4w","8w","3m","4m","6m","7.5m","9m","11m","14m","18m","24m"], - "0_4": ["0w","4w","8w","3m","4m","6m","7.5m","9m","11m","14m","18m","24m","36m","45m"], - "0_19": ["0w","3m","6m","12m","24m","5y","9y","10y","11y","14y","19y"], - "0_29": ["0w","3m","6m","14m","24m","48m","10y","18y"], - "matches": ["0", "1", "2", "5", "10", "25", "50", "100"]}; - -// starting defaults for initialisation per child -var slider_list = "0_2"; -var chartcode = "NJAH"; -document.getElementById("donordata").value = "0-2"; - -// Fire up sliders -$("#weekslider").ionRangeSlider({ - type: "single", - skin: "round", - grid_snap: true, - min: 25, - max: 36, - from: 36, - step: 1, - onFinish: function (data) { - update(); - } -}); -$("#matchslider").ionRangeSlider({ - type: "single", - skin: "round", - grid_snap: true, - from: 0, - values: slider_values[["matches"]], - onFinish: function (data) { - update(); - } -}); -$("#visitslider").ionRangeSlider({ - type: "double", - skin: "round", - grid_snap: true, - min_interval: 0, - drag_interval: true, - values: slider_values[[slider_list]], - onFinish: function (data) { - update(); - } +// Constants for OpenCPU server configuration based on environment +const isSingleUser = false; +const urlParams = new URLSearchParams(window.location.search); +const { protocol, hostname, pathname } = window.location; +const host = `${protocol}//${hostname}`; +const basePath = pathname.slice(0, -5); // Assuming removal of ".html" + +// Extract URL parameters with fallbacks to handle null or undefined +const userText = urlParams.get('txt') || ''; +const userSession = urlParams.get('session') || ''; +const userChartcode = urlParams.get('chartcode') || ''; + +// Set the OpenCPU server URL +ocpu.seturl(isSingleUser ? "../R" : `//${hostname}${basePath}/ocpu/library/james/R`); + +// Slider values configuration +const sliderValues = { + "0_2": ["0w", "4w", "8w", "3m", "4m", "6m", "7.5m", "9m", "11m", "14m", "18m", "24m"], + "0_4": ["0w", "4w", "8w", "3m", "4m", "6m", "7.5m", "9m", "11m", "14m", "18m", "24m", "36m", "45m"], + "0_19": ["0w", "3m", "6m", "12m", "24m", "5y", "9y", "10y", "11y", "14y", "19y"], + "0_29": ["0w", "3m", "6m", "14m", "24m", "48m", "10y", "18y"], + "matches": ["0", "1", "2", "5", "10", "25", "50", "100"] +}; + +let sliderList = "0_2"; +let chartcode = "NJAH"; +$("#donordata").val("0-2"); + +// Slider initialization with shared settings +const initializeSlider = (selector, settings) => { + $(selector).ionRangeSlider({ + type: settings.type || "single", // Default type if not specified + skin: "round", + grid_snap: true, + ...settings, + onFinish: update + }); +}; + +initializeSlider("#weekslider", { min: 25, max: 36, from: 36, step: 1 }); +initializeSlider("#matchslider", { values: sliderValues.matches }); +initializeSlider("#visitslider", { type: "double", min_interval: 0, drag_interval: true, values: sliderValues[sliderList] }); + +// Accordion page activation +let active = "groei"; +["#groei", "#ontwikkeling"].forEach(id => { + $(id).click(() => { + if (active !== id.substring(1)) { + active = id.substring(1); + update(); + } + }); }); -$("#weekslider_dsc").ionRangeSlider({ - type: "single", - skin: "round", - grid_snap: true, - min: 25, - max: 36, - from: 36, - step: 1, - onFinish: function (data) { - update(); + +// Change listeners for UI controls +const addChangeListener = (elementId) => { + document.getElementById(elementId).addEventListener('change', update, false); +}; + +addChangeListener('chartgrp'); +addChangeListener('chartgrp_dsc'); + +// Simplified event attachment for radio buttons +["agegrp", "msr", "etnicity", "sex", "agegrp_dsc"].forEach(formName => { + const radios = document.forms[formName].elements[formName]; // Assuming 'elements[formName]' is correct; might need adjustment based on actual HTML structure + for (let radio of radios) { + radio.onclick = update; } }); -// set active accordion page -var active = "groei"; -$('#groei').click(function (){ - if (active != "groei"){ - active = "groei"; - update(); - } - }); +// Selector logic +let selector = userChartcode ? "chartcode" : (userText || userSession) ? "data" : "derive"; -$('#ontwikkeling').click(function (){ - if (active != "ontwikkeling"){ - active = "ontwikkeling"; - update(); - } - }); +// Initialize chart controls or update based on user input +(userText || userSession || userChartcode) ? initializeChartControls() : update(); -// set onchange triggers -var chartgrplist = document.getElementById('chartgrp'); -chartgrplist.addEventListener('change', update, false); +// Definitions for 'initializeChartControls', 'updateSliders', 'updateWeekSlider', 'setEthnicity', and related functions remain the same as provided, ensuring they follow similar consistency and style practices. -var chartgrplist_dsc = document.getElementById('chartgrp_dsc'); -chartgrplist_dsc.addEventListener('change', update, false); -var radios = document.forms.agegrp.elements.agegrp; -for(var i = 0, max = radios.length; i < max; i++) { - radios[i].onclick = function() { - update(); - }; -} +// start.js -var radios = document.forms.msr.elements.msr; -for(var i = 0, max = radios.length; i < max; i++) { - radios[i].onclick = function() { - update(); - }; -} -var radios = document.forms.etnicity.elements.etnicity; - for(var i = 0, max = radios.length; i < max; i++) { - radios[i].onclick = function() { - update(); - }; -} +// Destructure window.location for concise access to needed properties. +const { protocol, hostname, pathname } = window.location; -var radios = document.forms.sex.elements.sex; - for(var i = 0, max = radios.length; i < max; i++) { - radios[i].onclick = function() { - update(); - }; -} +// Construct host URL using template literals for clarity and conciseness. +const host = `${protocol}//${hostname}`; -var radios = document.forms.agegrp_dsc.elements.agegrp_dsc; -for(var i = 0, max = radios.length; i < max; i++) { - radios[i].onclick = function() { - update(); - }; -} +// Remove ".html" from the pathname. +const basePath = pathname.slice(0, -5); -// if user_session is specified, report any warnings and messages -//if (user_session) { -// var warn = host + pathname + '/' + user_session + "/warnings/text"; -// var mess = host + pathname + '/' + user_session + "/messages/text"; -// $("#session").text(user_session); -// $("#warnings").load(warn); -// $("#messages").load(mess); -//} - -// updating logic to select charts -// 1. use "derive" based on user interaction -var selector = "derive"; -// 2. use "data" if we can calculate or load child data -if (user_txt || user_session) selector = "data"; -// 3. use hard chartcode if user specified one -if (user_chartcode) selector = "chartcode"; - -// calculate chartcode, set chart controls, update visibility, draw chart -if (user_txt || user_session || user_chartcode) initialize_chart_controls(); -// no user arguments: update visibility, draw chart -else update(); -// update(); - -function initialize_chart_controls() { - // function executes at initialization - // convert_tgt_chartadvice() obtains useful statistics from - // the uploaded individual data (R) from user_loc and - // from user_chartcode - - // handle null user inputs - var utxt = ''; - var uses = ''; - var ucode = ''; - if (typeof user_txt !== "undefined" && user_txt !== null) utxt = user_txt; - if (typeof user_session !== "undefined" && user_session !== null) uses = user_session; - if (typeof user_chartcode !== "undefined" && user_chartcode !== null) ucode = user_chartcode; - - var rq1 = ocpu.call("convert_tgt_chartadvice", { - txt : utxt, - session : uses, - chartcode : ucode, - selector : selector - }, function(session) { - - //retrieve the returned object async - session.getObject(function(output){ - //output is the object returned by the R function - - // alert user to invalid chartcode - if (!output.chartcode) { - alert("Unknown chartcode: " + user_chartcode); - return; - } +// Set the OpenCPU server URL based on the environment. +ocpu.seturl(isSingleUser ? "../R" : `//${hostname}${pathname}/ocpu/library/james/R`); - // set accordion menus according to return vector - showCards(String(output.accordion)); - // set UI elements according to return vector - if (String(output.side) === "dsc") { - document.getElementById("chartgrp_dsc").value = String(output.chartgrp); - } else { - document.getElementById("chartgrp").value = String(output.chartgrp); - document.forms.msr[String(output.side)].checked=true; - } - document.forms.agegrp[String(output.agegrp)].checked=true; - if (String(output.agegrp) !== "1-21y") {document.forms.agegrp_dsc[String(output.agegrp)].checked=true;} - - var week = String(output.week); - var weeknum = Math.trunc(Number(week)); - - // set week slider for both growth and development - if (week && weeknum >= 25 && weeknum <= 36) { - $("#weekslider").data("ionRangeSlider").update({ - from: week - }); - $("#weekslider_dsc").data("ionRangeSlider").update({ - from: week - }); +// Improved script + +// Setting URL for OpenCPU based on `isLocalApp` flag. +ocpu.seturl(isLocalApp ? "../R" : `//${hostname}${pathname}/ocpu/library/james/R`); + +// Internal constants for slider values +const sliderValues = { + "0_2": ["0w", "4w", "8w", "3m", "4m", "6m", "7.5m", "9m", "11m", "14m", "18m", "24m"], + "0_4": ["0w", "4w", "8w", "3m", "4m", "6m", "7.5m", "9m", "11m", "14m", "18m", "24m", "36m", "45m"], + "0_19": ["0w", "3m", "6m", "12m", "24m", "5y", "9y", "10y", "11y", "14y", "19y"], + "0_29": ["0w", "3m", "6m", "14m", "24m", "48m", "10y", "18y"], + "matches": ["0", "1", "2", "5", "10", "25", "50", "100"] +}; + +// Starting defaults for initialization per child +let sliderList = "0_2", chartcode = "NJAH"; +$("#donordata").val("0-2"); + +// Initialize sliders with shared settings and unique attributes where necessary +const initializeSlider = (selector, settings) => { + $(selector).ionRangeSlider({ + type: settings.type, + skin: "round", + grid_snap: true, + ...settings, + onFinish: update + }); +}; + +initializeSlider("#weekslider", { min: 25, max: 36, from: 36, step: 1 }); +initializeSlider("#matchslider", { from: 0, values: sliderValues["matches"] }); +initializeSlider("#visitslider", { type: "double", min_interval: 0, drag_interval: true, values: sliderValues[sliderList] }); + +// Set active accordion page +let active = "groei"; +["#groei", "#ontwikkeling"].forEach(id => { + $(id).click(() => { + if (active !== id.substring(1)) { + active = id.substring(1); + update(); } + }); +}); - // set etnicity - var pop = String(output.population).toLowerCase(); - switch(pop) { - case "nl": - case "tu": - case "ma": - case "hs": - case "ds": - document.forms.etnicity[pop].checked=true; - break; - default: - } - - //set sex UI element - document.forms.sex[String(output.sex)].checked=true; - - // Set donordata and visit slider - var dnr = String(output.dnr); - document.getElementById("donordata").value = dnr; - slider_list = String(output.slider_list); - var values = slider_values[[slider_list]]; - var from = values.indexOf(String(output.period[0])); - var to = values.indexOf(String(output.period[1])); - var slider_instance = $("#visitslider").data("ionRangeSlider"); - slider_instance.update({ - values: values, - from: from, - to: to}); - - update_notice_panel(rq = 1, session = session); - - // set UI controls and chart - update(); - - // for all subsequent calls, use derive - // this allows user to change charts interactively - selector = "derive"; - }); +// Set onchange triggers +const addChangeListener = (elementId) => { + document.getElementById(elementId).addEventListener('change', update, false); +}; + +addChangeListener('chartgrp'); +addChangeListener('chartgrp_dsc'); + +// Simplify radio button event attachment +["agegrp", "msr", "etnicity", "sex", "agegrp_dsc"].forEach(formName => { + document.forms[formName].elements[formName].forEach(radio => { + radio.onclick = update; + }); }); - rq1.fail(function(session) { - alert("Server error rq1 - cannot read data for initialization\n" + - "txt: " + utxt + "\n" + - "session: " + uses + "\n" + - "chartcode: " + ucode + "\n" + - "selector: " + selector + "\n" + - "error: " + rq1.responseText); - console.log("rq1 txt: " + utxt); - console.log("rq1 session: " + uses); - console.log("rq1 chartcode: " + ucode); - console.log("rq1 selector: " + selector); - console.log("rq1 error: " + rq1.responseText); - // note: the following update does not work SvB March 2024 - update_notice_panel(rq = 1, session = session); + +// Define the default selector based on user interaction +let selector = "derive"; + +// Update the selector based on available user data or specific user input +selector = userChartcode ? "chartcode" : (userText || userSession) ? "data" : selector; + +// Decide whether to initialize chart controls or simply update the chart based on the presence of any user input +(userText || userSession || userChartcode) ? initializeChartControls() : update(); + +function initializeChartControls() { + // Executes at initialization to get settings from uploaded data + const request = ocpu.call("convert_tgt_chartadvice", { + txt: userText, + session: userSession, + chartcode: userChartcode, + selector: selector + }, session => { + // Retrieve the returned object asynchronously + session.getObject(output => { + // Handle invalid chartcode + if (!output.chartcode) { + alert(`Unknown chartcode: ${userChartcode}`); + return; + } + + // Set UI elements based on returned data + showCards(output.accordion.toString()); + + // Conditional UI adjustments + const chartGroupElementId = output.side === "dsc" ? "chartgrp_dsc" : "chartgrp"; + document.getElementById(chartGroupElementId).value = output.chartgrp.toString(); + if (output.side !== "dsc") { + document.forms.msr[output.side].checked = true; + } + document.forms.agegrp[output.agegrp].checked = true; + if (output.agegrp !== "1-21y") { + document.forms.agegrp_dsc[output.agegrp].checked = true; + } + + // Update sliders + updateSliders(output); + + // Set ethnicity and sex + setEthnicity(output.population); + document.forms.sex[output.sex].checked = true; + + // Final UI updates + updateNoticePanel(true, session); + update(); + + // Prep for subsequent calls + selector = "derive"; + }); + }); + + request.fail(session => { + console.error("Server error rq1 - cannot read data for initialization", { + txt: userText, + session: userSession, + chartcode: userChartcode, + selector: selector, + error: request.responseText + }); + alert(`Server error rq1 - cannot read data for initialization\nDetails logged to console.`); + updateNoticePanel(true, session); }); } -function update_donordata() { - // update slider values and graph if user changes dnr - var dnr = document.getElementById("donordata").value; - switch (dnr){ - case "0-2": - slider_list = "0_2"; - break; - case "2-4": - slider_list = "0_4"; - break; - case "4-18": - slider_list = "0_29"; - break; - default: - slider_list = "0_2"; +function updateSliders(output) { + const weekNum = Math.trunc(Number(output.week)); + if (weekNum >= 25 && weekNum <= 36) { + updateWeekSlider("#weekslider", output.week); + updateWeekSlider("#weekslider_dsc", output.week); } - var values = slider_values[[slider_list]]; - var slider_instance = $("#visitslider").data("ionRangeSlider"); - slider_instance.update({ - values: values}); - update(); + document.getElementById("donordata").value = output.dnr; + slider_list = output.slider_list.toString(); + const values = slider_values[slider_list]; + const from = values.indexOf(output.period[0].toString()); + const to = values.indexOf(output.period[1].toString()); + $("#visitslider").data("ionRangeSlider").update({ values, from, to }); } -function showTextdiv() { - $("#plotdiv").hide(500); - $("#textdiv").show(500); +function updateWeekSlider(selector, week) { + $(selector).data("ionRangeSlider").update({ from: week }); } -function showPlotdiv() { - $("#plotdiv").show(500); - $("#textdiv").hide(500); +function setEthnicity(population) { + const pop = population.toLowerCase(); + if (["nl", "tu", "ma", "hs", "ds"].includes(pop)) { + document.forms.etnicity[pop].checked = true; + } } -function showCards(show = "all") { - if (show == "all") { - sr('ontwikkelingcard', 'block'); - sr('ontwikkelingcard', 'block'); - $('#collapseOne').collapse('show'); +function updateDonorData() { + // Update slider values and graph based on the donor data selection + const donorData = document.getElementById("donordata").value; - } else if (show == "groei") { - sr('ontwikkelingcard', 'none'); - $('#collapseOne').collapse('show'); + // Define a mapping from donor data to slider lists + const donorToSliderMap = { + "0-2": "0_2", + "2-4": "0_4", + "4-18": "0_29" + }; - } else if (show == "ontwikkeling") { - sr('groeicard', 'none'); - $('#collapseTwo').collapse('show'); - active = "ontwikkeling"; - } + // Use the mapping to find the slider list, defaulting to "0_2" if not found + const sliderList = donorToSliderMap[donorData] || "0_2"; + + // Update the slider with the new values + const values = slider_values[sliderList]; + $("#visitslider").data("ionRangeSlider").update({ + values: values + }); + + // Refresh UI elements as necessary + update(); } -function update_notice_panel(rq, session) { +function toggleDisplay(divToShow, divToHide) { + $(`#${divToHide}`).hide(500); + $(`#${divToShow}`).show(500); +} - if (rq == 1) { - $("#rq1-session").text(session.getKey()); - session.getConsole(function(outtxt){ - $("#rq1-console").text(outtxt); - }); - session.getWarnings(function(outtxt){ - $("#rq1-warnings").text(outtxt); - }); - session.getMessages(function(outtxt){ - $("#rq1-messages").text(outtxt); - }); - } - if (rq == 2) { - $("#rq2-session").text(session.getKey()); - session.getConsole(function(outtxt){ - $("#rq2-console").text(outtxt); - }); - session.getWarnings(function(outtxt){ - $("#rq2-warnings").text(outtxt); - }); - session.getMessages(function(outtxt){ - $("#rq2-messages").text(outtxt); +function showCards(option = "all") { + const displayMap = { + all: () => { + sr('ontwikkelingcard', 'block'); + sr('groeicard', 'block'); + $('#collapseOne, #collapseTwo').collapse('show'); + }, + groei: () => { + sr('ontwikkelingcard', 'none'); + sr('groeicard', 'block'); + $('#collapseOne').collapse('show'); + }, + ontwikkeling: () => { + sr('groeicard', 'none'); + sr('ontwikkelingcard', 'block'); + $('#collapseTwo').collapse('show'); + active = "ontwikkeling"; + } + }; + + // Execute the relevant function based on the 'option' parameter + if(displayMap[option]) displayMap[option](); +} + +function updateNoticePanel(rq, session) { + // Handle multiple requests + const rqKey = `#rq${rq}-session`; + const consoleOutput = `#rq${rq}-console`; + const warningsOutput = `#rq${rq}-warnings`; + const messagesOutput = `#rq${rq}-messages`; + + $(rqKey).text(session.getKey()); + + // Helper function to set session info + const setSessionInfo = (selector, method) => { + session[method](outtxt => { + $(selector).text(outtxt); }); - } + }; + + setSessionInfo(consoleOutput, 'getConsole'); + setSessionInfo(warningsOutput, 'getWarnings'); + setSessionInfo(messagesOutput, 'getMessages'); } From dd26c36851c7dacf781d191f579b5f00dd30f9c7 Mon Sep 17 00:00:00 2001 From: Stef van Buuren Date: Tue, 19 Mar 2024 23:15:12 +0100 Subject: [PATCH 02/26] Refactor and split update.js --- inst/www/js/handleUIVisibility.js | 124 ++++++++++++++ inst/www/js/update.js | 275 +++++++----------------------- 2 files changed, 190 insertions(+), 209 deletions(-) create mode 100644 inst/www/js/handleUIVisibility.js diff --git a/inst/www/js/handleUIVisibility.js b/inst/www/js/handleUIVisibility.js new file mode 100644 index 0000000..656076f --- /dev/null +++ b/inst/www/js/handleUIVisibility.js @@ -0,0 +1,124 @@ +function handleUIVisibility(chartGroup, ageGroup, population) { + // Define a mapping for chart group visibility settings + const chartGroupVisibility = { + 'nl2010': { + 'agegrp_1-21y': 'block', + 'weekmenu': 'none', + 'etnicity': 'block', + }, + 'preterm': { + 'agegrp_1-21y': 'none', + 'weekmenu': 'block', + 'etnicity': 'none', + }, + 'who': { + 'agegrp_1-21y': 'none', + 'weekmenu': 'none', + 'etnicity': 'none', + }, + 'gsed1': { + 'weekmenu_dsc': 'none', + }, + 'gsed1pt': { + 'weekmenu_dsc': 'block', + } + }; + + // Mapping for age group and population visibility settings + const ageGroupPopulationVisibility = { + '0-15m': { + 'nl': { + 'msr_hgt': 'block', + 'msr_wgt': 'block', + 'msr_wfh': 'none', + 'msr_hdc': 'block', + 'msr_bmi': 'none', + 'msr_front': 'block', + 'msr_back': 'block', + }, + 'default': { + 'msr_hgt': 'block', + 'msr_wgt': 'block', + 'msr_wfh': 'none', + 'msr_hdc': 'block', + 'msr_bmi': 'none', + 'msr_front': 'block', + 'msr_back': 'none', + } + }, + '0-4y': { + 'nl': { + 'msr_hgt': 'block', + 'msr_wgt': 'block', + 'msr_wfh': 'block', + 'msr_hdc': 'block', + 'msr_bmi': 'none', + 'msr_front': 'block', + 'msr_back': 'block', + }, + 'hs': { + 'msr_hgt': 'block', + 'msr_wgt': 'none', + 'msr_wfh': 'block', + 'msr_hdc': 'none', + 'msr_bmi': 'none', + 'msr_front': 'block', + 'msr_back': 'block', + }, + 'default': { + 'msr_hgt': 'block', + 'msr_wgt': 'none', + 'msr_wfh': 'block', + 'msr_hdc': 'none', + 'msr_bmi': 'none', + 'msr_front': 'block', + 'msr_back': 'none', + } + }, + '1-21y': { + 'nl': { + 'msr_hgt': 'block', + 'msr_wgt': 'block', + 'msr_wfh': 'block', + 'msr_hdc': 'block', + 'msr_bmi': 'block', + 'msr_front': 'block', + 'msr_back': 'block', + }, + 'hs': { + 'msr_hgt': 'block', + 'msr_wgt': 'none', + 'msr_wfh': 'block', + 'msr_hdc': 'none', + 'msr_bmi': 'block', + 'msr_front': 'block', + 'msr_back': 'none', + }, + 'default': { + 'msr_hgt': 'block', + 'msr_wgt': 'none', + 'msr_wfh': 'block', + 'msr_hdc': 'block', + 'msr_bmi': 'block', + 'msr_front': 'block', + 'msr_back': 'block', + } + } + }; + + // Apply visibility settings for chart group + Object.entries(chartGroupVisibility[chartGroup] || {}).forEach(([id, display]) => { + sr(id, display); + }); + + // Apply visibility settings for age group and population + const agePopSettings = ageGroupPopulationVisibility[ageGroup][population] || ageGroupPopulationVisibility[ageGroup]['default']; + Object.entries(agePopSettings || {}).forEach(([id, display]) => { + sr(id, display); + }); +} + +// Auxiliary function to modify UI element display property +function sr(id, display) { + document.getElementById(id).style.display = display; +} diff --git a/inst/www/js/update.js b/inst/www/js/update.js index a069373..9501d45 100644 --- a/inst/www/js/update.js +++ b/inst/www/js/update.js @@ -3,224 +3,81 @@ // Netherlands Organisation for Applied Scientific Research TNO, Leiden function update() { + // Use let for variables that may change within the function + let msr, chartgrp, agegrp, population, ga; - // grab active variables - if (active == "groei"){ - var msr = document.querySelector('input[name="msr"]:checked').value; - var chartgrp = document.getElementById("chartgrp").value; - var agegrp = document.querySelector('input[name="agegrp"]:checked').value; - var population = document.querySelector('input[name="etnicity"]:checked').value; - var ga = Number($("#weekslider").data().from); + if (active === "groei") { + msr = document.querySelector('input[name="msr"]:checked').value; + chartgrp = document.getElementById("chartgrp").value; + agegrp = document.querySelector('input[name="agegrp"]:checked').value; + population = document.querySelector('input[name="etnicity"]:checked').value; + ga = Number($("#weekslider").data().from); + // Synchronize interpolation checkboxes document.getElementById("interpolation_dsc").checked = document.getElementById("interpolation").checked; - } else if (active == "ontwikkeling"){ - var msr = "dsc"; - var chartgrp = document.getElementById("chartgrp_dsc").value; - var agegrp = document.querySelector('input[name="agegrp_dsc"]:checked').value; - var population = "nl"; - var ga = Number($("#weekslider_dsc").data().from); + } else if (active === "ontwikkeling") { + msr = "dsc"; + chartgrp = document.getElementById("chartgrp_dsc").value; + agegrp = document.querySelector('input[name="agegrp_dsc"]:checked').value; + population = "nl"; // Assume default population + ga = Number($("#weekslider_dsc").data().from); document.getElementById("interpolation").checked = document.getElementById("interpolation_dsc").checked; } - var sex = document.querySelector('input[name="sex"]:checked').value; - var cm = document.getElementById("interpolation").checked; - var dnr = document.getElementById("donordata").value; - var lo = $("#visitslider").data().from; - var hi = $("#visitslider").data().to; - var match = Number($("#matchslider").data().from); - var exact_sex = document.getElementById("exact_sex").checked; - var exact_ga = document.getElementById("exact_ga").checked; - var show_future = document.getElementById("show_future").checked; - var show_realized = document.getElementById("show_realized").checked; + const sex = document.querySelector('input[name="sex"]:checked').value; + const cm = document.getElementById("interpolation").checked; + const dnr = document.getElementById("donordata").value; + const lo = $("#visitslider").data().from; + const hi = $("#visitslider").data().to; + const match = Number($("#matchslider").data().from); + const exact_sex = document.getElementById("exact_sex").checked; + const exact_ga = document.getElementById("exact_ga").checked; + const show_future = document.getElementById("show_future").checked; + const show_realized = document.getElementById("show_realized").checked; - var hi_str = slider_values[[slider_list]][hi]; - var lo_str = slider_values[[slider_list]][lo]; - var nmatch = slider_values[["matches"]][match]; + // Simplify retrieval of string values + const hiStr = sliderValues[sliderList][hi]; + const loStr = sliderValues[sliderList][lo]; + const nmatch = sliderValues.matches[match]; - // set active UI elements - if (chartgrp == 'nl2010') { - sr('agegrp_1-21y', 'block'); - sr('weekmenu', 'none'); - sr('etnicity', 'block'); - } - if (chartgrp == 'preterm') { - sr('agegrp_1-21y', 'none'); - sr('weekmenu', 'block'); - sr('etnicity', 'none'); - } - if (chartgrp == 'who') { - sr('agegrp_1-21y', 'none'); - sr('weekmenu', 'none'); - sr('etnicity', 'none'); - } - if (chartgrp == 'gsed1') { - ga = 40; - sr('weekmenu_dsc', 'none'); - } - if (chartgrp == 'gsed1pt') { - sr('weekmenu_dsc', 'block'); - } - - if (agegrp == '0-15m' & chartgrp == 'nl2010' & population == 'nl') { - sr('msr_hgt', 'block'); - sr('msr_wgt', 'block'); - sr('msr_wfh', 'none'); - sr('msr_hdc', 'block'); - sr('msr_bmi', 'none'); - sr('msr_front', 'block'); - sr('msr_back', 'block'); - } - if (agegrp == '0-15m' & chartgrp == 'nl2010' & population != 'nl') { - sr('msr_hgt', 'block'); - sr('msr_wgt', 'block'); - sr('msr_wfh', 'none'); - sr('msr_hdc', 'block'); - sr('msr_bmi', 'none'); - sr('msr_front', 'block'); - sr('msr_back', 'block'); - } - if (agegrp == '0-15m' & chartgrp == 'preterm' & population == 'nl') { - sr('msr_hgt', 'block'); - sr('msr_wgt', 'block'); - sr('msr_wfh', 'none'); - sr('msr_hdc', 'block'); - sr('msr_bmi', 'none'); - sr('msr_front', 'block'); - sr('msr_back', 'none'); - } - if (agegrp == '0-15m' & chartgrp == 'preterm' & population != 'nl') { - sr('msr_hgt', 'block'); - sr('msr_wgt', 'block'); - sr('msr_wfh', 'none'); - sr('msr_hdc', 'block'); - sr('msr_bmi', 'none'); - sr('msr_front', 'block'); - sr('msr_back', 'none'); - } - if (agegrp == '0-15m' & chartgrp == 'who') { - sr('msr_hgt', 'block'); - sr('msr_wgt', 'block'); - sr('msr_wfh', 'none'); - sr('msr_hdc', 'block'); - sr('msr_bmi', 'none'); - sr('msr_front', 'block'); - sr('msr_back', 'none'); - } - if (agegrp == '0-4y' & chartgrp == 'nl2010' & population == 'nl') { - sr('msr_hgt', 'block'); - sr('msr_wgt', 'block'); - sr('msr_wfh', 'block'); - sr('msr_hdc', 'block'); - sr('msr_bmi', 'none'); - sr('msr_front', 'block'); - sr('msr_back', 'block'); - } - if (agegrp == '0-4y' & chartgrp == 'nl2010' & population != 'nl') { - sr('msr_hgt', 'block'); - sr('msr_wgt', 'none'); - sr('msr_wfh', 'block'); - sr('msr_hdc', 'block'); - sr('msr_bmi', 'none'); - sr('msr_front', 'block'); - sr('msr_back', 'block'); - } - if (agegrp == '0-4y' & chartgrp == 'nl2010' & population == 'hs') { - sr('msr_hgt', 'block'); - sr('msr_wgt', 'none'); - sr('msr_wfh', 'block'); - sr('msr_hdc', 'none'); - sr('msr_bmi', 'none'); - sr('msr_front', 'block'); - sr('msr_back', 'block'); - } - if (agegrp == '0-4y' & chartgrp == 'preterm') { - sr('msr_hgt', 'block'); - sr('msr_wgt', 'block'); - sr('msr_wfh', 'none'); - sr('msr_hdc', 'none'); - sr('msr_bmi', 'none'); - sr('msr_front', 'block'); - sr('msr_back', 'none'); - } - if (agegrp == '0-4y' & chartgrp == 'who') { - sr('msr_hgt', 'block'); - sr('msr_wgt', 'none'); - sr('msr_wfh', 'block'); - sr('msr_hdc', 'none'); - sr('msr_bmi', 'none'); - sr('msr_front', 'block'); - sr('msr_back', 'none'); - } - if (agegrp == '1-21y' & population != 'hs') { - sr('msr_hgt', 'block'); - sr('msr_wgt', 'none'); - sr('msr_wfh', 'block'); - sr('msr_hdc', 'block'); - sr('msr_bmi', 'block'); - sr('msr_front', 'block'); - sr('msr_back', 'block'); - } - if (agegrp == '1-21y' & population == 'hs') { - sr('msr_hgt', 'block'); - sr('msr_wgt', 'none'); - sr('msr_wfh', 'block'); - sr('msr_hdc', 'none'); - sr('msr_bmi', 'block'); - sr('msr_front', 'block'); - sr('msr_back', 'none'); - } - - // handle null user inputs - var utxt = ''; - var uses = ''; - var ucode = ''; - if (typeof user_txt !== "undefined" && user_txt !== null) utxt = user_txt; - if (typeof user_session !== "undefined" && user_session !== null) uses = user_session; - if (typeof user_chartcode !== "undefined" && user_chartcode !== null) ucode = user_chartcode; + // Simplify the logic of showing/hiding elements based on `chartgrp` and `agegrp` + handleUIVisibility(chartgrp, agegrp, population); - // trigger chart drawing - var rq2 = $("#plotdiv").rplot("draw_chart", { - txt : utxt, - session : uses, - chartcode: ucode, - selector : selector, - chartgrp : chartgrp, - agegrp : agegrp, - sex : sex, - etn : population, - ga : ga, - side : msr, - curve_interpolation : cm, - quiet : false, - dnr : dnr, - lo : lo_str, - hi : hi_str, - nmatch : nmatch, - exact_sex: exact_sex, - exact_ga : exact_ga, - show_future : show_future, - show_realized : show_realized - }, function(session) { - update_notice_panel(rq = 2, session = session); - }); - rq2.fail(function(session) { - alert("Server error rq2 - cannot read data for plotting\n" + - "txt: " + utxt + "\n" + - "session: " + uses + "\n" + - "chartcode: " + ucode + "\n" + - "selector: " + selector + "\n" + - "error: " + rq2.responseText); - console.log("rq2 txt: " + utxt); - console.log("rq2 session: " + uses); - console.log("rq2 chartcode: " + ucode); - console.log("rq2 selector: " + selector); - console.log("rq2 error: " + rq2.responseText); - // note: the following update does not work SvB March 2024 - update_notice_panel(rq = 2, session = session); + // Trigger chart drawing, simplified error handling + drawChart({ + txt: userText, + session: userSession, + chartcode: userChartCode, + selector, + chartgrp, + agegrp, + sex, + etn: population, + ga, + side: msr, + curve_interpolation: cm, + quiet: false, + dnr, + lo: loStr, + hi: hiStr, + nmatch, + exact_sex, + exact_ga, + show_future, + show_realized }); } -function sr(id, display) { - // set UI element display - document.getElementById(id).style.display = display; +function drawChart(params) { + const rq = $("#plotdiv").rplot("draw_chart", params, session => { + update_notice_panel(2, session); + }).fail(session => { + console.error("Server error rq2 - cannot read data for plotting", { + txt: params.txt, + session: params.session, + chartcode: params.chartcode, + selector: params.selector, + error: rq.responseText // This might need adjustment based on how rq is scoped + }); + // Logging or user notification + }); } - From d609d99468a95dbe8d0aca121a056ebb28115e42 Mon Sep 17 00:00:00 2001 From: Stef van Buuren Date: Tue, 19 Mar 2024 23:15:46 +0100 Subject: [PATCH 03/26] Update opencpu-0.5-james-0.1.js --- inst/www/js/opencpu-0.5-james-0.1.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/inst/www/js/opencpu-0.5-james-0.1.js b/inst/www/js/opencpu-0.5-james-0.1.js index 2eac125..12b304c 100644 --- a/inst/www/js/opencpu-0.5-james-0.1.js +++ b/inst/www/js/opencpu-0.5-james-0.1.js @@ -164,11 +164,11 @@ if(!window.jQuery) { //ajax call var jqxhr = $.ajax(settings).done(function(){ var key = jqxhr.getResponseHeader('X-ocpu-session') || console.log("X-ocpu-session response header missing."); - if (localapp) + if (isSingleUser) { var loc = host + ':80/ocpu/tmp/' + key + '/'; } else { - var loc = host + pathname + '/' + key + '/'; + var loc = host + basePath + '/' + key + '/'; } var txt = jqxhr.responseText; @@ -477,7 +477,7 @@ if(!window.jQuery) { /* take out user:pass from target url */ var target = document.createElement('a'); target.href = settings.url; - settings.url = target.protocol + "//" + target.host + target.pathname + settings.url = target.protocol + "//" + target.host + target.basePath /* set basic auth header */ settings.xhrFields = settings.xhrFields || {}; From c496d4544fbba4553bed495185f93531a3ae7a16 Mon Sep 17 00:00:00 2001 From: Stef van Buuren Date: Tue, 19 Mar 2024 23:22:40 +0100 Subject: [PATCH 04/26] Add new .js file --- inst/www/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/inst/www/index.html b/inst/www/index.html index 706a30b..e3a865f 100644 --- a/inst/www/index.html +++ b/inst/www/index.html @@ -14,6 +14,7 @@ + From 990c954c9b440cff22a7ea0f558c8ef9e6bf304a Mon Sep 17 00:00:00 2001 From: Stef van Buuren Date: Tue, 19 Mar 2024 23:27:49 +0100 Subject: [PATCH 05/26] Update start.js --- inst/www/js/start.js | 87 -------------------------------------------- 1 file changed, 87 deletions(-) diff --git a/inst/www/js/start.js b/inst/www/js/start.js index e35ed32..c5ae33d 100644 --- a/inst/www/js/start.js +++ b/inst/www/js/start.js @@ -76,93 +76,6 @@ let selector = userChartcode ? "chartcode" : (userText || userSession) ? "data" // Initialize chart controls or update based on user input (userText || userSession || userChartcode) ? initializeChartControls() : update(); -// Definitions for 'initializeChartControls', 'updateSliders', 'updateWeekSlider', 'setEthnicity', and related functions remain the same as provided, ensuring they follow similar consistency and style practices. - - -// start.js - - -// Destructure window.location for concise access to needed properties. -const { protocol, hostname, pathname } = window.location; - -// Construct host URL using template literals for clarity and conciseness. -const host = `${protocol}//${hostname}`; - -// Remove ".html" from the pathname. -const basePath = pathname.slice(0, -5); - -// Set the OpenCPU server URL based on the environment. -ocpu.seturl(isSingleUser ? "../R" : `//${hostname}${pathname}/ocpu/library/james/R`); - - -// Improved script - -// Setting URL for OpenCPU based on `isLocalApp` flag. -ocpu.seturl(isLocalApp ? "../R" : `//${hostname}${pathname}/ocpu/library/james/R`); - -// Internal constants for slider values -const sliderValues = { - "0_2": ["0w", "4w", "8w", "3m", "4m", "6m", "7.5m", "9m", "11m", "14m", "18m", "24m"], - "0_4": ["0w", "4w", "8w", "3m", "4m", "6m", "7.5m", "9m", "11m", "14m", "18m", "24m", "36m", "45m"], - "0_19": ["0w", "3m", "6m", "12m", "24m", "5y", "9y", "10y", "11y", "14y", "19y"], - "0_29": ["0w", "3m", "6m", "14m", "24m", "48m", "10y", "18y"], - "matches": ["0", "1", "2", "5", "10", "25", "50", "100"] -}; - -// Starting defaults for initialization per child -let sliderList = "0_2", chartcode = "NJAH"; -$("#donordata").val("0-2"); - -// Initialize sliders with shared settings and unique attributes where necessary -const initializeSlider = (selector, settings) => { - $(selector).ionRangeSlider({ - type: settings.type, - skin: "round", - grid_snap: true, - ...settings, - onFinish: update - }); -}; - -initializeSlider("#weekslider", { min: 25, max: 36, from: 36, step: 1 }); -initializeSlider("#matchslider", { from: 0, values: sliderValues["matches"] }); -initializeSlider("#visitslider", { type: "double", min_interval: 0, drag_interval: true, values: sliderValues[sliderList] }); - -// Set active accordion page -let active = "groei"; -["#groei", "#ontwikkeling"].forEach(id => { - $(id).click(() => { - if (active !== id.substring(1)) { - active = id.substring(1); - update(); - } - }); -}); - -// Set onchange triggers -const addChangeListener = (elementId) => { - document.getElementById(elementId).addEventListener('change', update, false); -}; - -addChangeListener('chartgrp'); -addChangeListener('chartgrp_dsc'); - -// Simplify radio button event attachment -["agegrp", "msr", "etnicity", "sex", "agegrp_dsc"].forEach(formName => { - document.forms[formName].elements[formName].forEach(radio => { - radio.onclick = update; - }); -}); - -// Define the default selector based on user interaction -let selector = "derive"; - -// Update the selector based on available user data or specific user input -selector = userChartcode ? "chartcode" : (userText || userSession) ? "data" : selector; - -// Decide whether to initialize chart controls or simply update the chart based on the presence of any user input -(userText || userSession || userChartcode) ? initializeChartControls() : update(); - function initializeChartControls() { // Executes at initialization to get settings from uploaded data const request = ocpu.call("convert_tgt_chartadvice", { From 5ce2fa0122d0e13c58a86f4f1df358cd3a4ff125 Mon Sep 17 00:00:00 2001 From: Stef van Buuren Date: Tue, 19 Mar 2024 23:30:41 +0100 Subject: [PATCH 06/26] Typo --- inst/www/js/update.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/www/js/update.js b/inst/www/js/update.js index 9501d45..9d23aad 100644 --- a/inst/www/js/update.js +++ b/inst/www/js/update.js @@ -46,7 +46,7 @@ function update() { drawChart({ txt: userText, session: userSession, - chartcode: userChartCode, + chartcode: userChartcode, selector, chartgrp, agegrp, From 66f649eff67f4d0f23909d4d9b3e3a5c90b4325f Mon Sep 17 00:00:00 2001 From: Stef van Buuren Date: Tue, 19 Mar 2024 23:34:30 +0100 Subject: [PATCH 07/26] Use update NoticePanel --- inst/www/js/update.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/www/js/update.js b/inst/www/js/update.js index 9d23aad..9fbe1a6 100644 --- a/inst/www/js/update.js +++ b/inst/www/js/update.js @@ -69,7 +69,7 @@ function update() { function drawChart(params) { const rq = $("#plotdiv").rplot("draw_chart", params, session => { - update_notice_panel(2, session); + updateNoticePanel(2, session); }).fail(session => { console.error("Server error rq2 - cannot read data for plotting", { txt: params.txt, From 1a7b13786ce4d13e6b0d3a18499764d82c4d5042 Mon Sep 17 00:00:00 2001 From: Stef van Buuren Date: Wed, 20 Mar 2024 08:32:07 +0100 Subject: [PATCH 08/26] Adapt toggle div behavior to new JS setup --- inst/www/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/inst/www/index.html b/inst/www/index.html index e3a865f..2f665d1 100644 --- a/inst/www/index.html +++ b/inst/www/index.html @@ -47,7 +47,7 @@
@@ -118,7 +118,7 @@
@@ -158,7 +158,7 @@
@@ -231,7 +231,7 @@
From ef1242c763f104028e5516d571f5d7d3484f8833 Mon Sep 17 00:00:00 2001 From: Stef van Buuren Date: Wed, 20 Mar 2024 08:38:03 +0100 Subject: [PATCH 09/26] Repair typos --- inst/www/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/inst/www/index.html b/inst/www/index.html index 2f665d1..0b0b06c 100644 --- a/inst/www/index.html +++ b/inst/www/index.html @@ -47,7 +47,7 @@
@@ -118,7 +118,7 @@
@@ -252,8 +252,8 @@
-
-