From 965f2854b2da090116fef1d9ca30c38541fdc96e Mon Sep 17 00:00:00 2001
From: Patrick Jentsch
Date: Tue, 24 Oct 2023 15:09:20 +0200
Subject: [PATCH] Add comments to JavaScript and some restructuring
---
app/static/js/app/app.js | 95 ++++++++++++++++++++++++
app/static/js/forms/index.js | 2 +-
app/static/js/resource-displays/index.js | 2 +-
app/static/js/resource-lists/index.js | 2 +-
app/templates/_scripts.html.j2 | 71 +++---------------
app/templates/main/_manual_modal.html.j2 | 2 +-
6 files changed, 111 insertions(+), 63 deletions(-)
diff --git a/app/static/js/app/app.js b/app/static/js/app/app.js
index 92a5c546..fefabd1a 100644
--- a/app/static/js/app/app.js
+++ b/app/static/js/app/app.js
@@ -1,3 +1,8 @@
+// IDEA: Split the App logic into seperate units
+// - App.Data
+// - App.IO (name is WIP)
+// - App.UI
+
App.App = class App {
constructor() {
this.data = {
@@ -101,4 +106,94 @@ App.App = class App {
// Apply Patch
jsonpatch.applyPatch(this.data, filteredPatch);
}
+
+ init() {
+ this.initUi();
+ }
+
+ initUi() {
+ /* Pre-Initialization fixes */
+ // #region
+
+ // Flask-WTF sets the standard HTML maxlength Attribute on input/textarea
+ // elements to specify their maximum length (in characters). Unfortunatly
+ // Materialize won't recognize the maxlength Attribute, instead it uses
+ // the data-length Attribute. It's conversion time :)
+ for (let elem of document.querySelectorAll('input[maxlength], textarea[maxlength]')) {
+ elem.dataset.length = elem.getAttribute('maxlength');
+ elem.removeAttribute('maxlength');
+ }
+
+ // To work around some limitations with the Form setup of Flask-WTF.
+ // HTML option elements with an empty value are considered as placeholder
+ // elements. The user should not be able to actively select these options.
+ // So they get the disabled attribute.
+ for (let optionElement of document.querySelectorAll('option[value=""]')) {
+ optionElement.disabled = true;
+ }
+
+ // TODO: Check why we are doing this.
+ for (let optgroupElement of document.querySelectorAll('optgroup[label=""]')) {
+ for (let c of optgroupElement.children) {
+ optgroupElement.parentElement.insertAdjacentElement('afterbegin', c);
+ }
+ optgroupElement.remove();
+ }
+
+ // #endregion
+
+ /* Initialize Materialize Components */
+ // #region
+
+ // Automatically initialize Materialize Components that do not require
+ // additional configuration.
+ M.AutoInit();
+
+ // CharacterCounters
+ // Materialize didn't include the CharacterCounter plugin within the
+ // AutoInit method (maybe they forgot it?). Anyway... We do it here. :)
+ M.CharacterCounter.init(document.querySelectorAll('input[data-length]:not(.no-autoinit), textarea[data-length]:not(.no-autoinit)'));
+
+ // Header navigation "more" Dropdown.
+ M.Dropdown.init(
+ document.querySelector('#nav-more-dropdown-trigger'),
+ {
+ alignment: 'right',
+ constrainWidth: false,
+ coverTrigger: false
+ }
+ );
+
+ // Manual modal
+ M.Modal.init(
+ document.querySelector('#manual-modal'),
+ {
+ onOpenStart: (modalElement, modalTriggerElement) => {
+ if ('manualModalChapter' in modalTriggerElement.dataset) {
+ let manualModalTocElement = document.querySelector('#manual-modal-toc');
+ let manualModalToc = M.Tabs.getInstance(manualModalTocElement);
+ manualModalToc.select(modalTriggerElement.dataset.manualModalChapter);
+ }
+ }
+ }
+ );
+
+ // Terms of use modal
+ M.Modal.init(
+ document.querySelector('#terms-of-use-modal'),
+ {
+ dismissible: false,
+ onCloseEnd: (modalElement) => {
+ Requests.users.entity.acceptTermsOfUse();
+ }
+ }
+ );
+ // #endregion
+
+ // #region Nopaque Components
+ ResourceDisplays.AutoInit();
+ ResourceLists.AutoInit();
+ Forms.AutoInit();
+ // #endregion Nopaque Components
+ }
};
diff --git a/app/static/js/forms/index.js b/app/static/js/forms/index.js
index 02909448..a6d098dd 100644
--- a/app/static/js/forms/index.js
+++ b/app/static/js/forms/index.js
@@ -1,6 +1,6 @@
var Forms = {};
-Forms.autoInit = () => {
+Forms.AutoInit = () => {
for (let propertyName in Forms) {
let property = Forms[propertyName];
// Call autoInit of all properties that are subclasses of Forms.BaseForm.
diff --git a/app/static/js/resource-displays/index.js b/app/static/js/resource-displays/index.js
index 8cc8809e..a559189d 100644
--- a/app/static/js/resource-displays/index.js
+++ b/app/static/js/resource-displays/index.js
@@ -1,6 +1,6 @@
var ResourceDisplays = {};
-ResourceDisplays.autoInit = () => {
+ResourceDisplays.AutoInit = () => {
for (let propertyName in ResourceDisplays) {
let property = ResourceDisplays[propertyName];
// Call autoInit of all properties that are subclasses of `ResourceDisplays.ResourceDisplay`.
diff --git a/app/static/js/resource-lists/index.js b/app/static/js/resource-lists/index.js
index 513da46b..1683a6a5 100644
--- a/app/static/js/resource-lists/index.js
+++ b/app/static/js/resource-lists/index.js
@@ -1,6 +1,6 @@
var ResourceLists = {};
-ResourceLists.autoInit = () => {
+ResourceLists.AutoInit = () => {
for (let propertyName in ResourceLists) {
let property = ResourceLists[propertyName];
// Call autoInit of all properties that are subclasses of `ResourceLists.ResourceList`.
diff --git a/app/templates/_scripts.html.j2 b/app/templates/_scripts.html.j2
index 1fd32f7e..78b7af60 100644
--- a/app/templates/_scripts.html.j2
+++ b/app/templates/_scripts.html.j2
@@ -119,76 +119,29 @@
diff --git a/app/templates/main/_manual_modal.html.j2 b/app/templates/main/_manual_modal.html.j2
index 3eb5d4a1..9233fb0d 100644
--- a/app/templates/main/_manual_modal.html.j2
+++ b/app/templates/main/_manual_modal.html.j2
@@ -1,7 +1,7 @@