Created
January 26, 2016 22:21
-
-
Save heisters/eb89a0f85295c33babc9 to your computer and use it in GitHub Desktop.
Simple window hash URL navigation
This file contains hidden or 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
(function( exports ) { | |
var onDOMReady = function( fn ) { | |
if ( document.readyState !== 'loading' ) { | |
fn(); | |
} else { | |
document.addEventListener( "DOMContentLoaded", fn ); | |
} | |
}; | |
exports.onDOMReady = onDOMReady; | |
})(this); | |
/** | |
* MicroEvent - to make any js object an event emitter (server or browser) | |
* | |
* - pure javascript - server compatible, browser compatible | |
* - dont rely on the browser doms | |
* - super simple - you get it immediatly, no mistery, no magic involved | |
* | |
* - create a MicroEventDebug with goodies to debug | |
* - make it safer to use | |
*/ | |
(function( exports ) { | |
var MicroEvent = function(){}; | |
MicroEvent.prototype = { | |
on: function(event, fct){ | |
this._events = this._events || {}; | |
this._events[event] = this._events[event] || []; | |
this._events[event].push(fct); | |
}, | |
off: function(event, fct){ | |
this._events = this._events || {}; | |
if( event in this._events === false ) return; | |
this._events[event].splice(this._events[event].indexOf(fct), 1); | |
}, | |
emit: function(event /* , args... */){ | |
this._events = this._events || {}; | |
if( event in this._events === false ) return; | |
for(var i = 0; i < this._events[event].length; i++){ | |
this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1)); | |
} | |
} | |
}; | |
exports.MicroEvent = MicroEvent; | |
})(this); | |
(function( exports ) { | |
var HashManager = function(options) { | |
if (options == null) options = {}; | |
this.defaults = options.defaults || {}; | |
}; | |
HashManager.prototype = new MicroEvent(); | |
Object.defineProperties( HashManager.prototype, { | |
bind: { value: function() { | |
onDOMReady( this.onHashChange.bind( this ) ); | |
window.addEventListener( "hashchange", this.onHashChange.bind( this ) ); | |
} } | |
, onHashChange: { value: function( event ) { | |
if ( event ) event.preventDefault(); | |
this.current = this.getAll(); | |
this.emit('change', this); | |
this.old = this.current; | |
return false; | |
} } | |
, changed: { value: function(param) { | |
if (this.old == null) return true; | |
return JSON.stringify(this.get(param)) !== JSON.stringify(this.get(param, this.old)); | |
} } | |
, getAll: { value: function() { | |
var compact = function(a) { return a.reduce(function(a2, e) { if (e !== "") a2.push(e); return a2; }, []); } | |
, decode = function(s) { return decodeURIComponent(s.replace(/\+/g, " ")); } | |
, hashParams = {} | |
, part = void 0 | |
, query = window.location.hash.substring(1) | |
, regex = /([^;=]+)=?([^;]*)/g | |
, split = function(s) { return s.split(/,/g); } | |
; | |
while ( part = regex.exec(query) ) { | |
hashParams[decode(part[1])] = compact(split(decode(part[2]))); | |
} | |
return hashParams; | |
} } | |
, get: { value: function(param, params) { | |
if (params == null) params = this.current; | |
if (params === void 0) return void 0; | |
return params[param] || this.defaults[param] || []; | |
} } | |
, set: { value: function(param, value) { | |
var current; | |
if ( !Array.isArray(value) ) value = [value]; | |
current = this.getAll(); | |
current[param] = value; | |
this.setAll(current); | |
} } | |
, setAll: { value: function(params) { | |
var keys = Object.keys(params).sort() | |
, keysAndValues = []; | |
for ( var i = 0, l = keys.length; i < l; ++i ) { | |
var key = keys[i]; | |
keysAndValues.push("" + key + "=" + (params[key].join(",").replace(/\s/g, '+'))); | |
} | |
history.pushState( null, null, "#" + (keysAndValues.join(";")) ); | |
} } | |
, remove: { value: function(param) { | |
var current = this.getAll(); | |
delete current[param]; | |
this.setAll(current); | |
} } | |
, setDefault: { value: function(param, value) { | |
this.defaults[param] = value; | |
} } | |
, bindLinks: { value: function(delegateEl) { | |
delegateEl.addEventListener( "click", function( event ) { | |
if ( event.target.matches( "a[href^='#']" ) ) { | |
event.preventDefault(); | |
var params = event.target.getAttribute("href").substr(1).split('='); | |
this.set( params[0], params[1] ); | |
} | |
}.bind( this ) ); | |
} } | |
} ); | |
exports.HashManager = HashManager; | |
})(this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment