2011-10-24 12:33:54 -04:00
|
|
|
/**
|
|
|
|
* Util Object
|
2012-03-29 11:58:32 -04:00
|
|
|
*
|
2011-10-24 12:33:54 -04:00
|
|
|
* Various object and string manipulation functions
|
2011-10-24 19:18:22 -04:00
|
|
|
* Note: these are based on similar phpjs functions: http://phpjs.org
|
2011-10-24 12:33:54 -04:00
|
|
|
*/
|
|
|
|
(function(){
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
2012-03-29 11:58:32 -04:00
|
|
|
var reverse_key_sort = function(o)
|
2011-10-31 11:56:59 -04:00
|
|
|
{
|
|
|
|
//Define some variables
|
|
|
|
var keys = [],
|
|
|
|
num_keys = 0,
|
|
|
|
new_o = {},
|
|
|
|
i;
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-31 11:56:59 -04:00
|
|
|
//Extract the keys
|
|
|
|
keys = u.object_keys(o);
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-31 11:56:59 -04:00
|
|
|
//Sort the keys
|
2012-03-29 11:58:32 -04:00
|
|
|
keys.sort(function (b, a) {
|
2011-10-31 11:56:59 -04:00
|
|
|
var aFloat = parseFloat(a),
|
|
|
|
bFloat = parseFloat(b),
|
|
|
|
aNumeric = aFloat + '' === a,
|
|
|
|
bNumeric = bFloat + '' === b;
|
2011-12-12 11:47:20 -05:00
|
|
|
|
2012-03-29 11:58:32 -04:00
|
|
|
if (aNumeric && bNumeric)
|
2011-10-24 12:33:54 -04:00
|
|
|
{
|
2011-10-31 11:56:59 -04:00
|
|
|
return aFloat > bFloat ? 1 : aFloat < bFloat ? -1 : 0;
|
2012-03-29 11:58:32 -04:00
|
|
|
}
|
|
|
|
else if (aNumeric && !bNumeric)
|
2011-10-31 11:56:59 -04:00
|
|
|
{
|
|
|
|
return 1;
|
2012-03-29 11:58:32 -04:00
|
|
|
}
|
|
|
|
else if (!aNumeric && bNumeric)
|
2011-10-31 11:56:59 -04:00
|
|
|
{
|
|
|
|
return -1;
|
2011-10-24 12:33:54 -04:00
|
|
|
}
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-31 11:56:59 -04:00
|
|
|
return a > b ? 1 : a < b ? -1 : 0;
|
|
|
|
});
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-11-06 17:11:34 -05:00
|
|
|
// cache object/array size
|
2011-10-31 11:56:59 -04:00
|
|
|
num_keys = keys.length;
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-11-06 17:11:34 -05:00
|
|
|
// Recreate the object/array
|
2011-10-31 11:56:59 -04:00
|
|
|
for(i=0; i < num_keys; i++)
|
|
|
|
{
|
|
|
|
new_o[keys[i]] = o[keys[i]];
|
|
|
|
}
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-31 11:56:59 -04:00
|
|
|
return new_o;
|
|
|
|
},
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-11-01 18:56:27 -04:00
|
|
|
/**
|
|
|
|
* String and object manipulation utilities
|
2012-03-29 11:58:32 -04:00
|
|
|
*
|
2011-11-01 18:56:27 -04:00
|
|
|
* @namespace
|
|
|
|
* @name util
|
|
|
|
* @memberOf $_
|
|
|
|
*/
|
2011-10-31 11:56:59 -04:00
|
|
|
u = {
|
2011-11-01 18:56:27 -04:00
|
|
|
/**
|
|
|
|
* Retrieve the keys, or member names of an object
|
2012-03-29 11:58:32 -04:00
|
|
|
*
|
2011-11-01 18:56:27 -04:00
|
|
|
* @name object_keys
|
|
|
|
* @memberOf $_.util
|
|
|
|
* @function
|
|
|
|
* @param object
|
|
|
|
* @return array
|
|
|
|
* @type array
|
|
|
|
*/
|
2011-10-24 12:33:54 -04:00
|
|
|
object_keys: function(o)
|
|
|
|
{
|
|
|
|
var keys = [],
|
|
|
|
k;
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-24 12:33:54 -04:00
|
|
|
for(k in o)
|
|
|
|
{
|
|
|
|
if(o.hasOwnProperty(k))
|
|
|
|
{
|
|
|
|
keys.push(k);
|
|
|
|
}
|
|
|
|
}
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-24 12:33:54 -04:00
|
|
|
return keys;
|
|
|
|
},
|
2011-11-01 18:56:27 -04:00
|
|
|
/**
|
|
|
|
* Retrieves the values of an object, and returns
|
|
|
|
* them as an array
|
|
|
|
*
|
|
|
|
* @name object_values
|
|
|
|
* @memberOf $_.util
|
|
|
|
* @function
|
|
|
|
* @param object
|
|
|
|
* @return array
|
|
|
|
* @type array
|
|
|
|
*/
|
2011-10-24 12:33:54 -04:00
|
|
|
object_values: function(o)
|
|
|
|
{
|
|
|
|
var vals = [],
|
|
|
|
prop;
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-24 12:33:54 -04:00
|
|
|
for(prop in o)
|
|
|
|
{
|
|
|
|
vals.push(o[prop]);
|
|
|
|
}
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-24 12:33:54 -04:00
|
|
|
return vals;
|
|
|
|
},
|
2011-11-01 18:56:27 -04:00
|
|
|
/**
|
2012-03-29 11:58:32 -04:00
|
|
|
* Creates an object, with the property names of the first array,
|
|
|
|
* and the values of the second. If objects are passed, the values
|
|
|
|
* of the object are used. If the arrays or objects passed are
|
2011-11-01 18:56:27 -04:00
|
|
|
* not the same size, the function will return false.
|
2012-03-29 11:58:32 -04:00
|
|
|
*
|
2011-11-01 18:56:27 -04:00
|
|
|
* @name array_combine
|
|
|
|
* @memberOf $_.util
|
|
|
|
* @function
|
|
|
|
* @param array/object keys
|
|
|
|
* @param array/object vals
|
|
|
|
* @return object
|
|
|
|
* @type object
|
|
|
|
*/
|
2011-10-24 12:33:54 -04:00
|
|
|
array_combine: function(keys, vals)
|
|
|
|
{
|
|
|
|
var new_object = {},
|
|
|
|
num_keys,
|
|
|
|
i = 0;
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-11-06 17:11:34 -05:00
|
|
|
// Extract the keys or values if needed
|
2011-10-24 12:33:54 -04:00
|
|
|
if($_.type(keys) !== "array")
|
|
|
|
{
|
|
|
|
keys = this.object_values(keys);
|
|
|
|
}
|
|
|
|
if($_.type(vals) !== "array")
|
|
|
|
{
|
|
|
|
vals = this.object_values(vals);
|
|
|
|
}
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-11-06 17:11:34 -05:00
|
|
|
// cache the number of keys
|
2011-10-24 12:33:54 -04:00
|
|
|
num_keys = keys.length;
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-24 12:33:54 -04:00
|
|
|
if(num_keys !== vals.length)
|
|
|
|
{
|
|
|
|
console.log("Object combine requires two arrays of the same size");
|
|
|
|
return false;
|
|
|
|
}
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-11-06 17:11:34 -05:00
|
|
|
// Create and return the new object
|
2011-10-24 12:33:54 -04:00
|
|
|
for(i = 0; i < num_keys; i++)
|
|
|
|
{
|
|
|
|
new_object[keys[i]] = vals[i];
|
|
|
|
}
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-24 12:33:54 -04:00
|
|
|
return new_object;
|
|
|
|
},
|
2011-11-01 18:56:27 -04:00
|
|
|
/**
|
|
|
|
* Combines two or more objects/arrays. If the keys are numeric, the outputted
|
|
|
|
* object will have re-indexed keys. If a key/value pair exists in both objects,
|
2012-03-29 11:58:32 -04:00
|
|
|
* indentical values will be droped, but if a key exists with a different value,
|
2011-11-01 18:56:27 -04:00
|
|
|
* with the same key, the value in the second array will replace the value in the
|
|
|
|
* first
|
2012-03-29 11:58:32 -04:00
|
|
|
*
|
2011-11-01 18:56:27 -04:00
|
|
|
* @name object_merge
|
|
|
|
* @memberOf $_.util
|
|
|
|
* @function
|
|
|
|
* @param object [as many as you wish to combine]
|
|
|
|
* @type object
|
|
|
|
* @return object
|
|
|
|
*/
|
2011-10-24 12:33:54 -04:00
|
|
|
object_merge: function()
|
|
|
|
{
|
|
|
|
var args = Array.prototype.slice.call(arguments),
|
|
|
|
arg_len = args.length,
|
|
|
|
new_obj = {},
|
|
|
|
arg,
|
|
|
|
iarg_len = 0,
|
|
|
|
i,
|
|
|
|
j,
|
|
|
|
x,
|
|
|
|
is_array = true;
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-11-06 17:11:34 -05:00
|
|
|
// Check for an array in the arguments
|
2011-10-24 12:33:54 -04:00
|
|
|
for(i=0; i < arg_len; i++)
|
|
|
|
{
|
|
|
|
if($_.type(args[i]) !== "array")
|
|
|
|
{
|
|
|
|
is_array = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-11-06 17:11:34 -05:00
|
|
|
// If all the arguments are javascript arrays
|
2011-10-24 12:33:54 -04:00
|
|
|
if(is_array)
|
|
|
|
{
|
|
|
|
new_obj = [];
|
2011-11-06 17:11:34 -05:00
|
|
|
// Let javascript do all the work!
|
2011-10-24 12:33:54 -04:00
|
|
|
for(i=0; i< arg_len; i++)
|
|
|
|
{
|
|
|
|
new_obj = new_obj.contact(args[i]);
|
|
|
|
}
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-11-06 17:11:34 -05:00
|
|
|
// Return early
|
2011-10-24 12:33:54 -04:00
|
|
|
return new_obj;
|
|
|
|
}
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-11-06 17:11:34 -05:00
|
|
|
// No, there's at least one object
|
2011-10-24 12:33:54 -04:00
|
|
|
for(i=0, x=0; i < arg_len; i++)
|
|
|
|
{
|
|
|
|
arg = args[i];
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-24 12:33:54 -04:00
|
|
|
// If the argument is an array, add the array items as
|
|
|
|
// numeric object properties
|
|
|
|
if ($_.type(arg) == "array")
|
|
|
|
{
|
|
|
|
for (j=0, iarg_len= arg.length; j < iarg_len; j++)
|
|
|
|
{
|
|
|
|
new_obj[x++] = arg[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (j in arg)
|
|
|
|
{
|
|
|
|
if(arg.hasOwnProperty(j))
|
|
|
|
{
|
|
|
|
// If the key is numeric, add the property with
|
|
|
|
// a numeric key
|
|
|
|
if(parseInt(j, 10) + '' === j)
|
|
|
|
{
|
|
|
|
new_obj[x++] = arg[j];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new_obj[j] = arg[j];
|
2012-03-29 11:58:32 -04:00
|
|
|
}
|
2011-10-24 12:33:54 -04:00
|
|
|
}
|
|
|
|
}
|
2012-03-29 11:58:32 -04:00
|
|
|
}
|
2011-10-24 12:33:54 -04:00
|
|
|
}
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-24 12:33:54 -04:00
|
|
|
return new_obj;
|
|
|
|
},
|
2011-11-01 18:56:27 -04:00
|
|
|
/**
|
2012-03-29 11:58:32 -04:00
|
|
|
* Replaces sections of strings in a greedy fashion,
|
2011-11-01 18:56:27 -04:00
|
|
|
* starting with the longest replace pairs first. Accepts
|
|
|
|
* one replace pair as two parameters, or an object, with
|
|
|
|
* from => to replacements as key/value pairs
|
|
|
|
*
|
|
|
|
* @name str_trans
|
|
|
|
* @memberOf $_.util
|
|
|
|
* @function
|
|
|
|
* @param string input_string
|
2011-11-03 16:04:35 -04:00
|
|
|
* @param mixed from (string)/replace pairs (object)
|
|
|
|
* @param [string]
|
2011-11-01 18:56:27 -04:00
|
|
|
* @return string
|
|
|
|
* @type string
|
|
|
|
*/
|
2011-10-24 19:18:22 -04:00
|
|
|
str_trans: function(str, from, to)
|
2011-10-24 12:33:54 -04:00
|
|
|
{
|
2011-10-24 19:18:22 -04:00
|
|
|
var froms = [],
|
|
|
|
tos = [],
|
|
|
|
ret = '',
|
|
|
|
match = false,
|
|
|
|
from_len = 0,
|
|
|
|
str_len = 0,
|
|
|
|
to_len = 0,
|
|
|
|
to_is_str = '',
|
|
|
|
from_is_str = '',
|
|
|
|
strx = '',
|
|
|
|
strw = '',
|
|
|
|
stry = '',
|
|
|
|
from_strx = '',
|
|
|
|
new_str = '',
|
|
|
|
f,
|
|
|
|
i,
|
|
|
|
j;
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-24 19:18:22 -04:00
|
|
|
//Replace pairs? add them to the internal arrays
|
|
|
|
if(typeof from === 'object')
|
|
|
|
{
|
|
|
|
// Sort the keys in descending order for better
|
|
|
|
// replacement functionality
|
2011-10-31 11:56:59 -04:00
|
|
|
from = reverse_key_sort(from);
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-24 19:18:22 -04:00
|
|
|
for(f in from)
|
|
|
|
{
|
|
|
|
if(from.hasOwnProperty(f))
|
|
|
|
{
|
|
|
|
froms.push(f);
|
|
|
|
tos.push(from[f]);
|
|
|
|
}
|
|
|
|
}
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-24 19:18:22 -04:00
|
|
|
from = froms;
|
|
|
|
to = tos;
|
|
|
|
}
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-24 19:18:22 -04:00
|
|
|
//Go through the string, and replace characters as needed
|
|
|
|
str_len = str.length;
|
|
|
|
from_len = from.length;
|
|
|
|
to_len = to.length;
|
|
|
|
to_is_str = typeof to === 'string';
|
|
|
|
from_is_str = typeof from === 'string';
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-24 19:18:22 -04:00
|
|
|
for(i=0; i < str_len; i++)
|
|
|
|
{
|
|
|
|
match = false;
|
|
|
|
if(from_is_str)
|
|
|
|
{
|
|
|
|
strw = str.charAt(i-1);
|
|
|
|
strx = str.charAt(i);
|
|
|
|
stry = str.charAt(i+1);
|
|
|
|
for(j=0; j < from_len; j++)
|
|
|
|
{
|
2011-10-31 11:56:59 -04:00
|
|
|
if(strx == from.charAt(j))
|
2011-10-24 19:18:22 -04:00
|
|
|
{
|
2011-10-31 11:56:59 -04:00
|
|
|
match = true;
|
|
|
|
break;
|
2011-10-24 19:18:22 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for(j=0; j < from_len; j++)
|
|
|
|
{
|
|
|
|
if(str.substr(i, from[j].length) == from[j])
|
|
|
|
{
|
|
|
|
match = true;
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-24 19:18:22 -04:00
|
|
|
//Go past the current match
|
|
|
|
i = (i + from[j].length) -1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(match)
|
|
|
|
{
|
|
|
|
new_str += (to_is_str) ? to.charAt(j) : to[j];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
new_str += str.charAt(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return new_str;
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-24 12:33:54 -04:00
|
|
|
}
|
2012-03-29 11:58:32 -04:00
|
|
|
|
2011-10-24 12:33:54 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
//Add it to the $_ object
|
|
|
|
$_.ext('util', u);
|
2011-10-24 19:18:22 -04:00
|
|
|
}());
|
|
|
|
|