Skip to content

Commit

Permalink
Merge pull request #27 from growthcharts/throttle
Browse files Browse the repository at this point in the history
Throttle 3 seconds and event attachment in JS
  • Loading branch information
stefvanbuuren authored Mar 20, 2024
2 parents 74e7ae9 + 5eb8a52 commit 04f770e
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 81 deletions.
20 changes: 10 additions & 10 deletions inst/www/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
<div class="card" id = "groeicard">
<div class="card-header">
<a class="card-link" data-toggle="collapse" href="#collapseOne" id = "groei">
<strong onclick="toggleDisplay('plotDiv', 'textDiv')">Groei</strong>
<strong>Groei</strong>
</a>
</div>
<div id="collapseOne" class="collapse show" data-parent="#accordion">
Expand Down Expand Up @@ -108,7 +108,7 @@
<p id="chartcode"></p>
<br>

<input type="checkbox" id="interpolation" checked='true' onchange="update()">
<input type="checkbox" id="interpolation" checked='true'>
Curve interpolation<br>
</div>
</div>
Expand All @@ -118,7 +118,7 @@
<div class="card" id = "ontwikkelingcard">
<div class="card-header">
<a class="card-link" data-toggle="collapse" href="#collapseTwo" id = "ontwikkeling">
<strong onclick="toggleDisplay('plotDiv', 'textDiv')">Ontwikkeling</strong>
<strong>Ontwikkeling</strong>
</a>
</div>
<div id="collapseTwo" class="collapse" data-parent="#accordion">
Expand Down Expand Up @@ -148,7 +148,7 @@
<p id="chartcode_dsc"></p>
<br>

<input type="checkbox" id="interpolation_dsc" checked='true' onchange="update()">
<input type="checkbox" id="interpolation_dsc" checked='true'>
Curve interpolation<br>

</div>
Expand All @@ -158,7 +158,7 @@
<div class="card">
<div class="card-header">
<a class="collapsed card-link" data-toggle="collapse" href="#collapseThree" id = "voorspeller">
<strong onclick="toggleDisplay('plotDiv','textDiv')">Voorspeller</strong>
<strong>Voorspeller</strong>
</a>
</div>
<div id="collapseThree" class="collapse" data-parent="#accordion">
Expand Down Expand Up @@ -190,7 +190,7 @@
<div class="form-group">
<div class="checkbox">
<label>
<input id="exact_sex" type="checkbox" checked="checked" onchange="update()"/>
<input id="exact_sex" type="checkbox" checked="checked"/>
<span>Zelfde geslacht</span>
</label>
</div>
Expand All @@ -199,7 +199,7 @@
<div class="form-group" style="display:none;">
<div class="checkbox">
<label>
<input id="exact_ga" type="checkbox" onchange="update()"/>
<input id="exact_ga" type="checkbox">
<span>Zelfde zwangerschapsduur</span>
</label>
</div>
Expand All @@ -208,7 +208,7 @@
<div class="form-group">
<div class="checkbox">
<label>
<input id="show_future" type="checkbox" onchange="update()"/>
<input id="show_future" type="checkbox"/>
<span>Kijk in toekomst</span>
</label>
</div>
Expand All @@ -217,7 +217,7 @@
<div class="form-group">
<div class="checkbox">
<label>
<input id="show_realized" type="checkbox" onchange="update()"/>
<input id="show_realized" type="checkbox"/>
<span>Gerealiseerde groei</span>
</label>
</div>
Expand All @@ -231,7 +231,7 @@
<div class="card">
<div class="card-header">
<a class="card-link" data-toggle="collapse" href="#collapseFour" id = "meldingen">
<strong onclick="toggleDisplay('textDiv', 'plotDiv')">Meldingen</strong>
<strong>Meldingen</strong>
</a>
</div>
<div id="collapseFour" class="collapse" data-parent="#accordion">
Expand Down
6 changes: 6 additions & 0 deletions inst/www/js/handleUIVisibility.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
// handleUIvisibility.js
// Author: Stef van Buuren
// (c) 2024 Netherlands Organisation for Applied Scientific Research TNO, Leiden
// Part of the JAMES package
// Licence: AGPL

