// underscore_plus.js // (c) 2013 Gary McGhee, Buzzware Solutions // https://github.com/buzzware/underscore_plus // Underscore may be freely distributed under the MIT license. (function() { //BEGIN copied from underscore var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; // Create quick reference variables for speed access to core prototypes. var slice = ArrayProto.slice; //END copied from underscore _.stringify = function(aObject) { if (_.isString(aObject)) return aObject; if (aObject===null || aObject===undefined) return ''; if (aObject.toString) return aObject.toString(); return ''; }; //var MAX_DUMP_DEPTH = 10; // // function dumpObj(obj, name, indent, depth) { // if (depth > MAX_DUMP_DEPTH) { // return indent + name + ": \n"; // } // if (typeof obj == "object") { // var child = null; // var output = indent + name + "\n"; // indent += "\t"; // for (var item in obj) // { // try { // child = obj[item]; // } catch (e) { // child = ""; // } // if (typeof child == "object") { // output += dumpObj(child, item, indent, depth + 1); // } else { // output += indent + item + ": " + child + "\n"; // } // } // return output; // } else { // return obj; // } // } _.concat = function(aArray,aAnotherArray) { var result = []; result.push.apply(result, aArray); result.push.apply(result, aAnotherArray); return result; }; _.nameValueString = function(aObject) { return _.map(_.keys(aObject),function(k) { return k+'="'+_.stringify(aObject[k])+'"'}).join(' '); }; _.classEnsure = function(aOrig,aNew) { if (!aOrig) return aNew; if (!aNew) return aOrig; return _.union(aOrig.split(' '),aNew.split(' ')); }; _.getPath = function(aObject,aPath,aDefault) { if ((typeof aObject)=='string') { // allow aObject to be left out and assume this if (arguments.length==1) { aPath = aObject; aObject = window; } else if (arguments.length==2) { aDefault = aPath; aPath = aObject; aObject = window; } } var nodes = aPath.split('.'); var curr = aObject; for (var i=0;i=0 && i===aString.length-aSuffix.length); } _.beginsWith = function(aString, aPrefix) { var i = aString.indexOf(aPrefix); return (i==0); } _.chop = function(aString, aSuffix) { var i = aString.lastIndexOf(aSuffix); return (i===aString.length-aSuffix.length) ? aString.substring(0,i) : aString; } _.bite = function(aString, aPrefix) { var i = aString.indexOf(aPrefix); return (i===0) ? aString.substring(aPrefix.length) : aString; } // undefined null function arguments string number date regexp object _.typeOf = function(aSomething) { if (aSomething===undefined) return 'undefined'; if (aSomething===null) return 'null'; var result = Object.prototype.toString.call(aSomething); result = _.bite(result,'[object '); result = _.chop(result,']'); return result.toLowerCase(); } /** * Clone properties that are objects or arrays, otherwise if aSource and aDestination are different, properties will be copied * @param aDestination * @param aSource (optional, defaults to aSource) * @return aDestination */ _.cloneComplexValues = function (aDestination, aSource) { if (!aSource) aSource = aDestination; for (var p in aSource) { var t = _.typeOf(aSource[p]); if (t==='array' || t==='object') aDestination[p] = _.clone(aSource[p]); else if (aDestination!==aSource) aDestination[p] = aSource[p]; } return aDestination; } // http://justtalkaboutweb.com/2008/01/06/javascript-object-extension/ _.originalClone = _.originalClone || _.clone; // Create a copy (shallow or deep) of an object from https://github.com/cederberg/underscore/commits/feature-clone _.clone = function(obj, deep, ignoreFns) { if (!deep && !ignoreFns) return _.originalClone(obj); if (!_.isObject(obj) || _.isFunction(obj)) return obj; if (_.isDate(obj)) return new Date(obj.getTime()); if (_.isRegExp(obj)) return new RegExp(obj.source, obj.toString().replace(/.*\//, "")); var isArr = (_.isArray(obj) || _.isArguments(obj)); if (deep) { var func = function(memo, value, key) { if (!ignoreFns || !_.isFunction(value)) { if (isArr) memo.push(_.clone(value, true)); else memo[key] = _.clone(value, true); } return memo; }; return _.reduce(obj, func, isArr ? [] : {}); } else { var result; if (isArr) result = slice.call(obj); else { result = {}; var v; for (var p in obj) { v = obj[p]; if (ignoreFns && _.isFunction(v)) continue; result[p] = v; } } return result; } }; _.randomString = function (aLength, aCharSet) { var result = []; aLength = aLength || 5; aCharSet = aCharSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; aCharSet = aCharSet.split(''); while (--aLength) { result.push(aCharSet[Math.floor(Math.random() * aCharSet.length)]); } return result.join(''); }; _.formatNumber = function(aValue,aDecimals) { if (aValue===null) return ''; if (!aDecimals && aDecimals!==0) aDecimals = 2; return aValue.toFixed(aDecimals); }; _.groupDigits = function(x) { var parts = x.toString().split("."); parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); return parts.join("."); }; _.sum = function() { var result = NaN; for (var i=0;i [{id: "cash", name:"Cash"}, {id: "consumer_mortgage",name: "Consumer Mortgage"}] // _.expand_options(["cash","consumer_mortgage"]) // => [{id: "cash", name:"cash"}, {id: "consumer_mortgage",name: "consumer_mortgage"}] _.expand_options = function(aObject,aIdField,aNameField) { if (!aIdField) aIdField = 'id'; if (!aNameField) aNameField = 'name'; if (_.isArray(aObject)) { return _.map(aObject,function(v){ var result = {}; result[aIdField] = v; result[aNameField] = String(v); return result; }); } else { return _.map(aObject,function(v,k){ var result = {}; result[aIdField] = k; result[aNameField] = v; return result; }); } }; // returns array of keys on object beginning with aPrefix _.keysWithPrefix = function(aObject,aPrefix) { var results = []; var keys = _.keys(aObject); for (var i=0;i=0) continue; if (p in aSource) aDest[p] = v; } } else { for (p in aSource) { v = aSource[p]; if (_.isFunction(v)) continue; if (aExclude && aExclude.indexOf(p)>=0) continue; if (p in aSource) aDest[p] = v; } } return aDest; }; var formatRegexes = {}; // format a string // Usage: _.format("{0} i{2}a night{1}", "This", "mare", "s "); // Could support _.format("{number} {street}, {suburb}", {number: 27, street: "Constant St", suburb: "Highgate"}); - might already // see http://stackoverflow.com/questions/2534803/string-format-in-javascript/2534870#2534870 _.format = function(aFormat, aValues) { var src,v; if (_.isObject(aValues)) { for (p in aValues) aFormat = aFormat.replace(formatRegexes[p] || (formatRegexes[p] = RegExp("\\{" + p + "\\}", "gm")), aValues[p]); } else { for (var args = arguments, i = args.length; --i;) aFormat = aFormat.replace(formatRegexes[i - 1] || (formatRegexes[i - 1] = RegExp("\\{" + (i - 1) + "\\}", "gm")), args[i]); } return aFormat; }; _.randomInt = function(aValues) { return Math.floor(Math.random()*aValues); }; _.randomIntRange = function(aMin,aMax) { return aMin + Math.floor(Math.random()*(aMax-aMin+1)); }; }).call(this);