1. Module bundling added to reduce server calls as each file was taking ~440 ms to load on public server.\n2. JavaScript lib files refactored with OOP for use with module bundling.

This commit is contained in:
2024-09-10 19:43:02 +01:00
parent aac01e687f
commit 0c88f161c3
7678 changed files with 778712 additions and 1254 deletions

View File

@@ -1,117 +1,85 @@
import Validation from "./validation";
function parseCSSPropertyToFloat(element, propertyName) {
var propertyText = element.css(propertyName);
export default class Common {
static parseCSSPropertyToFloat(element, propertyName) {
var propertyText = element.css(propertyName);
if (!isEmpty(propertyText)) {
if (!Validation.isEmpty(propertyText)) {
propertyText = propertyText.replace('px', '');
propertyText = propertyText.replace('px', '');
if (!isValidNumber(propertyText, true)) return parseFloat(propertyText);
if (!Validation.isValidNumber(propertyText, true)) return parseFloat(propertyText);
}
return 0.00;
}
return 0.00;
}
function scrollToElement(parent, element) {
// REQUIRED: parent has scroll-bar
parent.scrollTop(parent.scrollTop() + (element.offset().top - parent.offset().top));
}
function isElementInContainer(container, element) {
if (typeof jQuery === 'function') {
if (container instanceof jQuery) container = container[0];
if (element instanceof jQuery) element = element[0];
}
var containerBounds = container.getBoundingClientRect();
var elementBounds = element.getBoundingClientRect();
return (
containerBounds.top <= elementBounds.top &&
containerBounds.left <= elementBounds.left &&
((elementBounds.top + elementBounds.height) <= (containerBounds.top + containerBounds.height)) &&
((elementBounds.left + elementBounds.width) <= (containerBounds.left + containerBounds.width))
);
}
function getRowFromElement(element) {
return document.querySelectorAll(element).closest('tr');
}
function getCellFromElement(element) {
return document.querySelectorAll(element).closest('td');
}
function alertError(errorType, errorText) {
alert(errorType + '\n' + errorText);
}
function setPageToLoading(isLoading) {
if (isLoading) {
document.querySelectorAll(document.body).classList.add(_dataLoadingFlag);
}
else {
document.querySelectorAll(document.body).classList.remove(_dataLoadingFlag);
}
}
function setBackgroundToLoading(elId, isLoading) {
if (isEmpty(el)) {
var elObj = document.querySelectorAll(elId);
static setPageToLoading(isLoading) {
if (isLoading) {
setTimeout(function() {
elObj.innerHTML = "";
elObj.css({
"background-image": "url(" + urlImgLoading + ")",
"background-position": "center",
"background-repeat": "no-repeat"
});
}, 0);
document.querySelectorAll(document.body).classList.add(_dataLoadingFlag);
}
else {
elObj.css("background-image", "");
document.querySelectorAll(document.body).classList.remove(_dataLoadingFlag);
}
}
}
function allowClick() {
return !document.querySelectorAll("body").classList.contains(_dataLoadingFlag);
}
static setBackgroundToLoading(elId, isLoading) {
function displayOverlay(message, show, force) {
if (Validation.isEmpty(el)) {
if (show) {
_overlayLoadingCount += 1;
}
else if (force) {
_overlayLoadingCount = 0;
}
else {
_overlayLoadingCount -= 1;
if (_overlayLoadingCount < 0) _overlayLoadingCount = 0;
var elObj = document.querySelectorAll(elId);
if (isLoading) {
setTimeout(function() {
elObj.innerHTML = "";
elObj.css({
"background-image": "url(" + urlImgLoading + ")",
"background-position": "center",
"background-repeat": "no-repeat"
});
}, 0);
}
else {
elObj.css("background-image", "");
}
}
}
var loadingImg = document.querySelectorAll(idImageLoading);
var overlay = document.querySelectorAll(loadingImg.closest("div.overlay"));
if (_overlayLoadingCount == 0) {
// Prevent short glimpse of prev. content before switch to new content
// caused by data load but not fully rendered
setTimeout(function() {
overlay.fadeOut();
}, 100);
static allowClick() {
return !document.querySelectorAll("body").classList.contains(_dataLoadingFlag);
}
else if (show && _overlayLoadingCount == 1) {
// only show once
loadingImg.innerHTML = message;
overlay.style.display = "";
static displayOverlay(message, show, force) {
if (show) {
_overlayLoadingCount += 1;
}
else if (force) {
_overlayLoadingCount = 0;
}
else {
_overlayLoadingCount -= 1;
if (_overlayLoadingCount < 0) _overlayLoadingCount = 0;
}
var loadingImg = document.querySelectorAll(idImageLoading);
var overlay = document.querySelectorAll(loadingImg.closest("div.overlay"));
if (_overlayLoadingCount == 0) {
// Prevent short glimpse of prev. content before switch to new content
// caused by data load but not fully rendered
setTimeout(function() {
overlay.fadeOut();
}, 100);
}
else if (show && _overlayLoadingCount == 1) {
// only show once
loadingImg.innerHTML = message;
overlay.style.display = "";
}
}
}
}

View File

@@ -3,5 +3,4 @@ const _dataLoadingFlag = 'data-loading'
var _domParser = null;
// var hashPageCurrent; // moved to layout
const keyPublicStripe = 'pk_test_51OGrxlL7BuLKjoMpfpfw7bSmZZK1MhqMoQ5VhW2jUj7YtoEejO4vqnxKPiqTHHuh9U4qqkywbPCSI9TpFKtr4SYH007KHMWs68';
var _pageCurrent = null;
var _verbose = true;

View File

@@ -1,8 +1,10 @@
function initialiseEventHandler(selectorElement, classInitialised, eventHandler) {
document.querySelectorAll(selectorElement).forEach(function(element) {
if (element.classList.contains(classInitialised)) return;
element.classList.add(classInitialised);
eventHandler(element);
});
export default class Events {
static initialiseEventHandler(selectorElement, classInitialised, eventHandler) {
document.querySelectorAll(selectorElement).forEach(function(element) {
if (element.classList.contains(classInitialised)) return;
element.classList.add(classInitialised);
eventHandler(element);
});
}
}

View File

@@ -1,3 +0,0 @@
// Shared JS file names: routing, main, shared, localStorage, appDialogs

View File

@@ -1,5 +1,7 @@
// Local storage
import Validation from "./validation";
export default class LocalStorage {
/*
function getPageLocalStorage(pageHash) {
@@ -10,7 +12,7 @@ function getPageLocalStorage(pageHash) {
}
if (isEmpty(ls)) return {}
if (Validation.isEmpty(ls)) return {}
return ls;
}
@@ -32,19 +34,19 @@ function setupPageLocalStorage(pageHash) {
let ls = getPageLocalStorage(pageHash);
if (isEmpty(ls)) ls = {};
if (Validation.isEmpty(ls)) ls = {};
setPageLocalStorage(pageHash, ls);
}
*/
function getLocalStorage(key) {
return JSON.parse(localStorage.getItem(key));
}
static getLocalStorage(key) {
return JSON.parse(localStorage.getItem(key));
}
function setLocalStorage(key, newLS) {
localStorage.setItem(key, JSON.stringify(newLS));
}
static setLocalStorage(key, newLS) {
localStorage.setItem(key, JSON.stringify(newLS));
}
/*
function setupPageLocalStorageNext(pageHashNext) {
@@ -56,4 +58,5 @@ function setupPageLocalStorageNext(pageHashNext) {
lsNew[keyBasket] = (keyBasket in lsOld) ? lsOld[keyBasket] : {'items': []};
setPageLocalStorage(hashPageCurrent, lsNew);
}
*/
*/
}

View File

@@ -1,65 +0,0 @@
// main.js
import { initializeAPI } from './shared/api.js';
import { setupEventListeners } from './shared/events.js';
import { initializeComponents } from './components/componentInitializer.js';
import { router } from './shared/router.js';
import { CONFIG } from './config/config.js';
// DOM ready function
function domReady(fn) {
if (document.readyState !== 'loading') {
fn();
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}
// Main initialization function
function initializeApp() {
console.log('Initializing application...');
// Initialize API with base URL
initializeAPI(CONFIG.API_BASE_URL);
// Setup global event listeners
setupEventListeners();
// Initialize reusable components
initializeComponents();
// Initialize router
router.init();
// Page-specific initialization
const currentPage = document.body.dataset.page;
switch (currentPage) {
case 'home':
import('./pages/home.js').then(module => module.initHomePage());
break;
case 'about':
import('./pages/about.js').then(module => module.initAboutPage());
break;
case 'contact':
import('./pages/contact.js').then(module => module.initContactPage());
break;
default:
console.log('No specific initialization for this page');
}
console.log('Application initialized');
}
// Run the initialization when the DOM is ready
domReady(initializeApp);
// Expose a global app object if needed
window.app = {
// Add methods or properties that need to be globally accessible
reloadPage: () => {
window.location.reload();
},
navigateTo: (url) => {
router.navigateTo(url);
}
};

View File

@@ -1,107 +1,93 @@
// Argument validation
/*
function isNullOrWhitespace(v) {
let txt = JSON.stringify(v).replace('/\s\g', '');
return (txt == '' || 'null');
}
*/
export default class Validation {
/*
isNullOrWhitespace(v) {
let txt = JSON.stringify(v).replace('/\s\g', '');
return (txt == '' || 'null');
}
*/
function isEmpty(object) {
static isEmpty(object) {
let isEmpty = true;
let isEmpty = true;
if (object !== null && object !== "null" && object !== undefined && object !== "undefined") {
if (object !== null && object !== "null" && object !== undefined && object !== "undefined") {
if (object.length == undefined) {
isEmpty = false; // object exists but isn't a collection
}
else if (typeof object === "function") {
isEmpty = false; // object is function reference
}
else { // string or collection
if (object.length == undefined) {
isEmpty = false; // object exists but isn't a collection
}
else if (typeof object === "function") {
isEmpty = false; // object is reference
}
else { // string or collection
let isString = (typeof object == "string");
let isString = (typeof object == "string");
if (isString) object = object.trim();
if (isString) object = object.trim();
if (object.length > 0) {
if (object.length > 0) {
if (isString) {
isEmpty = false; // String greater than length 0
}
else {
if (typeof object[0] != "string") {
isEmpty = false;
if (isString) {
isEmpty = false; // String greater than length 0
}
else {
for(let i = 0; i < object.length; i++) {
if (object[i] != "") {
isEmpty = false;
break
if (typeof object[0] != "string") {
isEmpty = false;
}
else {
for(let i = 0; i < object.length; i++) {
if (object[i] != "") {
isEmpty = false;
break
}
}
}
}
}
}
}
return isEmpty;
}
return isEmpty;
}
function isValidNumber(value, positiveOnly) {
return !isEmpty(value) && !isNaN(value) && (!positiveOnly || parseFloat(value) > 0);
}
function getDataContentType(params) {
var data = null;
var contentType = '';
if (!isEmpty(params)) {
if (typeof params === "string") {
data = params;
contentType = "application/x-www-form-urlencoded; charset=UTF-8";
}
else {
data = JSON.stringify(params);
contentType = "application/json; charset=UTF-8";
}
static isValidNumber(value, positiveOnly) {
return !Validation.isEmpty(value) && !isNaN(value) && (!positiveOnly || parseFloat(value) > 0);
}
return { Data: data, ContentType: contentType };
}
static getDataContentType(params) {
function arrayContainsItem(array, itemValue) {
var data = null;
var contentType = '';
var hasItem = false;
if (!Validation.isEmpty(params)) {
if (!isEmpty(array) && !isEmpty(itemValue)) {
var isJQueryElementArray = array[0] instanceof jQuery;
if (isJQueryElementArray) {
for (let i = 0; i < array.length; i++) {
if (document.querySelectorAll(array[i]).is(itemValue)) {
hasItem = true;
break;
}
if (typeof params === "string") {
data = params;
contentType = "application/x-www-form-urlencoded; charset=UTF-8";
}
else {
data = JSON.stringify(params);
contentType = "application/json; charset=UTF-8";
}
}
else {
var isDate = array[0] instanceof Date;
return { Data: data, ContentType: contentType };
}
static arrayContainsItem(array, itemValue) {
var hasItem = false;
if (!Validation.isEmpty(array) && !Validation.isEmpty(itemValue)) {
var isJQueryElementArray = array[0] instanceof jQuery;
if (isJQueryElementArray) {
if (isDate) {
for (let i = 0; i < array.length; i++) {
if (array[i].getTime() === itemValue.getTime()) {
if (document.querySelectorAll(array[i]).is(itemValue)) {
hasItem = true;
break;
}
@@ -109,54 +95,69 @@ function arrayContainsItem(array, itemValue) {
}
else {
for (let i = 0; i < array.length; i++) {
var isDate = array[0] instanceof Date;
if (array[i] == itemValue) {
hasItem = true;
break;
if (isDate) {
for (let i = 0; i < array.length; i++) {
if (array[i].getTime() === itemValue.getTime()) {
hasItem = true;
break;
}
}
}
else {
for (let i = 0; i < array.length; i++) {
if (array[i] == itemValue) {
hasItem = true;
break;
}
}
}
}
}
return hasItem;
}
return hasItem;
}
function dictHasKey(d, k) {
return (k in d);
}
function areEqualDicts(dict1, dict2) {
const keys1 = Object.keys(dict1);
const keys2 = Object.keys(dict2);
if (keys1.length !== keys2.length) {
return false;
static dictHasKey(d, k) {
return (k in d);
}
for (let key of keys1) {
if (dict1[key] !== dict2[key]) {
static areEqualDicts(dict1, dict2) {
const keys1 = Object.keys(dict1);
const keys2 = Object.keys(dict2);
if (keys1.length !== keys2.length) {
return false;
}
}
return true;
}
function imageExists(url, callback) {
var img = new Image();
img.onload = function() { callback(true); };
img.onerror = function() { callback(false); };
img.src = url;
}
function validateImageUrl(id, img) {
imageExists(img, function(exists) {
if (exists) {
document.querySelectorAll("#" + id).css({ "background-image": "url(" + url + ")", "background-size": "35px 35px"})
}
})
}
for (let key of keys1) {
if (dict1[key] !== dict2[key]) {
return false;
}
}
return true;
}
static imageExists(url, callback) {
var img = new Image();
img.onload = function() { callback(true); };
img.onerror = function() { callback(false); };
img.src = url;
}
static validateImageUrl(id, img) {
Validation.imageExists(img, function(exists) {
if (exists) {
document.querySelectorAll("#" + id).css({ "background-image": "url(" + url + ")", "background-size": "35px 35px"})
}
})
}
}