|
!function(w,d) { |
|
|
|
// helper common utils |
|
|
|
function AEL(ev, cb) {return w.addEventListener(ev, cb, false)} |
|
|
|
//Zen.js ------------------------------------------------------------------------ |
|
|
|
var J = JSON, dp = Object.defineProperties, subbers = {} |
|
dp(w.Zen = {}, { |
|
sub: {value: function(propSet, cb, singleProp) { |
|
for(propSet = propSet.split(' ');singleProp = propSet.shift();) { |
|
!function(prop){ |
|
var oldval = this[prop], newval = oldval, o = {} |
|
if(subbers[prop]) subbers[prop].push(cb) |
|
else { |
|
subbers[prop] = [cb] |
|
o[prop] = { |
|
get: function(){return newval}, |
|
set: function(val, s, i) { |
|
oldval = newval, newval = val |
|
for(s = subbers[prop],i = s.length;s[--i];) s[i].call(this, prop, oldval, newval) |
|
return val |
|
}, |
|
configurable: true |
|
} |
|
if(delete Zen[prop]) dp(Zen, o) |
|
} |
|
}(singleProp) |
|
} |
|
}}, |
|
'import' : {value: function(obj, k) { |
|
if(''+obj === obj) try{obj=J.parse(obj)} catch(e) {} |
|
if(obj) |
|
for(k in obj) |
|
if(obj.hasOwnProperty(k)) this[k] = obj[k] |
|
return this |
|
}}, |
|
toString: {value: function(){return J.stringify(this)}}, |
|
req: {value: function(key, url, data, xhr) { |
|
xhr = new XMLHttpRequest |
|
xhr.open(data ? 'POST' : 'GET', url, true) |
|
xhr.onload = function(res) { |
|
res = xhr.responseText |
|
try {res = J.parse(res)} catch(e) {} |
|
this[key] = res |
|
} |
|
xhr.send(data) |
|
}} |
|
}) |
|
|
|
// Q.js -------------------------------------------------------------------------- |
|
|
|
function query(sel) { |
|
return (function(target) { |
|
function retF(cb, e, l) { |
|
retF.l=[].slice.call(target.querySelectorAll(sel)) |
|
if(cb) for(l=retF.l.slice();el=l.shift();) cb(el) |
|
return retF |
|
} |
|
retF.val = function(val, el, l) { |
|
for(l=retF.l.slice();el=l.shift();) { |
|
if(val==null) |
|
return 'value' in el ? el.value : el.innerHTML |
|
else { |
|
if('value' in el) { |
|
el.value = val |
|
if (el.tagName.toLowerCase()==='select') { |
|
el.Q('option')(function(opt){opt.selected = false}) |
|
el.Q('option[value="'+val+'"]')(function(opt){opt.selected = true}) |
|
} |
|
} |
|
else |
|
el.innerHTML = val |
|
} |
|
} |
|
return retF |
|
} |
|
retF.on = function(evNames, evCb, ev){ |
|
for(evNames = evNames.split(' ');ev=evNames.shift();) |
|
AEL(ev, function(e) { |
|
e.target.closest(sel) && evCb.call(e.target, e) |
|
}) |
|
return retF |
|
} |
|
return retF |
|
})(this) |
|
} |
|
w.Q = query.bind(d) |
|
!function(EP){ |
|
EP.Q = query |
|
EP.matches || (EP.matches = EP.matchesSelector || EP.webkitMatchesSelector || EP.mozMatchesSelector || EP.msMatchesSelector || function(sel, el) { |
|
el = this; |
|
return [].some.call(d.querySelectorAll(sel), function(e){return e === el}) |
|
}) |
|
EP.closest = EP.closest || function closest(sel) { |
|
return this.parentNode ? |
|
this.matches(sel) ? this : closest.call(this.parentNode, sel) |
|
: null |
|
} |
|
}(w.Element.prototype) |
|
|
|
// R.js -------------------------------------------------------------------------- |
|
|
|
var routeCache = {}, callRoutePath = function(l){l = w.location; routing.go(l.pathname + l.search + l.hash, true)}, |
|
routing = function(path, cb, cacheObj) { |
|
var cacheObj = {p: [], h: cb}, param, |
|
regexString = path.replace(/\//g, '\\/'), |
|
paramMatches = path.match(/:([^/]+)/ig) |
|
if(paramMatches != null) |
|
for(;param = paramMatches.shift();) { |
|
cacheObj.p.push(param.slice(1)) |
|
regexString = regexString.replace(param, '([^/]+)') |
|
} |
|
cacheObj.r = RegExp(regexString, 'i') |
|
routeCache[path] = cacheObj |
|
} |
|
routing.go = function(path, preventHistoryUpdates) { |
|
var formalPath, matchList, cacheObj, params, i |
|
for(formalPath in routeCache) |
|
if(matchList = path.match((cacheObj = routeCache[formalPath]).r)) { |
|
matchList.shift() |
|
for(params = {}, i = cacheObj.p.length;i;) |
|
params[cacheObj.p[--i]] = matchList.shift() |
|
if(!preventHistoryUpdates) w.history.pushState({}, '', path) |
|
return cacheObj.h(params) |
|
} |
|
} |
|
w.R = routing |
|
AEL('popstate', callRoutePath) |
|
if(~['interactive','complete'].indexOf(document.readyState)) callRoutePath() |
|
else AEL('DOMContentLoaded', callRoutePath) |
|
|
|
// XT.js -------------------------------------------------------------------------- |
|
|
|
function xtNodeRender(tplArr, parent, k, o) { |
|
for(;(o=tplArr.shift())!=null;) { |
|
if(''+o === o || +o === o) //scalar |
|
parent.appendChild(d.createTextNode(o)) |
|
else if(''+o === '[object Object]') //object |
|
for(k in o) parent.setAttribute(k, o[k]) |
|
else { //array |
|
xtNodeRender(o, k = d.createElement(o.shift())) |
|
parent.appendChild(k) |
|
} |
|
} |
|
} |
|
w.XT = function(tplArr, docFrag) { |
|
xtNodeRender(tplArr.slice(), docFrag = d.createDocumentFragment()) |
|
return docFrag |
|
} |
|
|
|
// XS.js -------------------------------------------------------------------------- |
|
|
|
w.XS = function(arr, style, list, rule, ruleString) { |
|
d.head.appendChild(style = d.createElement('style')) |
|
for(list = arr.slice(); rule = list.shift();) { |
|
for(ruleString = rule.shift()+'{';arr = rule.shift();) ruleString += arr[0] + ':' + arr[1] + ';' |
|
style.sheet.insertRule(ruleString+'}', style.sheet.cssRules.length) |
|
} |
|
return style |
|
} |
|
}(window,document) |