Skip to content

Instantly share code, notes, and snippets.

@plugnburn
Last active July 7, 2016 19:45
Show Gist options
  • Save plugnburn/07c8cd7387c9d7bdc610 to your computer and use it in GitHub Desktop.
Save plugnburn/07c8cd7387c9d7bdc610 to your computer and use it in GitHub Desktop.
Z5: a nano-library bundle for client-side development

Z5

Move all your frontend development to real programming with Z5 nano-library bundle that contains:

  • Zen.js (v2) for reactive in-memory storage;
  • Q.js for DOM manipulation;
  • R.js for client-side routing;
  • XT.js for dynamic DOM construction/templating;
  • XS.js for dynamic stylesheet construction.

And all that comes in less than 3 KB (more exactly, 2782 bytes not gzipped).

Download here or include:

<script src="//cdn.rawgit.com/plugnburn/07c8cd7387c9d7bdc610/raw/2a6c401f404126d6ede361b10c6e4d25df3cfb0e/z5.js"></script>

See also a skeleton to get started with Z5.

!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)
!function(e,f){function k(a,d){return e.addEventListener(a,d,!1)}function q(a){return function(d){function b(c,u,g){b.l=[].slice.call(d.querySelectorAll(a));if(c)for(g=b.l.slice();el=g.shift();)c(el);return b}b.val=function(c,a,d){for(d=b.l.slice();a=d.shift();){if(null==c)return"value"in a?a.value:a.innerHTML;"value"in a?(a.value=c,"select"===a.tagName.toLowerCase()&&(a.Q("option")(function(a){a.selected=!1}),a.Q('option[value="'+c+'"]')(function(a){a.selected=!0}))):a.innerHTML=c}return b};b.on=function(c,d,g){for(c=c.split(" ");g=c.shift();)k(g,function(c){c.target.closest(a)&&d.call(c.target,c)});return b};return b}(this)}function r(a,d,b,c){for(;null!=(c=a.shift());)if(""+c===c||+c===c)d.appendChild(f.createTextNode(c));else if("[object Object]"===""+c)for(b in c)d.setAttribute(b,c[b]);else r(c,b=f.createElement(c.shift())),d.appendChild(b)}var l=JSON,t=Object.defineProperties,h={};t(e.Zen={},{sub:{value:function(a,d,b){for(a=a.split(" ");b=a.shift();)!function(a){var b=this[a],g=b,e={};h[a]?h[a].push(d):(h[a]=[d],e[a]={get:function(){return g},set:function(d,e,f){b=g;g=d;e=h[a];for(f=e.length;e[--f];)e[f].call(this,a,b,g);return d},configurable:!0},delete Zen[a]&&t(Zen,e))}(b)}},"import":{value:function(a,d){if(""+a===a)try{a=l.parse(a)}catch(b){}if(a)for(d in a)a.hasOwnProperty(d)&&(this[d]=a[d]);return this}},toString:{value:function(){return l.stringify(this)}},req:{value:function(a,d,b,c){c=new XMLHttpRequest;c.open(b?"POST":"GET",d,!0);c.onload=function(b){b=c.responseText;try{b=l.parse(b)}catch(d){}this[a]=b};c.send(b)}}});e.Q=q.bind(f);!function(a){a.Q=q;a.matches||(a.matches=a.matchesSelector||a.webkitMatchesSelector||a.mozMatchesSelector||a.msMatchesSelector||function(a,b){b=this;return[].some.call(f.querySelectorAll(a),function(a){return a===b})});a.closest=a.closest||function b(a){return this.parentNode?this.matches(a)?this:b.call(this.parentNode,a):null}}(e.Element.prototype);var m={},p=function(a){a=e.location;n.go(a.pathname+a.search+a.hash,!0)},n=function(a,d,b){b={p:[],h:d};var c=a.replace(/\//g,"\\/"),e=a.match(/:([^/]+)/ig);if(null!=e)for(;d=e.shift();)b.p.push(d.slice(1)),c=c.replace(d,"([^/]+)");b.r=RegExp(c,"i");m[a]=b};n.go=function(a,d){var b,c,f,g;for(b in m)if(c=a.match((f=m[b]).r)){c.shift();b={};for(g=f.p.length;g;)b[f.p[--g]]=c.shift();d||e.history.pushState({},"",a);return f.h(b)}};e.R=n;k("popstate",p);~["interactive","complete"].indexOf(document.readyState)?p():k("DOMContentLoaded",p);e.XT=function(a,d){r(a.slice(),d=f.createDocumentFragment());return d};e.XS=function(a,d,b,c,e){f.head.appendChild(d=f.createElement("style"));for(b=a.slice();c=b.shift();){for(e=c.shift()+"{";a=c.shift();)e+=a[0]+":"+a[1]+";";d.sheet.insertRule(e+"}",d.sheet.cssRules.length)}return d}}(window,document)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment