// ### A tiny javascript utility belt
//
// Mutil is a micro-framework, a collection of helper functions that you often
// need. Full-blown frameworks like jQuery can be overkill for minor scripting
// tasks. Mutil is light-weight but still provides some useful functions for
// functional programming and dealing with DOM events across browsers.
//
// Mutil does not do Ajax, advanced templating, advanced selectors or
// animation. If you need any of those, you're better off going with
// [jQuery](http://jquery.com) or some other full-blown framework.
//
// **Note**: Mutil does not implement all the advanced javascript functions
// that are found in modern browsers, but not in IE. Although it mimicks some
// of these, some are intentionally left out to stay lean.
//
// Find the source code and tests [at Github](http://github.com/avdgaag/mutil)
// and the documentation at [the mutil homepage](http://avdgaag.github.com/mutil).
//
// **Author**: [Arjan van der Gaag](http://arjanvandergaag.nl)  
// **Date**: 2011-07-06  
// **License**: MIT License
//
(function(){var a=Array.prototype.slice,b={forEach:Array.prototype.forEach,reduce:Array.prototype.reduce,map:Array.prototype.map,filter:Array.prototype.filter};window.Mutil={VERSION:"0.1.1",nativize:function(){var a=this,b=function(b,c){a.forEach(c,function(c){b.prototype[c]||(b.prototype[c]=function(){args=a.toArray(arguments),args.unshift(this);return a[c].apply(a,args)})})};b(Array,["forEach","reduce","map","filter","pluck","invoke","include"]),b(String,["trim","format"]),b(Object,["extend","tap","forEach"]),b(Function,["bind"]);return this},$:function(a){if(this.isFunction(a))this.addLoadEvent(a);else{args=this.toArray(arguments);return this.query.apply(this,args)}},query:function(a,b){b=b||document;if(this.isArray(b))return this.reduce(b,[],this.bind(function(b,c){return b.concat(this.query(a,c))},this));if(a.match(/,/))return this.reduce(a.split(/\s*,\s*/),[],function(a,b){return a.concat(this.query(b))},this);if(a.match(/\s+/))return this.reduce(a.split(/\s+/),document,this.bind(function(a,b){return a=this.query(b,a)},this));if(a.match(/\./)){var c=a.split("."),d=c[0]||"*",e=c.slice(1);return this.filter(this.query(d,b),this.bind(function(a){return this.reduce(e,!0,function(b,c){return b&&a.className.indexOf(c)>=0})},this))}return(matches=a.match(/#([a-zA-Z\-_0-9]+)/))?this.tap([],function(a){(_el=b.getElementById(matches[1]))&&a.push(_el)}):this.toArray(b.getElementsByTagName(a))},addClass:function(a){if(!this.isElement(a))throw new TypeError;var b=this.toArray(arguments).slice(1),c=a.className.split(/\s+/);a.className=c.concat(b.filter(function(a){return!c.include(a)})).join(" ")},removeClass:function(a){if(!this.isElement(a))throw new TypeError;var b=a.className;this.toArray(arguments).slice(1).forEach(function(a){b=b.replace(new RegExp("\\b"+a+"\\b","g"),"")}),a.className=this.trim(b.replace(/\s+/g," "))},addLoadEvent:function(a){var b=window.onload;this.isFunction(b)?window.onload=function(){b&&b(),a()}:window.onload=a},addEvent:function(a,b,c){a.attachEvent?(a["e"+b+c]=c,a[b+c]=function(){a["e"+b+c](window.event)},a.attachEvent("on"+b,a[b+c])):a.addEventListener(b,c,!1)},removeEvent:function(a,b,c){a.detachEvent?(a.detachEvent("on"+b,a[b+c]),a[b+c]=null):a.removeEventListener(b,c,!1)},forEach:function(a,c,d){if(a!=null)if(b.forEach&&a.forEach===b.forEach)a.forEach(c,d);else if(a.length===0||a.length&&a.length.toExponential&&a.length.toFixed)for(var e=0,f=a.length;e<f;e++)c.call(d,a[e],e,a);else{if(typeof a!="object")throw new TypeError("Not iterable: "+typeof a);for(key in a)a.hasOwnProperty(key)&&c.call(d,key,a[key])}},include:function(a,b){return this.filter(a,function(a){return a===b}).length>0},filter:function(a,c,d){return b.filter&&a.filter===b.filter?a.filter(c,d):this.reduce(a,[],function(a,b){c.call(d,b)&&a.push(b);return a})},pluck:function(a,b){return this.map(a,function(a){return a[b]})},invoke:function(a,b){var c=this.toArray(arguments).slice(2);return this.map(a,function(a){return a[b].apply(a,c)})},map:function(a,c,d){return b.map&&a.map==b.map?a.map(c,d):this.reduce(a,[],function(a,b){a.push(c.call(d,b))})},reduce:function(a,c,d,e){if(b.reduce&&a.reduce===b.reduce){e&&(d=this.bind(d,e));return a.reduce(d,c)}this.forEach(a,function(a){return c=d.call(e,c,a)});return c},trim:function(a){return a.replace(/^\s*|\s*$/g,"")},format:function(a,b){this.forEach(b,function(b,c){a=a.replace(new RegExp("{"+b+"}","g"),c)});return a},tap:function(a,b){b(a);return a},extend:function(a){var b=this.toArray(arguments,1),c=this;this.forEach(b,function(b){c.forEach(b,function(b,c){a[b]=c})})},bind:function(a,b){var c=this,d=this.toArray(arguments).slice(2);return function(){return a.apply(b,d.concat(c.toArray(arguments)))}},isArray:function(a){return Object.prototype.toString.call(a)==="[object Array]"},isFunction:function(a){return!!(a&&a.constructor&&a.call&&a.apply)},isString:function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)},isElement:function(a){return!!a&&a.nodeType===1},isNumber:function(a){return a===0||a&&a.toExponential&&a.toFixed},isUndefined:function(a){return a===void 0},toArray:function(b){if(this.isArray(b))return b;if(b.toArray)return b.toArray();if(b&&Object.prototype.hasOwnProperty.call(b,"callee"))return a.call(b);var c=[];for(var d=b.length;d--;c.unshift(b[d]));return c},Observable:{observe:function(a,b){var c=this._observers||(this._observers={}),d=c[a]||(c[a]=[]);d.push(b);return this},unobserve:function(a,b){var c;if(!a)this._observers={};else if(c=this._observers)if(!b)c[a]=[];else{var d=c[a];if(!d)return this;for(var e=0,f=d.length;e<f;e++)if(b===d[e]){d[e]=null;break}}return this},trigger:function(b){if(!(o=this._observers))return this;if(l=o[b])for(var c=0,d=l.length;c<d;c++)l[c].apply(this,a.call(arguments,1));return this}}},Mutil.$=Mutil.bind(Mutil.$,Mutil)})()
