Merge branch 'main' into pages

merging main into pages
This commit is contained in:
Frank Knoll
2024-07-14 10:29:05 +02:00
10 changed files with 18756 additions and 415 deletions

File diff suppressed because one or more lines are too long

View File

@@ -5,34 +5,31 @@ class PageInitializer {
PageInitializer.#configureVaccine(vaccine); PageInitializer.#configureVaccine(vaccine);
} }
static #configureSymptom({ symptomSelectElement, prrByVaccineTableElement, downloadPrrByVaccineTableButton, keyColumnName }) { static #configureSymptom({ symptomSelectElement, searchParam, prrByVaccineTableElement, downloadPrrByVaccineTableButton, keyColumnName }) {
const prrByVaccineTableView = new PrrByVaccineTableView(prrByVaccineTableElement, downloadPrrByVaccineTableButton, keyColumnName); const prrByVaccineTableView = new PrrByVaccineTableView(prrByVaccineTableElement, downloadPrrByVaccineTableButton, keyColumnName);
PageInitializer.#initializeSelectElement( Select2.initializeSelectElement(
{ {
selectElement: symptomSelectElement, selectElement: symptomSelectElement,
onValueSelected: (id, text) => prrByVaccineTableView.displayPrrByVaccineTable4Symptom(id, text), textOfOption2Select: searchParam.get(),
onSelectOptionHavingValueAndText: (id, text) => {
prrByVaccineTableView.displayPrrByVaccineTable4Symptom(id, text);
searchParam.set(text);
},
minimumInputLength: 0 minimumInputLength: 0
}); });
} }
static #configureVaccine({ vaccineSelectElement, prrBySymptomTableElement, downloadPrrBySymptomTableButton, valueName }) { static #configureVaccine({ vaccineSelectElement, searchParam, prrBySymptomTableElement, downloadPrrBySymptomTableButton, valueName }) {
const prrBySymptomTableView = new PrrBySymptomTableView(prrBySymptomTableElement, downloadPrrBySymptomTableButton, valueName); const prrBySymptomTableView = new PrrBySymptomTableView(prrBySymptomTableElement, downloadPrrBySymptomTableButton, valueName);
PageInitializer.#initializeSelectElement( Select2.initializeSelectElement(
{ {
selectElement: vaccineSelectElement, selectElement: vaccineSelectElement,
onValueSelected: (id, text) => prrBySymptomTableView.displayPrrBySymptomTable4Vaccine(id ,text), textOfOption2Select: searchParam.get(),
onSelectOptionHavingValueAndText: (id, text) => {
prrBySymptomTableView.displayPrrBySymptomTable4Vaccine(id, text);
searchParam.set(text);
},
minimumInputLength: 0 minimumInputLength: 0
}); });
} }
static #initializeSelectElement({ selectElement, onValueSelected, minimumInputLength }) {
selectElement.select2({ minimumInputLength: minimumInputLength });
selectElement.on(
'select2:select',
function (event) {
const id = event.params.data.id;
const text = event.params.data.text;
onValueSelected(id, text);
});
}
} }

View File

