statelessjs
Version:
Front end javascript library for building web applications
1,073 lines (997 loc) • 30.4 kB
JavaScript
(function(context, overload, recursive){
if (context.stateless){ // lets not do extra work when we re-loading stuff
return
}
var converter = document.createElement("div")
// --------------------------------------------------------
// The templater that does the heavy lifting kinda
// --------------------------------------------------------
var Scope = function(ele){
// detect if new or just calling it
var self = {}
if (!ele){
throw new Error("No element selected")
}
// set public methods into the prototype of this object.
var public_method = {}
Object.setPrototypeOf(self, public_method)
// define public propertyies that can be gotten with .varname
Object.defineProperty(public_method, "parent", {
enumerable: false,
configurable: false,
get: function(){
return ele.parentNode && ele.parentNode.scope
}
})
Object.defineProperty(public_method, "children", {
enumerable: false,
configurable: false,
get: recursive(function(recur, children){
children = children || ele.children
var childList = []
Array.prototype.forEach.call(children, function(item){
if (item.scope != self){
childList.push(item.scope)
}
else {
Array.prototype.push.apply(childList, recur(item.children))
}
})
return childList
})
})
Object.defineProperty(public_method, "root", {
enumerable: false,
configurable: false,
get: recursive(function(getParent, scope){
scope = scope || self
return (scope.parent)? getParent(scope.parent) : scope
})
})
// set the "scope" property of every HTML element associated to self to provide a reference to self
// most depended upon property in the framework
var recursiveDefineScope = function(ele, recur){
Object.defineProperty(ele, "scope", {
enumerable: false,
configurable: false,
get: function(){
return self
}
})
if (recur !== false){
Array.prototype.forEach.call(ele.querySelectorAll("*"), function(item){
recursiveDefineScope(item, false)
})
}
}
recursiveDefineScope(ele)
// begin dom manip functions
var listeners = {}
// public methods (kept in the prototype) for others to access
public_method.on = overload()
.args({scope:{on:"function"}, addEventListener: "function"}, "string", "function").use(function(ele, type, callback){
if (ele.scope == self){
//ele_on(ele, type, callback)
var typeList = listeners[type] || (listeners[type] = []),
repeat = false
typeList.forEach(function(elfn){
if (
(elfn.fn == callback || elfn.fn.toString() == callback.toString()) &&
(elfn.el == ele)
){
repeat = true
}
})
if (!repeat){
ele.addEventListener(type, callback)
listeners[type].push({
fn: callback,
el: ele
})
}
else {
console.warn("listener is already registered")
}
}
else {
ele.scope.on(ele, type, callback)
}
return self
})
.args({"0":"object", length:"number", forEach:"function"}, "string", "function").use(function(eles, type, callback){
eles.forEach(function(ele){
self.on(ele, type, callback)
})
return self
})
.args("string", "string", "function").use(function(selector, type, callback){
if(selector[0] == "$"){
self.elements(selector).forEach( function(ele){
self.on(ele, type, callback)
})
}
else {
console.warn("selector must begin with '$'")
}
return self
})
.args("string", "function").use(function(type, callback){
self.on(ele, type, callback)
return self
})
.args().use(function(){
console.warn("on function inputs improperly formatted")
return self
})
public_method.off = overload()
.args({scope:{off:"function"}, addEventListener: "function"}, "string", "function").use(function(ele, type, callback){
if (ele.scope == self){
var typeList = listeners[type],
found = false
typeList && typeList.forEach(function(elfn, index){
if (
(elfn.fn == callback || elfn.fn.toString() == callback.toString()) &&
elfn.el == ele
){
found = true
ele.removeEventListener(type, elfn.fn)
typeList.splice(index, 1)
}
})
if (!found){
console.warn("Listener is not currently registered")
}
}
else {
ele.scope.off(ele, type, callback)
}
return self
})
.args({"0":"object", length:"number", forEach:"function"}, "string", "function").use(function(eles, type, callback){
eles.forEach(function(ele){
self.off(ele, type, callback)
})
})
.args("string", "string", "function").use(function(selector, type, callback){
if(selector[0] == "$"){
self.elements(selector).forEach( function(ele){
self.off(ele, type, callback)
})
}
else {
console.warn("selector must begin with '$'")
}
return self
})
.args("string", "function").use(function(type, callback){
self.off(ele, type, callback)
return self
})
.args().use(function(){
console.warn("off function inputs improperly formatted")
return self
})
public_method.once = overload()
.args({scope:{off:"function"}, addEventListener: "function"}, "string", "function").use(function(ele, type, callback){
if (ele.scope == self){
var cb = function(e){
callback(e)
self.off(ele, type, cb)
}
self.on(ele, type, cb)
}
else {
ele.scope.once(ele, type, callback)
}
return self
})
.args({"0":"object", length:"number", forEach:"function"}, "string", "function").use(function(eles, type, callback){
eles.forEach(function(ele){
self.once(ele, type, callback)
})
})
.args("string", "string", "function").use(function(selector, type, callback){
if(selector[0] == "$"){
self.elements(selector).forEach( function(ele){
self.once(ele, type, callback)
})
}
else {
console.warn("selector must begin with '$'")
}
return self
})
.args("string", "function").use(function(type, callback){
self.once(ele, type, callback)
return self
})
.args().use(function(){
console.warn("once function inputs improperly formatted")
return self
})
public_method.hasClass = overload()
.args({className: "string"}, "string").use(function(ele, c){
return (ele.className.match(new RegExp("(^"+c+"$|\\s"+c+"\\s|^"+c+"\\s|\\s"+c+"$)")))? true : false
})
.args("string", "string").use(function(selector, c){
if(selector[0] == "$"){
return self.hasClass(self.element(selector), c)
}
else {
console.warn("selector must begin with '$'")
return false
}
})
.args("string").use(function(c){
return self.hasClass(ele, c)
})
.args().use(function(c){
console.warn("malformed call")
return false
})
public_method.addClass = overload()
.args({scope:"object", className:"string"}, "string", "boolean").use(function(ele, c, multiple){
if (ele.scope == self){
if (multiple || !self.hasClass(ele, c)){
ele.className += " " + c
ele.className = ele.className.replace(/(^\s+|\s+$)/g, "")
}
}
else {
ele.scope.addClass(ele, c, multiple)
}
return self
})
.args({scope:"object", className:"string"}, "string").use(function(ele, c){
self.addClass(ele, c, false)
return self
})
.args({"0":"object", length:"number", forEach:"function"}, "string", "boolean").use(function(eles, c, multiple){
eles.forEach(function(ele){
self.addClass(ele, c, multiple)
})
})
.args("string", "string", "boolean").use(function(selector, c, multiple){
if(selector[0] == "$"){
self.elements(selector).forEach( function(ele){
self.addClass(ele, c, multiple)
})
}
else {
console.warn("selector must begin with '$'")
}
return self
})
.args({"0":"object", length:"number", forEach:"function"}, "string").use(function(eles, c){
eles.forEach(function(ele){
self.addClass(ele, c, false)
})
})
.args({scope:"object", className:"string"}, "string").use(function(ele, c){
self.addClass(ele, c, false)
return self
})
.args("string", "string").use(function(selector, c){
if(selector[0] == "$"){
self.elements(selector).forEach( function(ele){
self.addClass(ele, c, false)
})
}
else {
console.warn("selector must begin with '$'")
}
return self
})
.args("string", "boolean").use(function(c, multiple){
self.addClass(ele, c, multiple)
return self
})
.args("string").use(function(c){
self.addClass(ele, c, false)
return self
})
.args().use(function(){
console.warn("addClass function inputs improperly formatted")
return self
})
public_method.removeClass = overload()
.args({scope:"object", className:"string"}, "string", "boolean").use(function(ele, c, multiple){
if (ele.scope == self){
var globalMatch = (multiple)? "g" : ""
var matcher = new RegExp("(^"+c+"$|\\s"+c+"\\s|^"+c+"\\s|\\s"+c+"$)", globalMatch)
ele.className = ele.className
.replace(matcher, " ")
.replace(/(^\s+|\s+$)/g, "")
.replace(/\s+/g, " ")
}
else {
ele.scope.removeClass(ele, c, multiple)
}
return self
})
.args({scope:"object", className:"string"}, "string").use(function(ele, c){
self.removeClass(ele, c, false)
return self
})
.args({"0":"object", length:"number", forEach:"function"}, "string", "boolean").use(function(eles, c, multiple){
eles.forEach(function(ele){
self.removeClass(ele, c, multiple)
})
})
.args("string", "string", "boolean").use(function(selector, c, multiple){
if(selector[0] == "$"){
self.elements(selector).forEach( function(ele){
self.removeClass(ele, c, multiple)
})
}
else {
console.warn("selector must begin with '$'")
}
return self
})
.args({"0":"object", length:"number", forEach:"function"}, "string").use(function(eles, c){
eles.forEach(function(ele){
self.removeClass(ele, c, false)
})
})
.args("string", "string").use(function(selector, c){
if(selector[0] == "$"){
self.elements(selector).forEach( function(ele){
self.removeClass(ele, c, false)
})
}
else {
console.warn("selector must begin with '$'")
}
return self
})
.args("string", "boolean").use(function(c, multiple){
self.removeClass(ele, c, multiple)
return self
})
.args("string").use(function(c){
self.removeClass(ele, c, false)
return self
})
.args().use(function(){
console.warn("removeClass function inputs improperly formatted")
return self
})
public_method.attr = overload()
.args({scope:"object", getAttribute:"function", setAttribute: "function"}, "string").use(function(ele, attribute, value){
if (ele.scope == self){
if (typeof value == "undefined") {
return ele.getAttribute(attribute)
}
else {
ele.setAttribute(attribute, value)
return self
}
}
else {
if (typeof value == "undefined"){
return ele.scope.attr(ele, attribute)
}
else {
ele.scope.attr(ele, attribute, value)
return self
}
}
})
.args({"0":"object", length:"number", forEach:"function"}, "string").use(function(eles, attribute, value){
eles.forEach(function(ele){
self.attr(ele, attribute, value)
})
return self
})
.args("string", "string").use(function(v1, v2, v3){
if (v1[0] == "$"){ //v1 is selector
var selector = v1,
attribute = v2,
value = v3
if (typeof value == "undefined"){
return self.attr(self.element(selector), attribute)
}
else {
self.elements(selector).forEach( function(ele){
self.attr(ele, attribute, value)
})
return self
}
}
else{ // v1 is property name
var attribute = v1,
value = v2
return self.attr(ele, attribute, value)
}
})
.args("string").use(function(attribute, value){
return self.attr(ele, attribute, value)
})
.args().use(function(){
console.warn("attr function inputs improperly formatted")
return self
})
public_method.css = overload()
.args({scope: "object", style:"object"}, "string").use(function(ele, rule, value){
if (ele.scope == self){
if (typeof value != "undefined"){
var elemStyles = self.attr(ele, "style") || "",
ruleForm = rule + "[^;]*(;|$)"
replaceRule = new RegExp("((^(\\n|\\s)*|;)(\\s|\\n)*" + ruleForm + "|^" + ruleForm + ")", "gi"),
replaceWith = rule + ":" + value + ";"
newRules = elemStyles
.replace(replaceRule, ";" + replaceWith)
.replace(/^;/, "")
if (newRules == elemStyles){
self.attr(ele, "style", elemStyles + replaceWith)
}
else {
self.attr(ele, "style", newRules)
}
return self
}
else {
return getComputedStyle(ele).getPropertyValue(rule)
}
}
else {
if (value){
ele.scope.css(ele, rule, value)
return self
}
else {
return ele.scope.css(ele, rule)
}
}
})
.args({"0":"object", length:"number", forEach:"function"}, "string").use(function(eles, rule, value){
eles.forEach(function(ele){
self.css(ele, rule, value)
})
return self
})
.args("string", "string").use(function(v1, v2, v3){
if (v1[0] == "$"){
var selector = v1,
rule = v2,
value = v3
self.elements(selector).forEach(function(ele){
self.css(ele, rule, value)
})
return self
}
else {
var rule = v1,
value = v2
return self.css(ele, rule, value)
}
})
.args("string").use(function(rule){
return self.css(ele, rule)
})
.args().use(function(){
console.warn("css function inputs improperly formatted")
return self
})
public_method.data = overload()
.args({scope:"object", dataset:"object"}, "string").use(function(ele, attribute, value){
if (ele.scope == self){
if (typeof value !== "undefined"){
ele.dataset[attribute] = value
return self
}
else {
return ele.dataset[attribute]
}
}
else {
return ele.scope.data(ele, attribute)
}
})
.args("string", "string").use(function(v1, v2, v3){
if (v1[0] == "$"){ //v1 is selector
var selector = v1,
attribute = v2,
value = v3
if (typeof value == "undefined"){
return self.data(self.element(selector), attribute)
}
else {
self.elements(selector).forEach( function(ele){
self.data(ele, attribute, value)
})
return self
}
}
else{ // v1 is property name
var attribute = v1,
value = v2
return self.data(ele, attribute, value)
}
})
.args("string").use(function(attribute, value){
return self.data(ele, attribute, value)
})
.args().use(function(){
console.warn("data function inputs improperly formatted")
return self
})
public_method.html = overload()
.args({scope:"object", appendChild:"function"}, "string").use(function(ele, htmlString){
if (ele.scope == self){
self.children.forEach(function(subScope){
subScope.unlink()
})
ele.innerHTML = htmlString
ele.scope.include()
}
else {
ele.scope.html(ele, htmlString)
}
return self
})
.args("string", "string").use(function(selector, htmlString){
if (selector[0] == "$"){
self.html(self.element(selector), htmlString)
}
return self
})
.args({scope:"object", appendChild:"function"}).use(function(ele){
if (ele.scope == self) {
return ele.innerHTML
}
else {
return ele.scope.html(ele)
}
})
.args("string").use(function(v){
if (v[0] == "$"){
var selector = v
return self.html(self.element(selector))
}
else {
var htmlString = v
self.html(ele, htmlString)
return self
}
})
.args().use(function(v){
return self.html(self.element())
})
// functions for dom manip end
public_method.include = overload()
.args({scope:"object", appendChild:"function"}, "object").use(function(ele, subEle){
if (ele.scope == self && !subEle.scope){
recursiveDefineScope(subEle)
ele.appendChild(subEle)
}
else if (!subEle.scope){
ele.scope.include(ele, subEle)
}
else {
console.warn("The item you are trying to include into this scope is already part of another scope. Try to append that scope to the current scope instead")
}
return self
})
.args("string", "object").use(function(selector, subEle){
if(selector[0] == "$"){
self.include(self.element(selector), subEle)
}
else {
console.warn("selector must begin with '$'")
}
return self
})
.args("object").use(function(subEle){
self.include(ele, subEle)
return self
})
.args().use(function(){
self.children.forEach(function(subScope){
subScope.include()
})
self.elements().forEach(function(ele){
if (!ele.scope){
self.include(self.element(), ele)
}
})
return self
})
// functions for module manip begin
public_method.property = public_method.define = overload()
.args("string", {get: "function", static: "undefined", asVar: "undefined"}).use(function(prop, config){
config.scope = self
var deffs = {
enumerable: (typeof config.enumerable == "undefined")? true : config.enumerable,
configurable: true,
get: config.get
}
if (config.set && typeof config.set === "function") {
deffs.set = config.set
}
if (deffs.get.bind){
deffs.get = deffs.get.bind(config)
}
if (deffs.set && deffs.set.bind){
deffs.set = deffs.set.bind(config)
}
Object.defineProperty(self, prop, deffs)
return self
})
.args("string", {get: "undefined", set:"undefined", asVar: "undefined", static: "!undefined"}).use(function(prop, config){
config.scope = self
var deffs = {
enumerable: (typeof config.enumerable == "undefined")? true : config.enumerable,
configurable: true,
writable: false,
value: config.static
}
if (deffs.value.bind){
deffs.value = deffs.value.bind(config)
}
Object.defineProperty(self, prop, deffs)
return self
})
.args("string", {get: "undefined", set:"undefined", asVar: "!undefined", static: "undefined"}).use(function(prop, config){
var deffs = {
enumerable: (typeof config.enumerable == "undefined")? true : config.enumerable,
configurable: true,
writable: true,
value: config.asVar
}
Object.defineProperty(self, prop, deffs)
return self
})
.args().use(function(){
console.warn("property/define function inputs improperly formatted")
return self
})
public_method.element = function(selector){
if (selector){
if(selector[0] == "$"){
selector = selector.replace(/^\$\s*/, "")
}
return ele.querySelector(selector)
}
else {
return ele
}
}
public_method.elements = function(selector){
if (selector){
if(selector[0] == "$"){
selector = selector.replace(/^\$\s*/, "")
}
return Array.prototype.slice.call(ele.querySelectorAll(selector), 0)
}
else{
var arr = Array.prototype.filter.call(ele.querySelectorAll("*"), function(node){
return node.scope == self
})
arr.unshift(ele)
return arr
}
}
public_method.append = public_method.appendChild = overload()
// main method 1 append child scope
.args({scope:{append:"function"}, appendChild:"function"}, {children:"object", root:"object", element:"function", unlink:"function"}).use(function(ele, subScope){
if (ele.scope == self){
subScope.unlink()
Object.setPrototypeOf(Object.getPrototypeOf(subScope), self)
ele.appendChild(subScope.element())
}
else {
ele.scope.append(ele, subScope)
}
return self
})
// bootstrap off main method 1
.args("string", {children:"object", root:"object", element:"function", unlink:"function"}).use(function(selector, subScope){
if(selector[0] == "$"){
self.append(self.element(selector), subScope)
}
else {
console.warn("selector must begin with '$'")
}
return self
})
// main method 2: alias for include
.args({scope:{append:"function"}, appendChild:"function"}, "object").use(function(ele, addedEle){
if (ele.scope == self){
self.include(ele, addedEle)
}
else {
ele.scope.include(ele, addedEle)
}
return self
})
// main bootstrap off main metho 2
.args("string", "object").use(function(selector, addedEle){
if(selector[0] == "$"){
self.append(self.element(selector), addedEle)
}
else {
console.warn("selector must begin with '$'")
}
return self
})
// bootstrap off main method 2
.args({scope:{append:"function"}, appendChild:"function"}, "string").use(function(ele, htmlString){
converter.innerHTML = htmlString
Array.prototype.slice.call(converter.children, 0).forEach(function(addedEle){
self.append(ele, addedEle)
})
return self
})
// bootstrap off main method 2
.args("string", "string").use(function(selector, htmlString){
if(selector[0] == "$"){
var ele = self.element(selector)
converter.innerHTML = htmlString
Array.prototype.slice.call(converter.children, 0).forEach(function(addedEle){
self.append(ele, addedEle)
})
}
else {
console.warn("selector must begin with '$'")
}
return self
})
// bootstrp off of main method 1
.args({children:"object", root:"object", element:"function", unlink:"function"}).use(function(subScope){
self.append(ele, subScope)
return self
})
// bootstraps off main method 2
.args("object").use(function(addedEle){
if (ele.scope == self){
self.append(ele, addedEle)
}
return self
})
// bootstrap off main method 2
.args("string").use(function(htmlString){
converter.innerHTML = htmlString
Array.prototype.slice.call(converter.children, 0).forEach.call(converter.children, function(addedEle){
self.append(ele, addedEle)
})
return self
})
.args().use(function(){
console.warn("append/appendChild function inputs improperly formatted")
return self
})
public_method.unlink = function(){
if (ele.parentNode) {
Object.setPrototypeOf(Object.getPrototypeOf(self), Object.prototype)
ele.parentNode.removeChild(ele)
}
return self
}
public_method.render = function(){
self.unlink()
document.body.appendChild(ele)
return self
}
return self
}
// --------------------------------------------------------
// Stateless object exposed to the main execution scope for managing and playing with the templates
// --------------------------------------------------------
context.stateless = {}
var statelessOpps = {},
statelessPlugins = {}
Object.setPrototypeOf(context.stateless, statelessPlugins)
Object.setPrototypeOf(statelessPlugins, statelessOpps)
// private values to be manipulated internally
var length = 0,
migrateId = function(ele){
if (ele.id){
var className = ele.className
ele.className = ele.id
if (className){
ele.className += " " + className
}
ele.removeAttribute("id")
}
},
pushEle = function(ele){
var index = length
var id = ele.id || index
migrateId(ele)
length ++
Object.defineProperty(context.stateless, id, {
enumerable: false,
configurable: false,
writable: false,
value: ele
})
if (!context.stateless[index]){
Object.defineProperty(context.stateless, index, {
enumerable: false,
configurable: false,
writable: false,
value: ele
})
}
return id
}
// public unchangeable variable
Object.defineProperty(statelessOpps, "length", {
enumerable: false,
configurable: false,
get: function(){
return length
}
})
Object.defineProperty(statelessOpps, "consume", {
enumerable: false,
configurable: false,
writable: false,
value: function(ele){ // public static function
if (ele instanceof HTMLElement){
ele.parentElement && ele.parentElement.removeChild(ele)
pushEle(ele)
}
else if (typeof ele === "string"){
converter.innerHTML = ele
stateless.consume(converter.children)
}
else if (ele.length && ele[0] ){ //
for (var i = 0; i < ele.length; i++){
stateless.consume(ele[i])
}
}
else {
throw new Error("Invalid inputs")
}
return context.stateless
}
})
Object.defineProperty(statelessOpps, "register", {
enumerable: false,
configurable: false,
writable: false,
value: statelessOpps.consume
})
Object.defineProperty(statelessOpps, "view", {
enumerable: false,
configurable: false,
writable: false,
value: function(ele){
if (ele instanceof HTMLElement){
ele.parentElement && ele.parentElement.removeChild(ele)
migrateId(ele)
return Scope(ele)
}
else if (typeof ele === "string"){
converter.innerHTML = ele
if (converter.children.length === 1){
return stateless.view(converter.children[0])
}
}
else {
throw new Error("Invalid inputs")
}
}
})
Object.defineProperty(statelessOpps, "build", {
enumerable: false,
configurable: false,
writable: false,
value: statelessOpps.view
})
Object.defineProperty(statelessOpps, "instantiate", {
enumerable: false,
configurable: false,
writable: false,
value: function(identifyer){ // public static function
if (stateless[identifyer]) {
var instance = Scope(stateless[identifyer].cloneNode(true))
return instance
}
else {
throw new Error( identifyer + " cannot be found in the template library")
}
}
})
Object.defineProperty(statelessOpps, "each", {
enumerable: false,
configurable: false,
writable: false,
value: function(callback){
for (var i = 0; i < length; i++){
callback(context.stateless[i], i)
}
return context.stateless
}
})
var subscription = {},
globalWatchers = []
Object.defineProperty(statelessOpps, "watch", {
enumerable: false,
configurable: false,
writable: false,
value: overload()
.args("string", "function").use(function(nameSpace, callback){ // public static function
subscription[nameSpace] = subscription[nameSpace] || []
subscription[nameSpace].push(callback)
return function(){
subscription[nameSpace].forEach(function(watcher, index){
if (watcher == callback){
subscription[nameSpace].splice(index, 1)
}
})
}
})
.args("function").use(function(callback){
globalWatchers.push(callback)
return function(){
globalWatchers.forEach(function(watcher, index){
if (watcher == callback){
globalWatchers.splice(index, 1)
}
})
}
})
.args().use(function(){
console.warn("watcher registration error")
})
})
Object.defineProperty(statelessOpps, "emit", {
enumerable: false,
configurable: false,
writable: false,
value: function(nameSpace, data){ // public static function
data = data || {}
subscription[nameSpace] && subscription[nameSpace].forEach(function(callback){
callback(data)
})
globalWatchers.forEach(function(watcher){
watcher(nameSpace, data)
})
return context.stateless
}
})
Object.defineProperty(statelessOpps, "plugin", {
enumerable: false,
configurable: false,
writable: false,
value: overload() // public static function
.args("string", "!undefined").use(function(name, val){ // set a plugin function
if (statelessPlugins.hasOwnProperty(name)){
return console.warn("Plugin already defined")
}
Object.defineProperty(statelessPlugins, name, {
enumerable: true,
configurable: true,
writable: true,
value: val
})
return context.stateless
})
.args("string", "undefined").use(function(name){ // get a plugin function
if (statelessPlugins.hasOwnProperty(name)){
return statelessPlugins[name]
}
return context.stateless
})
.args().use(function(){
console.warn("plugin error")
return context.stateless
})
})
})(
this,
// modified method-overload v0.1.1
(function(){var b=function(a,c){var d=!0;for(var e in c){"string"==typeof c[e]&&"!"===c[e][0]?typeof a[e]===c[e].substring(1)&&(d=!1):"object"==typeof a[e]&&"object"==typeof c[e]?d=b(a[e],c[e])&&d:typeof a[e]!==c[e]&&(d=!1)}return d};return function(){var a=this,c=arguments;1===arguments.length&&(c=arguments[0]);var d=[],e=function(){};e.use=e.args=function(){return e};var f=function(){for(var a in d){var c=d[a];if(b(arguments,c.m))return c.e.apply(this,arguments)}},g=function(){var g=arguments;return{use:function(h){return 0==g.length&&delete f.args,d.push({m:g,e:h}),c.length&&b(c,g)?(h.apply(a,c),e):f}}};return f.args=g,f}})(),
// anonamyous recursive functions
function(fn){
var bound = function(){
var inputs = Array.prototype.concat.call([bound], Array.prototype.splice.call(arguments, 0))
return fn.apply(null, inputs)
}
return bound
}
)