Last active
December 10, 2019 23:51
-
-
Save bellydrum/b8d482c63f81615aa22a51904bd3d420 to your computer and use it in GitHub Desktop.
Modular application object
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* An all-purpose Javascript object for general and specific application functionality. | |
* | |
* The app object is intended to be defined only once and stored in the browser cache. | |
* | |
* @note Documented using a variant of JSDoc standards. | |
* @see https://devdocs.io/jsdoc/ | |
* @see https://devhints.io/jsdoc | |
* | |
* @version 1.1.0 | |
* @description Added getCookieWrapper method to INIT FUNCTIONS. | |
* | |
* @link https://gist.github.com/bellydrum/b8d482c63f81615aa22a51904bd3d420 | |
* @author David Maness <[email protected]> | |
* @since x.x.x | |
*/ | |
(() => { | |
document.addEventListener( 'DOMContentLoaded', () => { | |
const app = { | |
/** | |
* GLOBALS | |
* | |
* Variables referenced throughout the application object. | |
*/ | |
csrftoken: null, // TODO - set in requestHelper.es6 | |
cookie: null, | |
onDesktop: null, // TODO - define in utils.es6 | |
/** | |
* DOM LISTENERS | |
* | |
* Functions that are triggered by user interaction with the DOM. | |
* | |
* Listeners need to be defined after their respective DOM elements have been rendered. | |
* Adding a DOM element with an associated listener after initial page load requires the listener to be re-defined. | |
* See the definition of activateListeners() for more information on this. | |
* | |
* Application functions used within these listeners are defined in the PRIVATE FUNCTIONS section. | |
*/ | |
/** | |
* PRIVATE FUNCTIONS | |
* | |
* Reserved for internal use by this application. | |
*/ | |
activateDataEndpoints: ( className, excludedClass=null ) => { | |
/** | |
* Turns DOM element(s) into active hyperlinks based on that elements data-endpoint attribute value. | |
* | |
* @usage | |
* target: <div class="className" data-endpoint="cool-website.com"> ... </div> | |
* example: activateDataEndpoints( "className" ) | |
* | |
* @param {string} className | |
* the CSS class name that refers to 1 or more elements whose hyperlink needs activation. | |
* @param {string} [excludedClass] | |
* the CSS class name that refers to 1 or more elements that this function will ignore. | |
* | |
* @note | |
* The target DOM elements data-endpoint attribute value must be a valid URL. | |
* | |
* @return {null} This function returns nothing. | |
* | |
*/ | |
Array.from( document.getElementsByClassName( className ) ).forEach(( element ) => { | |
if ( !( element.classList.contains( excludedClass ) ) ) { | |
element.addEventListener('click', () => { | |
location.href = element.getAttribute('data-endpoint') | |
}) | |
} | |
}) | |
}, | |
/** | |
* INIT FUNCTIONS | |
* | |
* Activate parts of the application and make them interactive. | |
* | |
* Executed on page load or wherever necessary. | |
* No parameters are required for any of these functions. | |
* Not to be confused with PRIVATE FUNCTIONS; while private, these are used only one time by activate(). | |
*/ | |
activateLinks: () => { | |
/** | |
* Activates specified DOM elements as hyperlinks. | |
* | |
* See the definition of activateDataEndpoints() to see how this works. | |
*/ | |
app.activateDataEndpoints('main-navbar-item', 'navbar-menu-parent') | |
app.activateDataEndpoints('footer-link') | |
}, | |
activateListeners: () => { | |
/** | |
* Add listeners to their respective DOM elements. | |
* | |
* Everything is wrapped in an immediately-invoked function expression (IIFE). | |
* At the end of this block is a listener that fires when the user leaves the page. | |
* | |
* @see IIFE (immediately-invoked function expressions) | |
* @link https://developer.mozilla.org/en-US/docs/Glossary/IIFE | |
* | |
* @see document.querySelector | |
* @link https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector#Syntax | |
* | |
* @see target.addEventListener | |
* @link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Syntax | |
* | |
*/ | |
(() => { | |
// All standard event listeners go below. | |
/* | |
* Standard event listeners stop here. | |
* Below is reserved for the listener fired upon page exit. | |
*/ | |
window.addEventListener('beforeunload', () => { | |
/** | |
* This listener executes when the user leaves the page. | |
* | |
* @note | |
* Returning a non-empty string will prompt the user to confirm leaving the page. | |
* | |
* @see BeforeUnloadEvent | |
* @link https://developer.mozilla.org/en-US/docs/Web/API/BeforeUnloadEvent | |
* | |
* @return {null} | |
*/ | |
return null | |
}) | |
})() | |
}, | |
createCookieWrapper: () => { | |
/** | |
* Creates and returns a tool for accessing and updating the document cookie. | |
* | |
* @note | |
* It may be more beneficial to create and use a custom ES6 CookieWrapper class instead. | |
* | |
* @see Document.cookie | |
* @link https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie | |
* | |
* @see CookieHelper | |
* @link https://gist.github.com/bellydrum/cfc7869243b4d5c4e7ae710ea59edf67 | |
* | |
* @returns {Object} CookieWrapper | |
* A Javascript object with methods that allow access to the document cookie. | |
* | |
*/ | |
const cookieWrapper = { | |
getAsObject() { | |
/** | |
* Returns the document cookie as a Javascript object. | |
* | |
* @returns {Object.<string, string>} | |
* Object that contains the values of the document cookie at the time of execution. | |
*/ | |
let cookieObject = {} | |
document.cookie.split( '; ' ).forEach( item => { | |
cookieObject[ item.split( '=' )[0] ] = item.split( '=' )[1] | |
}) | |
return cookieObject | |
}, | |
hasKey( key ) { | |
/** | |
* Determines whether or not the cookie contains a given key. | |
* | |
* @param {string} key | |
* @returns {bool} | |
*/ | |
const cookieObject = this.getAsObject() | |
return Object.keys( cookieObject ).includes( key ) | |
}, | |
getObjectByKey( key ) { | |
/** | |
* Takes a key and returns it with its value according to the document cookie. | |
* | |
* @param {string} key | |
* Used to parse the document cookie for a value. | |
* @returns {Object.<string, string>} | |
*/ | |
return { key: this.getValueByKey( key ) } | |
}, | |
getValueByKey( key ) { | |
/** | |
* Takes a key and returns only its value according to the document cookie. | |
* | |
* @param {string} key | |
* Used to parse the document cookie for a value. | |
* @returns {string} | |
* The value of the given key according to the document cookie. | |
*/ | |
return this.getAsObject()[ key ] | |
}, | |
/* | |
* Methods above do NOT alter the document cookie. | |
* Methods below DO alter the document cookie. | |
*/ | |
addObject( object ) { | |
/** | |
* Updates the document cookie. | |
* | |
* @note | |
* Immediately alters the document cookie with all given {key:value} pairs. | |
* | |
* @param {Object.<string, string>} object | |
* Values to be added to the cookie. | |
* @returns {null} | |
*/ | |
Object.keys( object ).forEach( key => { | |
document.cookie = `${ key }=${ object[ key ] };` | |
}) | |
}, | |
deleteByKey( key ) { | |
/** | |
* Takes a key and deletes its value in the document cookie. | |
* | |
* @note | |
* Immediately alters the document cookie. | |
* | |
* @see How to delete a cookie. | |
* @link https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#Notes | |
* | |
* @param {string} key | |
* Key of the {key:value} pair to delete from the document cookie. | |
* @returns {null} | |
*/ | |
document.cookie = key + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;' | |
}, | |
flush() { | |
/** | |
* Deletes the document cookie. | |
* | |
* @note | |
* Immediately alters the document cookie. | |
* | |
* @see this.deleteByKey() | |
* | |
* @returns {Object.<string, string>} | |
* Object that contains only the values of the document cookie unable to be deleted. | |
*/ | |
Object.keys( this.getAsObject() ).forEach(key => {this.deleteByKey( key ) }) | |
return this.getAsObject() | |
} | |
} | |
return cookieWrapper | |
}, | |
/** | |
* ENTRY POINT | |
* | |
* The first and only function to be executed on page load. | |
*/ | |
activate: () => { | |
/** | |
* Executes the following block in order to "activate" the application on page load. | |
* | |
* All functions executed below are defined in the INIT FUNCTIONS section. | |
*/ | |
app.cookie = app.createCookieWrapper() | |
app.activateLinks() | |
app.activateListeners() | |
}, | |
} | |
// Application entry point. | |
app.activate() | |
}) | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment