Skip to content
Snippets Groups Projects
Commit 965f2854 authored by Patrick Jentsch's avatar Patrick Jentsch
Browse files

Add comments to JavaScript and some restructuring

parent f101a742
No related branches found
No related tags found
No related merge requests found
// 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
}
};
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.
......
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`.
......
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`.
......
......@@ -119,76 +119,29 @@
<script>
// TODO: Implement an app.run method and use this for all of the following
const app = new App.App();
app.init();
// Check if the current user is authenticated
{%- if current_user.is_authenticated %}
// TODO: Set this as a property of the app object
const currentUserId = {{ current_user.hashid|tojson }};
// Initialize components for current user
// Subscribe to the current user's data events
app.subscribeUser(currentUserId)
.catch((error) => {throw JSON.stringify(error);});
// Get the current user's data
app.getUser(currentUserId, true, true)
.catch((error) => {throw JSON.stringify(error);});
{%- endif %}
// Disable all option elements with no value
for (let optionElement of document.querySelectorAll('option[value=""]')) {
optionElement.disabled = true;
}
for (let optgroupElement of document.querySelectorAll('optgroup[label=""]')) {
for (let c of optgroupElement.children) {
optgroupElement.parentElement.insertAdjacentElement('afterbegin', c);
}
optgroupElement.remove();
}
// Set the data-length attribute on textareas/inputs with the maxlength attribute
for (let inputElement of document.querySelectorAll('textarea[maxlength], input[maxlength]')) {
inputElement.dataset.length = inputElement.getAttribute('maxlength');
}
// Initialize components
M.AutoInit();
M.CharacterCounter.init(document.querySelectorAll('input[data-length], textarea[data-length]'));
M.Dropdown.init(
document.querySelectorAll('#nav-more-dropdown-trigger'),
{alignment: 'right', constrainWidth: false, coverTrigger: false}
);
ResourceDisplays.autoInit();
ResourceLists.autoInit();
Forms.autoInit();
// Check if the current user hasn't accepted the terms of use yet
{%- if not current_user.terms_of_use_accepted %}
M.Modal.getInstance(document.querySelector('#terms-of-use-modal')).open();
{%- endif %}
{%- endif %}
// Display flashed messages
for (let [category, message] of {{ get_flashed_messages(with_categories=True)|tojson }}) {
app.flash(message, message);
}
// Initialize manual modal
let manualModalTableOfContentsElement = document.querySelector('#manual-modal-table-of-contents');
let manualModalTableOfContents = M.Tabs.init(manualModalTableOfContentsElement);
let manualModalElement = document.querySelector('#manual-modal');
let manualModal = M.Modal.init(
manualModalElement,
{
onOpenStart: (manualModalElement, modalTriggerElement) => {
if ('manualModalChapter' in modalTriggerElement.dataset) {
manualModalTableOfContents.select(modalTriggerElement.dataset.manualModalChapter);
}
}
}
);
// Initialize terms of use modal
const termsOfUseModal = document.getElementById('terms-of-use-modal');
M.Modal.init(
termsOfUseModal,
{
dismissible: false,
onCloseEnd: () => {
requests.users.entity.acceptTermsOfUse();
}
}
);
{% if current_user.is_authenticated and not current_user.terms_of_use_accepted %}
termsOfUseModal.M_Modal.open();
{% endif %}
</script>
<div id="manual-modal" class="modal no-autoinit">
<div class="modal-content">
<h2>Manual</h2>
<ul class="tabs no-autoinit" id="manual-modal-table-of-contents">
<ul class="tabs" id="manual-modal-toc">
<li class="tab"><a href="#manual-modal-introduction">Introduction</a></li>
<li class="tab"><a href="#manual-modal-registration-and-log-in">Registration and Log in</a></li>
<li class="tab"><a href="#manual-modal-dashboard">Dashboard</a></li>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment