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 @@