@@ -33,7 +33,7 @@ class PrrByKeyTableView {
} }
#downloadPrrByKey() { #downloadPrrByKey() {
UIUtils.downloadUrlAsFilename( UrlUtils.downloadUrlAsFilename(
window.URL.createObjectURL( window.URL.createObjectURL(
new Blob( new Blob(
[this.#prrByKeyTable.getDisplayedTableAsCsv(`# ${this.#valueName}: ${this.#text}`)], [this.#prrByKeyTable.getDisplayedTableAsCsv(`# ${this.#valueName}: ${this.#text}`)],

View File

@@ -0,0 +1,16 @@
class SearchParam {
#name;
constructor(name) {
this.#name = name;
}
get() {
return UrlUtils.getSearchParamOfCurrentUrl(this.#name);
}
set(value) {
UrlUtils.setSearchParamOfCurrentUrl(this.#name, value);
}
}

View File

@@ -0,0 +1,50 @@
class Select2 {
static initializeSelectElement(
{
selectElement,
textOfOption2Select,
onSelectOptionHavingValueAndText,
minimumInputLength
}) {
selectElement.select2({ minimumInputLength: minimumInputLength });
selectElement.on(
'select2:select',
function (event) {
const id = event.params.data.id;
const text = event.params.data.text;
onSelectOptionHavingValueAndText(id, text);
});
Select2.#selectOptionHavingText(selectElement, textOfOption2Select);
}
static #selectOptionHavingText(selectElement, text) {
const option = Select2.#getOptionHavingText(selectElement, text);
if (option === undefined) {
return;
}
Select2.#selectOption(selectElement, option);
}
static #getOptionHavingText(selectElement, text) {
if (text === null) {
return undefined;
}
return Array
.from(selectElement[0].options)
.find(option => option.text == text);
}
static #selectOption(selectElement, option) {
selectElement.val(option.value).trigger('change');
selectElement.trigger({
type: 'select2:select',
params: {
data: {
"id": option.value,
"text": option.text
}
}
});
}
}

File diff suppressed because one or more lines are too long

View File

@@ -11,13 +11,13 @@
<script src="../../Utils.js"></script> <script src="../../Utils.js"></script>
<script src="../../UIUtils.js"></script> <script src="../../UIUtils.js"></script>
<script src="../../NumberWithBarElementFactory.js"></script> <script src="../../NumberWithBarElementFactory.js"></script>
<script src="../js/PrrByKey2CsvConverter.js"></script> <script src="../../SymptomsCausedByDrugs/js/PrrByKey2CsvConverter.js"></script>
<script src="../js/PageInitializer.js"></script> <script src="../../SymptomsCausedByDrugs/js/PageInitializer.js"></script>
<script src="../js/PrrByVaccineProvider.js"></script> <script src="../../SymptomsCausedByDrugs/js/PrrByVaccineProvider.js"></script>
<script src="../js/PrrByKeyTable.js"></script> <script src="../../SymptomsCausedByDrugs/js/PrrByKeyTable.js"></script>
<script src="../js/PrrByKeyTableView.js"></script> <script src="../../SymptomsCausedByDrugs/js/PrrByKeyTableView.js"></script>
<script src="../js/PrrByVaccineTableView.js"></script> <script src="../../SymptomsCausedByDrugs/js/PrrByVaccineTableView.js"></script>
<script src="../js/PrrBySymptomTableView.js"></script> <script src="../../SymptomsCausedByDrugs/js/PrrBySymptomTableView.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-2.17.2.css"> <link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-2.17.2.css">
<script src="https://code.jquery.com/qunit/qunit-2.17.2.js"></script> <script src="https://code.jquery.com/qunit/qunit-2.17.2.js"></script>
<script type="text/javascript" src="./jshamcrest.js"></script> <script type="text/javascript" src="./jshamcrest.js"></script>

View File

@@ -20,75 +20,11 @@ class UIUtils {
return document.getElementById(templateId).content.firstElementChild.cloneNode(true); return document.getElementById(templateId).content.firstElementChild.cloneNode(true);
} }
static createCanvas() {
return UIUtils.instantiateTemplate('template-canvas');
}
static clear(container) { static clear(container) {
container.replaceChildren(); container.replaceChildren();
} }
static createChartViewElementWithHeading(heading) {
const chartViewElement = UIUtils.instantiateTemplate('template-ChartView');
chartViewElement.querySelector(".heading").textContent = heading;
return {
chartViewElement: chartViewElement,
canvas: chartViewElement.querySelector(".canvas")
};
}
static getSelectedOption(selectElement) { static getSelectedOption(selectElement) {
return selectElement.options[selectElement.selectedIndex]; return selectElement.options[selectElement.selectedIndex];
} }
static getYLabelWithPercent(context) {
return UIUtils.#getLabelWithPercent(context, context.parsed.y);
}
static getXLabelWithPercent(context) {
return UIUtils.#getLabelWithPercent(context, context.parsed.x);
}
static #getLabelWithPercent(context, value) {
let label = context.dataset.label || '';
if (label) {
label += ': ';
}
if (value !== null) {
label += value.toFixed(1) + "%";
}
return label;
}
static getPercentageScale(label) {
return {
min: 0,
max: 100,
title: {
display: true,
text: label
},
ticks: {
callback: value => value + "%"
}
}
}
static getSearchParam(urlParams, searchParam, defaultValue) {
return urlParams.has(searchParam) ?
urlParams.get(searchParam) :
defaultValue;
}
static isSearchParamYES(urlParams, searchParam) {
return UIUtils.getSearchParam(urlParams, searchParam, 'NO').toUpperCase() == 'YES';
}
static downloadUrlAsFilename(url, filename) {
const a = document.createElement('a');
a.setAttribute('href', url);
a.setAttribute('download', filename);
a.click();
}
} }

38
docs/UrlUtils.js Normal file
View File

@@ -0,0 +1,38 @@
class UrlUtils {
static isSearchParamYES(urlParams, searchParam) {
return UrlUtils.#getSearchParam(urlParams, searchParam, 'NO').toUpperCase() == 'YES';
}
static getSearchParamOfCurrentUrl(searchParam) {
return UrlUtils.#getSearchParam(
new URLSearchParams(window.location.search),
searchParam,
null)
}
static setSearchParamOfCurrentUrl(nameOfSearchParam, valueOfSearchParam) {
UrlUtils.#setSearchParam(
new URL(window.location.href),
nameOfSearchParam,
valueOfSearchParam);
}
static downloadUrlAsFilename(url, filename) {
const a = document.createElement('a');
a.setAttribute('href', url);
a.setAttribute('download', filename);
a.click();
}
static #getSearchParam(urlParams, searchParam, defaultValue) {
return urlParams.has(searchParam) ?
urlParams.get(searchParam) :
defaultValue;
}
static #setSearchParam(url, nameOfSearchParam, valueOfSearchParam) {
url.searchParams.set(nameOfSearchParam, valueOfSearchParam);
window.history.replaceState(null, "", url);
}
}

