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:
@@ -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 = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
// Shared JS file names: routing, main, shared, localStorage, appDialogs
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
*/
|
||||
*/
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
@@ -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"})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user