function handleUIVisibility(chartgrp, agegrp, population) {
if (chartgrp == 'nl2010') {
sr('agegrp_1-21y', 'block');
Expand Down
2 changes: 1 addition & 1 deletion inst/www/js/opencpu-0.5-james-0.1.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* File: opencpu-0.5-james-x.y.js
* Javascript client library for OpenCPU
* Version 0.5.0
* -- Adapted for JAMES by Stef van Buuren --- May 2019
* -- Adapted for JAMES by Stef van Buuren
* Depends: jQuery
* Requires HTML5 FormData support for file uploads
* http://github.com/jeroenooms/opencpu.js
Expand Down
151 changes: 83 additions & 68 deletions inst/www/js/start.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
// start.js
// Author: Stef van Buuren
// (c) 2024 Netherlands Organisation for Applied Scientific Research TNO, Leiden
// Part of the JAMES package
// Licence: AGPL

// Constants for OpenCPU server configuration based on environment
const isSingleUser = false;
Expand All @@ -15,68 +19,95 @@ const userChartcode = urlParams.get('chartcode') || '';
// Set the OpenCPU server URL
ocpu.seturl(isSingleUser ? "../R" : `//${hostname}${basePath}/ocpu/library/james/R`);

// Slider values configuration
// Defaults
let chartcode = "NJAH";
$("#donordata").val("0-2");

// Event attachment for UI controls
const addChangeListenerUpdate = (elementId) => {
document.getElementById(elementId).addEventListener('change', update, false);
};
const addChangeListenerThrottledUpdate = (elementId) => {
document.getElementById(elementId).addEventListener('change', throttledUpdate, false);
};

// Event attachment for UI controls: menus
addChangeListenerUpdate('chartgrp');
addChangeListenerUpdate('chartgrp_dsc');

// Event attachment for UI controls: check boxes
addChangeListenerThrottledUpdate('interpolation');
addChangeListenerThrottledUpdate('interpolation_dsc');
addChangeListenerThrottledUpdate('exact_sex');
addChangeListenerThrottledUpdate('exact_ga');
addChangeListenerThrottledUpdate('show_future');
addChangeListenerThrottledUpdate('show_realized');
addChangeListenerThrottledUpdate('exact_ga');

// Event attachment for UI controls: radio buttons
["agegrp", "msr", "etnicity", "sex", "agegrp_dsc"].forEach(formName => {
const radios = document.forms[formName].elements[formName];
for (let radio of radios) {
radio.onclick = throttledUpdate;
}
});

// Event attachment for UI controls: accordion
document.addEventListener('DOMContentLoaded', function() {
// Create a mapping of element IDs to the function arguments they correspond to.
// This assumes toggleDisplay accepts two arguments for divs to show/hide.
const linksToToggle = {
'groei': ['plotDiv', 'textDiv'],
'ontwikkeling': ['plotDiv', 'textDiv'],
'voorspeller': ['plotDiv', 'textDiv'],
'meldingen': ['textDiv', 'plotDiv']
};

// Iterate over the entries in the mapping object.
Object.entries(linksToToggle).forEach(([id, divs]) => {
const link = document.getElementById(id);
if (link) { // Check if the element exists to avoid null reference errors
link.addEventListener('click', function(event) {
// Prevent the default action if it's a link or a button inside a form
event.preventDefault();

// Call toggleDisplay with the div IDs specific to this link
toggleDisplay(...divs);
});
}
});
});

// Event attachment for UI controls: sliders
function initializeSlider(selector, options) {
const commonOptions = {
type: "single",
skin: "round",
grid_snap: true,
onFinish: throttledUpdate
};

// Merge common options with specific options provided for each slider
$(selector).ionRangeSlider($.extend({}, commonOptions, options));
}

// 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"]
};

// Defaults
let sliderList = "0_2";
let chartcode = "NJAH";
$("#donordata").val("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: sliderValues[["matches"]],
onFinish: function (data) {
update();
}
});
$("#visitslider").ionRangeSlider({
type: "double",
skin: "round",
grid_snap: true,
min_interval: 0,
drag_interval: true,
values: sliderValues[[sliderList]],
onFinish: function (data) {
update();
}
});
$("#weekslider_dsc").ionRangeSlider({
type: "single",
skin: "round",
grid_snap: true,
min: 25,
max: 36,
from: 36,
step: 1,
onFinish: function (data) {
update();
}
});
// Initialize the sliders with both common and specific options
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] });
initializeSlider("#weekslider_dsc", { min: 25, max: 36, from: 36, step: 1 });

// set active accordion page
// Set active accordion page
let active = "groei";
$('#groei').click(function (){
if (active != "groei"){
Expand All @@ -92,22 +123,6 @@ $('#ontwikkeling').click(function (){
}
});

// Listeners for UI controls
const addChangeListener = (elementId) => {
document.getElementById(elementId).addEventListener('change', update, false);
};

addChangeListener('chartgrp');
addChangeListener('chartgrp_dsc');

// Event attachment for radio buttons
["agegrp", "msr", "etnicity", "sex", "agegrp_dsc"].forEach(formName => {
const radios = document.forms[formName].elements[formName];
for (let radio of radios) {
radio.onclick = update;
}
});

// Selector logic
let selector = userChartcode ? "chartcode" : (userText || userSession) ? "data" : "derive";

Expand Down
45 changes: 43 additions & 2 deletions inst/www/js/update.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// update.js
// Author: Stef van Buuren, 2019-2023
// Netherlands Organisation for Applied Scientific Research TNO, Leiden
// Author: Stef van Buuren
// (c) 2024 Netherlands Organisation for Applied Scientific Research TNO, Leiden
// Part of the JAMES package
// Licence: AGPL

function update() {
// Use let for variables that may change within the function
Expand Down Expand Up @@ -67,6 +69,42 @@ function update() {
});
}

/**
* Creates a throttled version of a function that only invokes the original
* function at most once per every wait milliseconds.
*
* @param {Function} func The function to throttle.
* @param {number} wait The number of milliseconds to throttle invocations to.
* @return {Function} A throttled version of the function.
*/
function throttle(func, wait) {
let isThrottling = false;
let lastArgs;
let lastThis;

const invokeFunc = () => {
isThrottling = true;
setTimeout(() => {
isThrottling = false;
if (lastArgs) {
invokeFunc.apply(lastThis, lastArgs);
lastArgs = lastThis = null;
}
}, wait);

func.apply(lastThis, lastArgs);
};

return function() {
if (!isThrottling) {
invokeFunc.apply(this, arguments);
} else {
lastArgs = arguments;
lastThis = this;
}
};
}

function drawChart(params) {
const rq = $("#plotDiv").rplot("draw_chart", params, session => {
updateNoticePanel(2, session);
Expand All @@ -81,3 +119,6 @@ function drawChart(params) {
// Logging or user notification
});
}

// Set throttleUpdate to 3 seconds
const throttledUpdate = throttle(update, 3000);

0 comments on commit 04f770e

Please sign in to comment.