View File

@@ -1,88 +1,95 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf-8"/> <meta charset="utf-8" />
<meta content="width=device-width, initial-scale=1.0" name="viewport"/> <meta content="width=device-width, initial-scale=1.0" name="viewport" />
<title>Batch Codes of Coronavirus 2019 Vaccines</title> <title>Batch Codes of Coronavirus 2019 Vaccines</title>
<!-- Google tag (gtag.js) --> <!-- Google tag (gtag.js) -->
<script async="" src="https://www.googletagmanager.com/gtag/js?id=G-ERHYDH4P64"></script> <script async="" src="https://www.googletagmanager.com/gtag/js?id=G-ERHYDH4P64"></script>
<script> <script>
window.dataLayer = window.dataLayer || []; window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); } function gtag() { dataLayer.push(arguments); }
gtag('js', new Date()); gtag('js', new Date());
gtag('config', 'G-ERHYDH4P64'); gtag('config', 'G-ERHYDH4P64');
</script> </script>
<link href="https://cdn.datatables.net/1.13.1/css/jquery.dataTables.css" rel="stylesheet" type="text/css"/> <link href="https://cdn.datatables.net/1.13.1/css/jquery.dataTables.css" rel="stylesheet" type="text/css" />
<link href="batchCodeTable.css" rel="stylesheet" type="text/css"/> <link href="batchCodeTable.css" rel="stylesheet" type="text/css" />
<link href="forkMeOnGitHub.css" rel="stylesheet" type="text/css"/> <link href="forkMeOnGitHub.css" rel="stylesheet" type="text/css" />
<script crossorigin="anonymous" integrity="sha512-T5Bneq9hePRO8JR0S/0lQ7gdW+ceLThvC80UjwkMRz+8q+4DARVZ4dqKoyENC7FcYresjfJ6ubaOgIE35irf4w==" referrerpolicy="no-referrer" src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.5.1/nouislider.min.js"></script> <script crossorigin="anonymous"
<link crossorigin="anonymous" href="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.5.1/nouislider.css" integrity="sha512-MKxcSu/LDtbIYHBNAWUQwfB3iVoG9xeMCm32QV5hZ/9lFaQZJVaXfz9aFa0IZExWzCpm7OWvp9zq9gVip/nLMg==" referrerpolicy="no-referrer" rel="stylesheet"/> integrity="sha512-T5Bneq9hePRO8JR0S/0lQ7gdW+ceLThvC80UjwkMRz+8q+4DARVZ4dqKoyENC7FcYresjfJ6ubaOgIE35irf4w=="
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> referrerpolicy="no-referrer"
<script charset="utf8" src="https://cdn.datatables.net/1.13.1/js/jquery.dataTables.min.js" type="text/javascript"></script> src="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.5.1/nouislider.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.2.0/dist/chart.umd.min.js"></script> <link crossorigin="anonymous" href="https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.5.1/nouislider.css"
<script src="./Utils.js"></script> integrity="sha512-MKxcSu/LDtbIYHBNAWUQwfB3iVoG9xeMCm32QV5hZ/9lFaQZJVaXfz9aFa0IZExWzCpm7OWvp9zq9gVip/nLMg=="
<script src="./UIUtils.js"></script> referrerpolicy="no-referrer" rel="stylesheet" />
<script src="./DataTablesFilter.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="./ColumnSearch.js"></script> <script charset="utf8" src="https://cdn.datatables.net/1.13.1/js/jquery.dataTables.min.js"
<script src="./BatchCodeTableInitializer.js"></script> type="text/javascript"></script>
<script src="./BatchcodeByCountryBarChartView.js"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js@4.2.0/dist/chart.umd.min.js"></script>
<script src="./BatchcodeByCountryBarChart.js"></script> <script src="./Utils.js"></script>
<script> <script src="./UIUtils.js"></script>
<script src="./UrlUtils.js"></script>
<script src="./DataTablesFilter.js"></script>
<script src="./ColumnSearch.js"></script>
<script src="./BatchCodeTableInitializer.js"></script>
<script src="./BatchcodeByCountryBarChartView.js"></script>
<script src="./BatchcodeByCountryBarChart.js"></script>
<script>
$(document).ready(function () { $(document).ready(function () {
const urlSearchParams = new URLSearchParams(window.location.search); const urlSearchParams = new URLSearchParams(window.location.search);
new BatchCodeTableInitializer().initialize( new BatchCodeTableInitializer().initialize(
{ {
batchCodeTableElement: $('#batchCodeTable'), batchCodeTableElement: $('#batchCodeTable'),
showCountriesColumn: UIUtils.isSearchParamYES(urlSearchParams, 'showCountriesColumn'), showCountriesColumn: UrlUtils.isSearchParamYES(urlSearchParams, 'showCountriesColumn'),
showDataTablesFilter: UIUtils.isSearchParamYES(urlSearchParams, 'showDataTablesFilter'), showDataTablesFilter: UrlUtils.isSearchParamYES(urlSearchParams, 'showDataTablesFilter'),
}); });
}); });
</script> </script>
</head> </head>
<body> <body>
<h1>Batch Codes of Coronavirus 2019 Vaccines</h1> <h1>Batch Codes of Coronavirus 2019 Vaccines</h1>
<table class="display" id="batchCodeTable"> <table class="display" id="batchCodeTable">
<thead> <thead>
<tr> <tr>
<th>Batch</th> <th>Batch</th>
<th>Adverse Reaction Reports</th> <th>Adverse Reaction Reports</th>
<th>Deaths</th> <th>Deaths</th>
<th>Disabilities</th> <th>Disabilities</th>
<th>Life-Threatening Illnesses</th> <th>Life-Threatening Illnesses</th>
<th>Hospitalizations</th> <th>Hospitalizations</th>
<th>Company</th> <th>Company</th>
<th>Severe reports</th> <th>Severe reports</th>
<th>Lethality</th> <th>Lethality</th>
<th>Countries</th> <th>Countries</th>
</tr> </tr>
</thead> </thead>
</table> </table>
<footer> <footer>
<dl> <dl>
<dt>Data Source:</dt> <dt>Data Source:</dt>
<dd><a href="https://vaers.hhs.gov/data/datasets.html" target="_blank">Vaccine Adverse Event Reporting System <dd><a href="https://vaers.hhs.gov/data/datasets.html" target="_blank">Vaccine Adverse Event Reporting System
(VAERS)</a></dd> (VAERS)</a></dd>
<dt>Last updated:</dt> <dt>Last updated:</dt>
<dd id="last_updated">July 05, 2024</dd> <dd id="last_updated">July 05, 2024</dd>
</dl> </dl>
<span id="forkongithub"><a href="https://github.com/KnollFrank/HowBadIsMyBatch" target="_blank">Fork me on <span id="forkongithub"><a href="https://github.com/KnollFrank/HowBadIsMyBatch" target="_blank">Fork me on
GitHub</a></span> GitHub</a></span>
<div class="clearfix"></div> <div class="clearfix"></div>
</footer> </footer>
<template id="template-canvas"> <template id="template-chartWithSlider">
<canvas></canvas> <div class="chartWithSlider">
</template> <div class="chartContainer">
<template id="template-chartWithSlider"> <canvas class="canvas"></canvas>
<div class="chartWithSlider"> </div>
<div class="chartContainer"> <!-- FK-TODO: remove sliderContainer and slider -->
<canvas class="canvas"></canvas> <div class="sliderContainer">
</div> <div class="slider"></div>
<!-- FK-TODO: remove sliderContainer and slider --> </div>
<div class="sliderContainer"> </div>
<div class="slider"></div> </template>
</div>
</div>
</template>
</body> </body>
</html> </html>