//===== Collection of small utilities
/*
* Bind/Unbind events
*
* Usage:
* var el = document.getElementyById('#container');
* bnd(el, 'click', function() {
* console.log('clicked');
* });
*/
var bnd = function(
d, // a DOM element
e, // an event name such as "click"
f // a handler function
){
d.addEventListener(e, f, false);
}
/*
* Create DOM element
*
* Usage:
* var el = m('
Hello
');
* document.body.appendChild(el);
*
* Copyright (C) 2011 Jed Schmidt - WTFPL
* More: https://gist.github.com/966233
*/
var m = function(
a, // an HTML string
b, // placeholder
c // placeholder
){
b = document; // get the document,
c = b.createElement("p"); // create a container element,
c.innerHTML = a; // write the HTML to it, and
a = b.createDocumentFragment(); // create a fragment.
while ( // while
b = c.firstChild // the container element has a first child
) a.appendChild(b); // append the child to the fragment,
return a // and then return the fragment.
}
/*
* DOM selector
*
* Usage:
* $('div');
* $('#name');
* $('.name');
*
* Copyright (C) 2011 Jed Schmidt - WTFPL
* More: https://gist.github.com/991057
*/
var $ = function(
a, // take a simple selector like "name", "#name", or ".name", and
b // an optional context, and
){
a = a.match(/^(\W)?(.*)/); // split the selector into name and symbol.
return( // return an element or list, from within the scope of
b // the passed context
|| document // or document,
)[
"getElement" + ( // obtained by the appropriate method calculated by
a[1]
? a[1] == "#"
? "ById" // the node by ID,
: "sByClassName" // the nodes by class name, or
: "sByTagName" // the nodes by tag name,
)
](
a[2] // called with the name.
)
}
/*
* Get cross browser xhr object
*
* Copyright (C) 2011 Jed Schmidt
* More: https://gist.github.com/993585
*/
var j = function(
a // cursor placeholder
){
for( // for all a
a=0; // from 0
a<4; // to 4,
a++ // incrementing
) try { // try
return a // returning
? new ActiveXObject( // a new ActiveXObject
[ // reflecting
, // (elided)
"Msxml2", // the various
"Msxml3", // working
"Microsoft" // options
][a] + // for Microsoft implementations, and
".XMLHTTP" // the appropriate suffix,
) // but make sure to
: new XMLHttpRequest // try the w3c standard first, and
}
catch(e){} // ignore when it fails.
}
// dom element iterator: domForEach($(".some-class"), function(el) { ... });
function domForEach(els, fun) { return Array.prototype.forEach.call(els, fun); }
// createElement short-hand
e = function(a) { return document.createElement(a); }
// chain onload handlers
function onLoad(f) {
var old = window.onload;
if (typeof old != 'function') {
window.onload = f;
} else {
window.onload = function() {
old();
f();
}
}
}
//===== helpers to add/remove/toggle HTML element classes
function addClass(el, cl) {
el.className += ' ' + cl;
}
function removeClass(el, cl) {
var cls = el.className.split(/\s+/),
l = cls.length;
for (var i=0; i= 200 && xhr.status < 300) {
console.log("XHR done:", method, url, "->", xhr.status);
ok_cb(xhr.responseText);
} else {
console.log("XHR ERR :", method, url, "->", xhr.status, xhr.responseText, xhr);
err_cb(xhr.status, xhr.responseText);
}
}
console.log("XHR send:", method, url);
try {
xhr.send();
} catch(err) {
console.log("XHR EXC :", method, url, "->", err);
err_cb(599, err);
}
}
function dispatchJson(resp, ok_cb, err_cb) {
var j;
try { j = JSON.parse(resp); }
catch(err) {
console.log("JSON parse error: " + err + ". In: " + resp);
err_cb(500, "JSON parse error: " + err);
return;
}
ok_cb(j);
}
function ajaxJson(method, url, ok_cb, err_cb) {
ajaxReq(method, url, function(resp) { dispatchJson(resp, ok_cb, err_cb); }, err_cb);
}
function ajaxSpin(method, url, ok_cb, err_cb) {
$("#spinner").removeAttribute('hidden');
ajaxReq(method, url, function(resp) {
$("#spinner").setAttribute('hidden', '');
ok_cb(resp);
}, function(status, statusText) {
$("#spinner").setAttribute('hidden', '');
//showWarning("Error: " + statusText);
err_cb(status, statusText);
});
}
function ajaxJsonSpin(method, url, ok_cb, err_cb) {
ajaxSpin(method, url, function(resp) { dispatchJson(resp, ok_cb, err_cb); }, err_cb);
}
//===== main menu, header spinner and notification boxes
function hidePopup(el) {
addClass(el, "popup-hidden");
addClass(el.parentNode, "popup-target");
}
onLoad(function() {
var l = $("#layout");
var o = l.childNodes[0];
// spinner
l.insertBefore(m(''), o);
// notification boxes
l.insertBefore(m(
''), o);
// menu hamburger button
l.insertBefore(m(''), o);
// menu left-pane
var mm = m(
'\
');
l.insertBefore(mm, o);
// make hamburger button pull out menu
var ml = $('#menuLink'), mm = $('#menu');
bnd(ml, 'click', function (e) {
console.log("hamburger time");
var active = 'active';
e.preventDefault();
toggleClass(l, active);
toggleClass(mm, active);
toggleClass(ml, active);
});
// hide pop-ups
domForEach($(".popup"), function(el) {
hidePopup(el);
});
// populate menu via ajax call
var getMenu = function() {
ajaxJson("GET", "/menu", function(data) {
var html = "", path = window.location.pathname;
for (var i=0; i