UNPKG

litespeed.js

Version:

Lite & fast micro javascript framework that is easy to learn

279 lines (237 loc) 6.63 kB
window.ls.container.set('router', function (window) { /** * Takes a valid URL and return a JSON based object with all params. * This function support URL array syntax (x[]=1) * * As published at StackOverflow: * @see http://stackoverflow.com/a/8486188 * * @param URL string * @returns {*} */ let getJsonFromUrl = function (URL) { let query; if (URL) { let pos = location.search.indexOf('?'); if (pos === -1) return []; query = location.search.substr(pos + 1); } else { query = location.search.substr(1); } let result = Object.create(null); query.split('&').forEach(function (part) { if (!part) { return; } part = part.split('+').join(' '); // replace every + with space, regexp-free version let eq = part.indexOf('='); let key = eq > -1 ? part.substr(0, eq) : part; let val = eq > -1 ? decodeURIComponent(part.substr(eq + 1)) : ''; let from = key.indexOf('['); if (from === -1) { result[decodeURIComponent(key)] = val; } else { let to = key.indexOf(']'); let index = decodeURIComponent(key.substring(from + 1, to)); key = decodeURIComponent(key.substring(0, from)); if (!result[key]) { result[key] = []; } if (!index) { result[key].push(val); } else { result[key][index] = val; } } }); return result; }; let states = []; let params = getJsonFromUrl(window.location.search); let hash = window.location.hash; let current = null; let previous = null; /** * Get previous state scope * * @returns {*} */ let getPrevious = () => previous; /** * Get current state scope * * @returns {*} */ let getCurrent = () => current; /** * Set previous state scope * * @param value * @returns {*} */ let setPrevious = (value) => { previous = value; return this; }; /** * Set current state scope * * @param value * @returns {*} */ let setCurrent = (value) => { current = value; return this; }; /** * Set Param * * Set a new key & value pair to current scope * * @param key * @param value * @returns {setParam} */ let setParam = function (key, value) { params[key] = value; return this; }; /** * Get Param * * Returns param value or default if not exists * * @param key * @param def * @returns {*} */ let getParam = function (key, def) { if (key in params) { return params[key]; } return def; }; /** * Get Params * * Returns all params * * @returns {*} */ let getParams = function () { return params; }; /** * Return current state URL * @returns {string} */ let getURL = function () { return window.location.href; }; /** * State * * Adds a new application state. * * @param path string * @param view object * @returns this */ let add = function (path, view) { /** * Validation */ if (typeof path !== 'string') { throw new Error('path must be of type string'); } if (typeof view !== 'object') { throw new Error('view must be of type object'); } states[states.length++] = {/* string */ path: path, /* object */ view: view }; return this; }; /** * Match * * Compare current location and application states to find a match. * * Sort array of states based on: * http://stackoverflow.com/questions/8837454/sort-array-of-objects-by-single-key-with-date-value * * Regex is based on this StackOverflow topic: * @see http://stackoverflow.com/a/11809601 * * New Regex is based on this post: * @see https://stackoverflow.com/a/40739605/2299554 * * @param location object * @return value object|null */ let match = function (location) { let url = location.pathname; if (url.endsWith('/')) { url = url.slice(0, -1); } states.sort(function (a, b) { return b.path.length - a.path.length; }); // order by length states.sort(function (a, b) { let n = b.path.split('/').length - a.path.split('/').length; if (n !== 0) { return n; } return b.path.length - a.path.length; }); // order by number of paths parts for (let i = 0; i < states.length; i++) { let value = states[i]; value.path = (value.path.substring(0, 1) !== '/') ? location.pathname + value.path : value.path; // Support for relative paths let match = new RegExp("^" + value.path.replace(/:[^\s/]+/g, '([\\w-]+)') + "$"); let found = url.match(match); if (found) { previous = current; current = value; return value; } } return null }; /** * Change current state to given URL * * @param URL string * @param replace bool */ let change = function (URL, replace) { if (!replace) { window.history.pushState({}, '', URL); } else { window.history.replaceState({}, '', URL); } window.dispatchEvent(new PopStateEvent('popstate', {})); return this; }; let reload = function () { return change(window.location.href); }; return { setParam: setParam, getParam: getParam, getParams: getParams, getURL: getURL, add: add, change: change, reload: reload, match: match, getCurrent: getCurrent, setCurrent: setCurrent, getPrevious: getPrevious, setPrevious: setPrevious, params: params, hash: hash, reset: function () { this.params = getJsonFromUrl(window.location.search); this.hash = window.location.hash; } }; }, true, true);