UNPKG

ares-ide

Version:

A browser-based code editor and UI designer for Enyo 2 projects

982 lines (905 loc) 30.4 kB
(function(){ //* @protected enyo.global = this; //*@protected /** Used internally by the _enyo.uid()_ method to produce a runtime unique identifier. */ var uidCounter = 0; //*@public /** Returns a boolean value indicating whether a target is undefined. */ enyo.exists = function (target) { return (undefined !== target); }; var exists = enyo.exists; //*@public /** Looks for last occurrence of a string _(needle)_ inside an array or string _(haystack)_. An IE8-safe fallback for the default _lastIndexOf()_ method. */ enyo.lastIndexOf = function (needle, haystack, index) { if (haystack.lastIndexOf) { return haystack.lastIndexOf(needle, index || haystack.length); } // in IE8 there is no lastIndexOf for arrays or strings but we // treat them slightly differently, this is written for minimal- // code as a slight tradeoff in performance but should rarely be // hit as it is var string = ("string" === typeof haystack); var rev = (string? haystack.split(""): haystack).reverse(); var cap = rev.length-1; var len = haystack.length; var idx; // if it is a string we need to make it a string again for // the indexOf method if (string) { rev = rev.join(""); } idx = enyo.indexOf(needle, rev, len - (index || len)); // put the array back the way it was if (!string) { rev.reverse(); } return -1 === idx? idx: (cap - idx); }; var lastIndexOf = enyo.lastIndexOf; //*@protected /** Internally-used method to detect deferred kind constructors. */ var isDeferredConstructor = function(target) { return target && ("function" === typeof target) && (target._FinalCtor || target._finishKindCreation); }; //*@public /** A fast-path enabled global getter that takes a string path, which may be a full path (from context window/Enyo) or a relative path (to the execution context of the method). It knows how to check for and call the backwards-compatible generated getters, as well as how to handle computed properties. Returns _undefined_ if the object at the given path cannot be found. May safely be called on non-existent paths. */ enyo.getPath = function (path) { // in case nothing is passed or null, we return it to keep it from // failing the other cases if (path === undefined || null === path) { return path; } // in almost all cases when calling and enyo is the context global is // the intended scope var b = (this === enyo? enyo.global: this), // strip leading `.` without adding to the stack when possible p = (path[0] == "."? path.replace(/^\.+/, ""): path); // break setting variables and doing work because if stripping all "." // left us with nothing in the string then we just return the discovered scope object if (!p) { return b; } // simply split it on "." and try and run down the path without recursively // executing the getter var ps = p.split("."), // the final property pr = ps.pop(), // ultimately the value we intend to return v, fn; for (var i=0, r$; (r$=ps[i]); ++i) { // this will retrieve the requested element if it has a getter we call this // to account for computed properties, default getters are used when present b = ( // these are carefully ordered in terms of likeliness to encounter thus // reducing the number of checks that need to be executed (b && b._isObject && ( (b._getters && (fn = b._getters[r$]) && b[fn]()) || (b.get && b.computed && b.computed[r$] && b[r$]()) || b[r$] )) || (("function" == typeof b && (b = enyo.checkConstructor(b)) && b[r$]) || b[r$]) ); if (!b) { break; } } // if the index isn't the same as the length of parts (including the 0 case) // then there was an error in the path and it couldn't be determined // so we return undefined if (i != ps.length) { return; } // otherwise we grab the final property from the base we now have, check if its a // deferred constructor, and return it v = b[pr]; return (("function" == typeof v && enyo.checkConstructor(v)) || v); }; //*@protected //* Simplified version of enyo.getPath used internally for get<Name> calls enyo.getPath.fast = function (path) { // the current context var b = this, // the final value to return fn, v; v = ((b._getters && (fn=b._getters[path]) && b[fn]()) || b[path]); return (("function" == typeof v && enyo.checkConstructor(v)) || v); }; //*@public /** A global setter that takes a string path (relative to the method's execution context) or a full path (relative to window). Attempts to automatically retrieve any previously existing value to supply to any observers. If the context is an _enyo.Object_ or subkind, the _notifyObservers()_ method is used to notify listeners for the path's being set. If the previous value is equivalent to the newly set value, observers will not be triggered by default. If the third parameter is present and is an explicit boolean true, the observers will be triggered regardless. Returns the context from which the method was executed. */ enyo.setPath = function (path, value, force) { // in almost all cases when calling and enyo is the context global is // the intended scope var b = (this === enyo? enyo.global: this), c = b; // if the path is nothing, undefined or null, or an empty string even // we can't do anything so we return this if (!path) { return b; } // strip leading `.` without adding to the stack when possible var p = (path[0] == "."? path.replace(/^\.+/, ""): path); // if the string is empty then we won't process anything else either if (!p) { return b; } // simply split it on "." and try and run down the path without recursively // executing the getter var ps = p.split("."), // the final property pr = ps.pop(), // placeholder during iterations over the path, // the previous value and a helper variable in case we find a computed property tp, rv, fn; for (var i=0, r$; (r$=ps[i]); ++i) { // unfortunately it is possible to request the actual "enyo" object in // a path so we have to test for this case or bad things happen if (r$ == "enyo" && enyo === b) { continue; } // its actually pretty simple, check to see if the next requested context exists and is an object // or a function, if so, we use that and continue, otherwise we have to create it b = ( ((tp=b[r$]) && ( // if its just an object, use it straight up (typeof tp == "object" && tp) || (typeof tp == "function" && ( // in the rare case that our path includes a computed property (as part of // chain -- this really is rare but not impossible) we use the getter to retrieve // it correctly (b._isObject && b.computed && b.computed[r$] && b.get(r$)) || // ensure this isn't a constructor that needs to be undeferred (isDeferredConstructor(tp) && enyo.checkConstructor(tp)) || tp )) // if it wasn't present we instantiate the path and use that object )) || (b[r$]={}) ); } // now we can attempt to retrieve a previous value if it can be done in as // efficient a manner as possible -- we will call an overloaded getter if necessary rv = ((b && b._isObject && b._getters && (fn=b._getters[pr]) && b[fn]()) || b[pr]); // now we set the new value, much simpler b[pr] = value; // only notify if the value has changed or if the update should be forced if (b.notifyObservers && rv !== value || force) { b.notifyObservers(pr, rv, value); } // return the original base reference we made in the first line return c; }; //*@protected //* Simplified version of enyo.setPath used on set<Name> calls enyo.setPath.fast = function (path, value) { // the current context var b = this, // the previous value and helper variable rv, fn; // we have to check and ensure that we're not setting a computed property // and if we are, do nothing if (b.computed && b.computed[path]) { return b; } rv = ((b._getters && (fn=b._getters[path]) && b[fn]()) || b[path]); // set the new value now that we can b[path] = value; // this method is only ever called from the context of enyo objects // as a protected method if (rv !== value) { b.notifyObservers(path, rv, value); } // return the context return b; }; //*@public /** Creates a unique identifier (with an optional prefix) and returns the identifier as a string. */ enyo.uid = function (prefix) { return String((prefix? prefix: "") + uidCounter++); }; //* @public //* Returns a random integer between 0 and a specified upper boundary; //* i.e., 0 <= return value < _inBound_. // // var randomLetter = String.fromCharCode(enyo.irand(26) + 97); // enyo.irand = function(inBound) { return Math.floor(Math.random() * inBound); }; //* Returns _inString_ with the first letter capitalized. enyo.cap = function(inString) { return inString.slice(0, 1).toUpperCase() + inString.slice(1); }; //* Returns _inString_ with the first letter lower-cased. enyo.uncap = function(inString) { return inString.slice(0, 1).toLowerCase() + inString.slice(1); }; enyo.format = function(inVarArgs) { var pattern = /\%./g; var arg = 0, template = inVarArgs, args = arguments; var replacer = function(inCode) { return args[++arg]; }; return template.replace(pattern, replacer); }; var toString = Object.prototype.toString; //* Returns true if the argument is a string. enyo.isString = function(it) { return toString.call(it) === "[object String]"; }; //* Returns true if the argument is a function. enyo.isFunction = function(it) { return toString.call(it) === "[object Function]"; }; //* Returns true if the argument is an array. enyo.isArray = Array.isArray || function(it) { return toString.call(it) === "[object Array]"; }; //* Returns true if the argument is an object. enyo.isObject = Object.isObject || function (it) { // explicit null/undefined check for IE8 compatibility return (it != null) && (toString.call(it) === "[object Object]"); }; //* Returns true if the argument is true. enyo.isTrue = function(it) { return !(it === "false" || it === false || it === 0 || it === null || it === undefined); }; //*@public /** Returns the index of any entry in _array_ whose _callback_ returns a truthy value. Accepts an optional _context_ for the _callback_. Each _callback_ will receive three parameters, the _value_ at _index_, and an immutable copy of the original array. If no callback returns true, or _array_ is not an Array, this method returns false. */ enyo.find = function (array, callback, context) { var $source = enyo.isArray(array) && array; var $ctx = context || enyo.global; var $fn = callback; var idx = 0, len, $copy, ret; if ($source && $fn && enyo.isFunction($fn)) { $copy = enyo.clone($source); len = $source.length; for (; idx < len; ++idx) { ret = $fn.call($ctx, $source[idx], idx, $copy); if (!! ret) { return idx; } } } return false; }; //* Returns the index of the element in _inArray_ that is equivalent //* (==) to _inElement_, or -1 if no such element is found. enyo.indexOf = function(inElement, inArray, fromIndex) { if (inArray.indexOf) { return inArray.indexOf(inElement, fromIndex); } if (fromIndex) { if (fromIndex < 0) { fromIndex = 0; } if (fromIndex > inArray.length) { return -1; } } for (var i=fromIndex || 0, l=inArray.length, e; (e=inArray[i]) || (i<l); i++) { if (e == inElement) { return i; } } return -1; }; //* Removes the first element in the passed-in array that is equivalent //* (==) to _inElement_. enyo.remove = function(inElement, inArray) { var i = enyo.indexOf(inElement, inArray); if (i >= 0) { inArray.splice(i, 1); } }; /** Invokes _inFunc_ on each element of _inArray_. If _inContext_ is specified, _inFunc_ is called with _inContext_ as _this_. */ enyo.forEach = function(inArray, inFunc, inContext) { if (inArray) { var c = inContext || this; if (enyo.isArray(inArray) && inArray.forEach) { inArray.forEach(inFunc, c); } else { var a = Object(inArray); var al = a.length >>> 0; for (var i = 0; i < al; i++) { if (i in a) { inFunc.call(c, a[i], i, a); } } } } }; /** Invokes _inFunc_ on each element of _inArray_, and returns the results as an Array. If _inContext_ is specified, _inFunc_ is called with _inContext_ as _this_. */ enyo.map = function(inArray, inFunc, inContext) { var c = inContext || this; if (enyo.isArray(inArray) && inArray.map) { return inArray.map(inFunc, c); } else { var results = []; var add = function(e, i, a) { results.push(inFunc.call(c, e, i, a)); }; enyo.forEach(inArray, add, c); return results; } }; //*@public /** Concatenates a variable number of arrays, removing any duplicate entries. */ enyo.merge = function (/* _arrays_ */) { var $m = Array.prototype.concat.apply([], arguments); var $s = []; for (var $i=0, v$; (v$=$m[$i]); ++$i) { if (!~enyo.indexOf(v$, $s)) { $s.push(v$); } } return $s; }; var merge = enyo.merge; //*@public /** Returns an array of the values of all properties in an object. */ enyo.values = function (o) { if (o) { var $r = []; for (var $k in o) { if (o.hasOwnProperty($k)) { $r.push(o[$k]); } } return $r; } }; //*@public /** Takes a variable number of arrays and returns an array of values that are unique across all of the arrays. Note that this is not a particularly cheap method and should never be called recursively. TODO: test in IE8 TODO: figure out why the one-hit reversal wasn't working */ enyo.union = function (/* _arrays_ */) { // create one large array of all of the arrays passed to // the method for comparison var values = Array.prototype.concat.apply([], arguments); // the array of seen values var seen = []; // the array of values actually to be returned var ret = []; var idx = 0; var len = values.length; var value; for (; idx < len; ++idx) { value = values[idx]; // if we haven't seen this value before go ahead and // push it to the seen array if (!~enyo.indexOf(value, seen)) { seen.push(value); // here we check against the entirety of any other values // in the values array starting from the end if (idx === lastIndexOf(value, values)) { // if this turned out to be true then it is a unique entry // so go ahead and push it to our union array ret.push(value); } } } // we should have a flattened/unique array now, return it return ret; }; var union = enyo.union; //*@public /** Returns the unique values found in one or more arrays. */ enyo.unique = union; var unique = enyo.unique; //*@public /** Reduces one or more arrays, removing any duplicate entries across them. */ enyo.reduce = merge; //*@public /** Convenience method that takes an array of properties and an object as parameters. Returns a new object with just those properties named in the array that are found to exist on the base object. If the third parameter is true, falsy values will be ignored. */ enyo.only = function (properties, object, ignore) { var ret = {}; var idx = 0; var len; var property; // sanity check the properties array if (!exists(properties) || !(properties instanceof Array)) { return ret; } // sanity check the object if (!exists(object) || "object" !== typeof object) { return ret; } // reduce the properties array to just unique entries properties = unique(properties); // iterate over the properties given and if the property exists on // the object copy its value to the return array for (len = properties.length; idx < len; ++idx) { property = properties[idx]; if (property in object) { if (true === ignore && !object[property]) { continue; } ret[property] = object[property]; } } // return the array of values we found for the given properties return ret; }; //*@public /** Convenience method that takes two objects as parameters. For each key from the first object, if the key also exists in the second object, a mapping of the key from the first object to the key from the second object is added to a result object, which is eventually returned. In other words, the returned object maps the named properties of the first object to the named properties of the second object. The optional third parameter is a boolean designating whether to pass unknown key/value pairs through to the new object. If true, those keys will exist on the returned object. */ enyo.remap = function (map, obj, pass) { var $key, $val, $ret = pass? enyo.clone(obj): {}; for ($key in map) { $val = map[$key]; if ($key in obj) { $ret[$val] = obj.get? obj.get($key): obj[$key]; } } return $ret; }; //*@public /** Convenience method that takes an array of properties and an object as parameters. Returns a new object with all of the keys in the object except those specified in the _properties_ array. The values are shallow copies. */ enyo.except = function (properties, object) { // the new object to return with just the requested keys var ret = {}; var keep; var idx = 0; var len; var key; // sanity check the properties array if (!exists(properties) || !(properties instanceof Array)) { return ret; } // sanity check the object if (!exists(object) || "object" !== typeof object) { return ret; } // we want to only use the union of the properties and the // available keys on the object keep = union(properties, keys(object)); // for every property in the keep array now copy that to the new // hash for (len = keep.length; idx < len; ++idx) { key = keep[idx]; // if the key was specified in the properties array but does not // exist in the object ignore it if (!(key in object)) { continue; } ret[key] = object[key]; } // return the new hash return ret; }; //*@public /** Helper method that accepts an array of objects and returns a hash of those objects indexed by the specified property. If a filter is provided, it should accept four parameters: the key, the value (object), the current mutable map reference, and an immutable copy of the original array of objects for comparison. */ enyo.indexBy = function (property, array, filter) { // the return value - indexed map from the given array var map = {}; var value; var len; var idx = 0; // sanity check for the array with an efficient native array check if (!exists(array) || !(array instanceof Array)) { return map; } // sanity check the property as a string if (!exists(property) || "string" !== typeof property) { return map; } // the immutable copy of the array var copy = enyo.clone(array); // test to see if filter actually exsits filter = exists(filter) && "function" === typeof filter? filter: undefined; for (len = array.length; idx < len; ++idx) { // grab the value from the array value = array[idx]; // make sure that it exists and has the requested property at all if (exists(value) && exists(value[property])) { if (filter) { // if there was a filter use it - it is responsible for // updating the map accordingly filter(property, value, map, copy); } else { // use the default behavior - check to see if the key // already exists on the map it will be overwritten map[value[property]] = value; } } } // go ahead and return our modified map return map; }; //*@public /** Expects as parameters a string, _property_, and an array of objects that may have the named property. Returns an array of all the values of the named property in the objects in the array. */ enyo.pluck = function (property, array) { var ret = []; var idx = 0; var len; // if we don't have a property to look for or an array of // objects to search through we have to return an empty array if (!(exists(property) && exists(array))) { return ret; } // if it isn't actually an array, return an empty array if (!(array instanceof Array)) { return ret; } // if property isn't a string, then return an empty array if ("string" !== typeof property) { return ret; } // now that sanity is established to some extent, let's get // to work for (len = array.length; idx < len; ++idx) { // if the object in the array is actually undefined, skip if (!exists(array[idx])) { continue; } // if it was found, then check to see if the property // exists on it if (exists(array[idx][property])) { ret.push(array[idx][property]); } } // return whatever we found, if anything return ret; }; /** Creates a new array with all elements of _inArray_ that pass the test defined by _inFunc_. If _inContext_ is specified, _inFunc_ is called with _inContext_ as _this_. */ enyo.filter = function(inArray, inFunc, inContext) { var c = inContext || this; if (enyo.isArray(inArray) && inArray.filter) { return inArray.filter(inFunc, c); } else { var results = []; var f = function(e, i, a) { var eo = e; if (inFunc.call(c, e, i, a)) { results.push(eo); } }; enyo.forEach(inArray, f, c); return results; } }; /** Returns an array of all own enumerable properties found on _inObject_. */ enyo.keys = Object.keys || function(inObject) { var results = []; var hop = Object.prototype.hasOwnProperty; for (var prop in inObject) { if (hop.call(inObject, prop)) { results.push(prop); } } // *sigh* IE 8 if (!({toString: null}).propertyIsEnumerable("toString")) { var dontEnums = [ 'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor' ]; for (var i = 0, p; (p = dontEnums[i]); i++) { if (hop.call(inObject, p)) { results.push(p); } } } return results; }; var keys = enyo.keys; /** Clones an existing Array, or converts an array-like object into an Array. If _inOffset_ is non-zero, the cloning starts from that index in the source Array. The clone may be appended to an existing Array by passing the existing Array as _inStartWith_. Array-like objects have _length_ properties, and support square-bracket notation ([]). Often, array-like objects do not support Array methods, such as _push_ or _concat_, and so must be converted to Arrays before use. The special _arguments_ variable is an example of an array-like object. */ enyo.cloneArray = function(inArrayLike, inOffset, inStartWith) { var arr = inStartWith || []; for(var i = inOffset || 0, l = inArrayLike.length; i<l; i++){ arr.push(inArrayLike[i]); } return arr; }; enyo.toArray = enyo.cloneArray; /** Shallow-clones an object or an array. */ enyo.clone = function(obj) { return enyo.isArray(obj) ? enyo.cloneArray(obj) : enyo.mixin({}, obj); }; //* @protected var empty = {}; //* @public /** Will take a variety of options to ultimately mix a set of properties from objects into single object. All configurations accept a boolean as the final parameter to indicate whether or not to ignore _truthy_/_existing_ values on any _objects_ prior. If _target_ exists and is an object, it will be the base for all properties and the returned value. If the parameter is used but is _falsy_, a new object will be created and returned. If no such parameter exists, the first parameter must be an array of objects and a new object will be created as the _target_. The _source_ parameter may be an object or an array of objects. If no _target_ parameter is provided, _source_ must be an array of objects. The _options_ parameter allows you to set the _ignore_ and/or _exists_ flags such that if _ignore_ is true, it will not override any truthy values in the target, and if _exists_ is true, it will only use truthy values from any of the sources. You may optionally add a _filter_ method-option that returns a true or false value to indicate whether the value should be used. It receives parameters in this order: _property_, _source value_, _source values_, _target_, _options_. Note that modifying the target in the filter method can have unexpected results. Setting _options_ to true will set all options to true. */ enyo.mixin = function(target, source, options) { // the return object/target var t; // the source or sources to use var s; var o, i, n, s$; if (enyo.isArray(target)) { t = {}; s = target; if (source && enyo.isObject(source)) { o = source; } } else { t = target || {}; s = source; o = options; } if (!enyo.isObject(o)) { o = {}; } if (true === options) { o.ignore = true; o.exists = true; } // here we handle the array of sources if (enyo.isArray(s)) { for (i=0; (s$=s[i]); ++i) { enyo.mixin(t, s$, o); } } else { // otherwise we execute singularly for (n in s) { s$ = s[n]; if (empty[n] !== s$) { if ((!o.exists || s$) && (!o.ignore || !t[n]) && (o.filter && enyo.isFunction(o.filter)? o.filter(n, s$, s, t, o): true)) { t[n] = s$; } } } } return t; }; //* @public /** Returns a function closure that will call (and return the value of) function _method_, with _scope_ as _this_. _method_ may be a function or the string name of a function-valued property on _scope_. Arguments to the closure are passed into the bound function. // a function that binds this to this.foo var fn = enyo.bind(this, "foo"); // the value of this.foo(3) var value = fn(3); Optionally, any number of arguments may be prefixed to the bound function. // a function that binds this to this.bar, with arguments ("hello", 42) var fn = enyo.bind(this, "bar", "hello", 42); // the value of this.bar("hello", 42, "goodbye"); var value = fn("goodbye"); Functions may be bound to any scope. // binds function 'bar' to scope 'foo' var fn = enyo.bind(foo, bar); // the value of bar.call(foo); var value = fn(); */ enyo.bind = function(scope, method/*, bound arguments*/){ if (!method) { method = scope; scope = null; } scope = scope || enyo.global; if (enyo.isString(method)) { if (scope[method]) { method = scope[method]; } else { throw('enyo.bind: scope["' + method + '"] is null (scope="' + scope + '")'); } } if (enyo.isFunction(method)) { var args = enyo.cloneArray(arguments, 2); if (method.bind) { return method.bind.apply(method, [scope].concat(args)); } else { return function() { var nargs = enyo.cloneArray(arguments); // invoke with collected args return method.apply(scope, args.concat(nargs)); }; } } else { throw('enyo.bind: scope["' + method + '"] is not a function (scope="' + scope + '")'); } }; //*@public /** Binds a callback to a scope. If the object has a "destroyed" property that's truthy, then the callback will not be run if called. This can be used to implement both enyo.Object.bindSafely and for enyo.Object-like objects like enyo.Model and enyo.Collection. */ enyo.bindSafely = function(scope, method/*, bound arguments*/) { if (enyo.isString(method)) { if (scope[method]) { method = scope[method]; } else { throw('enyo.bindSafely: scope["' + method + '"] is null (this="' + this + '")'); } } if (enyo.isFunction(method)) { var args = enyo.cloneArray(arguments, 2); return function() { if (scope.destroyed) { return; } var nargs = enyo.cloneArray(arguments); return method.apply(scope, args.concat(nargs)); }; } else { throw('enyo.bindSafely: scope["' + method + '"] is not a function (this="' + this + '")'); } }; /** Calls method _inMethod_ on _inScope_ asynchronously. Uses _window.setTimeout_ with minimum delay, usually around 10ms. Additional arguments are passed to _inMethod_ when it is invoked. */ enyo.asyncMethod = function(inScope, inMethod/*, inArgs*/) { return setTimeout(enyo.bind.apply(enyo, arguments), 1); }; /** Calls named method _inMethod_ (String) on _inObject_ with optional arguments _inArguments_ (Array), if the object and method exist. enyo.call(myWorkObject, "doWork", [3, "foo"]); */ enyo.call = function(inObject, inMethod, inArguments) { var context = inObject || this; if (inMethod) { var fn = context[inMethod] || inMethod; if (fn && fn.apply) { return fn.apply(context, inArguments || []); } } }; /** Returns the current time. The returned value is equivalent to _new Date().getTime()_. */ enyo.now = Date.now || function() { return new Date().getTime(); }; //* @protected enyo.nop = function(){}; enyo.nob = {}; enyo.nar = []; // this name is reported in inspectors as the type of objects created via delegate, // otherwise we would just use enyo.nop enyo.instance = function() {}; // some platforms need alternative syntax (e.g., when compiled as a v8 builtin) if (!enyo.setPrototype) { enyo.setPrototype = function(ctor, proto) { ctor.prototype = proto; }; } // boodman/crockford delegation w/cornford optimization enyo.delegate = function(proto) { enyo.setPrototype(enyo.instance, proto); return new enyo.instance(); }; //* @public /** Takes a string and trims leading and trailing spaces. If the string has no length, is not a string, or is a falsy value, it will be returned without modification. */ enyo.trim = function (str) { return str && str.replace? (str.replace(/^\s+|\s+$/g, "")): str; }; // use built-in .trim when available in JS runtime if (String.prototype.trim) { enyo.trim = function(str) { return str && str.trim? str.trim() : str; }; } //*@public /** Efficient _uuid_ generator according to RFC4122 for the browser. */ enyo.uuid = function () { // TODO: believe this can be even faster... var t, p = ( (Math.random().toString(16).substr(2,8)) + "-" + ((t=Math.random().toString(16).substr(2,8)).substr(0,4)) + "-" + (t.substr(4,4)) + ((t=Math.random().toString(16).substr(2,8)).substr(0,4)) + "-" + (t.substr(4,4)) + (Math.random().toString(16).substr(2,8)) ); return p; }; })();