Skip to content

Instantly share code, notes, and snippets.

@mofax
Last active March 15, 2017 12:13
Show Gist options
  • Save mofax/aac7117ba547ae1ad0b0277b34cef2b4 to your computer and use it in GitHub Desktop.
Save mofax/aac7117ba547ae1ad0b0277b34cef2b4 to your computer and use it in GitHub Desktop.
routing on the frontend
'use strict';
/**
* change the browser location hash
*/
function changeRoute(path, global) {
// switch the location hash of the page
if (!path.startsWith('/')) {
path = '/' + path.trim();
}
if (typeof (global.location) === 'object') {
global.location.hash = path;
}
}
/**
* create component of the routing tree
*
* @param {[]} arr - Array of nodes
* @param {Object} container - node container
* @param {Function} callback - callback function attached at the leaf
*/
function createTree(arr, container, callback) {
var previous = container;
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
if (item.startsWith(':')) {
item = ':parameter';
}
if (!previous[item]) {
if (i === arr.length - 1) {
previous[item] = callback;
} else {
previous[item] = {};
}
}
previous = previous[item];
}
}
/**
* takes url path and returns an array of nodes
*
* @param {string} path - url path
* @return {[]} nodes
*/
function scan(_path) {
let path = _path || '';
if (!path.startsWith('/')) {
path = '/' + path.trim();
}
let arr = path.split('/');
let ret = arr.splice(1);
return ret;
}
// a global container
let container = {};
/**
* register a url into the router
*/
function register(path, callback) {
createTree(scan(path), container, callback);
}
/**
* trigger the callback of a registered route
*/
function trigger(path) {
var arr = scan(path);
var params = [];
var previous = container;
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
if (!previous[item]) {
item = ':parameter';
if (!previous[item]) {
return;
} else {
params[params.length] = arr[i];
}
}
previous = previous[item];
}
if (typeof (previous) === 'function') {
previous.apply(null, params);
}
}
// redirect the page via push state
function redirect(path, title) {
if (!path) {
return;
}
global.history.pushState({}, title || 'page', path)
trigger(path);
}
/**
* init function to setup really simple routing on the browser, takes as a parameter the window object, or similar
*
* @param {Object} window - the window object
* @return {Object}
*/
function init(window) {
// listen for popstate event
if ('onpopstate' in window) {
window.addEventListener('popstate', e => {
let location = window.location;
trigger(location.pathname);
});
}
return {
register,
redirect
}
}
export default init;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment