/** * Utopia: A JavaScript util library that assumes modern standards support and doesn't fix any browser bugs * @author Lea Verou (http://lea.verou.me) * MIT license (http://www.opensource.org/licenses/mit-license.php) * Last update: 2012-4-29 */ function $(expr, con) { return typeof expr === 'string'? (con || document).querySelector(expr) : expr; } function $$(expr, con) { var elements = (con || document).querySelectorAll(expr); try { return Array.prototype.slice.call(elements); } catch(e) { var arr = Array(elements.length); for (var i = elements.length; i-- > 0;) { arr[i] = elements[i]; } return arr; } } if (!Array.prototype.forEach) { Array.prototype.forEach = function(fn, scope) { for (var i = 0, len = this.length; i < len; ++i) { fn.call(scope || this, this[i], i, this); } } } // Make each ID a global variable // Many browsers do this anyway (it’s in the HTML5 spec), so it ensures consistency $$('[id]').forEach(function(element) { window[element.id] = element; }); // Array#splice but for strings String.prototype.splice = function(i, remove, add) { remove = +remove || 0; add = add || ''; return this.slice(0,i) + add + this.slice(i + remove); }; (function(){ var _ = window.Utopia = { /** * Returns the [[Class]] of an object in lowercase (eg. array, date, regexp, string etc) * Caution: Results for DOM elements and collections aren't reliable. * @param {Object} obj * * @return {String} */ type: function(obj) { if(obj === null) { return 'null'; } if(obj === undefined) { return 'undefined'; } var ret = Object.prototype.toString.call(obj).match(/^\[object\s+(.*?)\]$/)[1]; ret = ret? ret.toLowerCase() : ''; if(ret == 'number' && isNaN(obj)) { return 'NaN'; } return ret; }, /** * Iterate over the properties of an object. Checks whether the properties actually belong to it. * Can be stopped if the function explicitly returns a value that isn't null, undefined or NaN. * * @param obj {Object} The object to iterate over * @param func {Function} The function used in the iteration. Can accept 2 parameters: one of the * value of the object and one for its name. * @param context {Object} Context for the above function. Default is the object being iterated. * * @return {Object} Null or the return value of func, if it broke the loop at some point. */ each: function(obj, func, context) { if(!_.type(func) == 'function') { throw Error('The second argument in Utopia.each() must be a function'); }; context = context || obj; for (var i in obj) { if(obj.hasOwnProperty && obj.hasOwnProperty(i)) { var ret = func.call(context, obj[i], i); if(!!ret || ret === 0 || ret === '') { return ret; } } } return null; }, /** * Copies the properties of one object onto another. * When there is a collision, the later one wins * * @return {Object} destination object */ merge: function(objects) { var ret = {}; for(var i=0; i