pbojinov
7/16/2013 - 8:04 PM

Extract useful Q.js functions from http://github.com/EGreg/Q.js/blob/master/Q.js

Extract useful Q.js functions from http://github.com/EGreg/Q.js/blob/master/Q.js

/**
 * Add an event listener on an elemnent or array of elements
 * @param element DOMNode
 * @param eventName String
 * @param eventHandler Function
 */
function addEventListener(element, eventName, eventHandler) {

	if (typeOf(eventName) === 'array') {
		for (var i=0, l=eventName.length; i<l; ++i) {
			addEventListener(element, eventName[i], eventHandler);
		}
	}
	if (element.addEventListener) {
		element.addEventListener(eventName, handler, false);
	} else if (element.attachEvent) {
		element.attachEvent('on'+eventName, handler);
	}
}

/**
 * Returns the type of a value
 * @param value
 *
 * return type
 */
function typeOf(value) {
    var s = typeof value;
	if (s === 'object') {
		if (value === null) {
			return 'null';
		}
		if (value instanceof Array || (value.constructor && value.constructor.name === 'Array') || Object.prototype.toString.apply(value) === '[object Array]') {
			s = 'array';
		} 
        else if (typeof(value) != 'undefined' ) {
			return value;
		} 
        else if (typeof(value.constructor) != 'undefined' && typeof(value.constructor.name) != 'undefined') {
			if (value.constructor.name == 'Object') {
				return 'object';
			}
			return value.constructor.name;
		} 
        else {
			return 'object';
		}
	}
	return s;
}

/**
 * Tests if the value is an integer
 * @method isInteger
 * @param value {mixed}
 *  The value to test
 * @return {boolean}
 *	Whether it is an integer
 */
function isInteger(value) {
	return (parseFloat(value) == parseInt(value)) && !isNaN(value);
}

/**
 * Returns the first index in a container with a value that's not undefined
 * @method first
 * @param {array|Object|String} container
 * @return {Number|String}
 *  the index in the container, or null
 * @throws {Q.Exception} If container is not array, object or string
 */
function first(container) {
    if (!container) {
		return null;
	}
	switch (typeof container) {
		case 'array':
			for (var i=0; i<container.length; ++i) {
				if (container[i] !== undefined) {
					return i;
				}
			}
			break;
		case 'object':
			for (var k in container) {
				if (!container.hasOwnProperty(k)) {
					return k;
				}
			}
			break;
		case 'string':
			return 0;
		default:
			throw 'container has to be an array, object or string';
	}
	return null;
}

/**
 * Tests whether a variable contains a false value,
 * or an empty object or array.
 * @param o
 *  The object to test.
 */
function isEmpty(o) {
    if (!o) {
		return true;
	}
	var i, v, t;
	t = typeOf(o);
	if (t === 'object') {
		for (i in o) {
			v = o[i];
			if (v !== undefined) {
				return false;
			}
		}
		return true;
	} 
    else if (t === 'array') {
		return (o.length === 0);
	}
	return false;
}

/**
 * Returns whether an object contains a property directly
 * @param obj Object
 * @param key String
 * @return Boolean
 */
function has(obj, key) {
    return Object.prototype.hasOwnProperty.call(obj, key);
}

/**
 * Shuffles an array
 * @param Array arr
 *  The array passed in is shuffled in place, no return value
 */
function shuffle( arr ) {
  var i = arr.length;
  if ( !i ) return false;
  while ( --i ) {
     var j = Math.floor(Math.random() * ( i + 1 ));
	 var tempi = arr[i];
	 var tempj = arr[j];
	 arr[i] = tempj;
	 arr[j] = tempi;
   }
};

/**
 * Extend some built-in prototypes if they don't exist
 */

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function _Array_prototype_indexOf(searchElement /*, fromIndex */ ) {
		if (this === void 0 || this === null) {
			throw new TypeError();
		}
		var t = Object(this);
		var len = t.length >>> 0;
		if (len === 0) {
			return -1;
		}
		var n = 0;
		if (arguments.length > 0) {
			n = Number(arguments[1]);
			if (n !== n) { // shortcut for verifying if it's NaN
				n = 0;
			} else if (n !== 0 && n !== window.Infinity && n !== -window.Infinity) {
				n = (n > 0 || -1) * Math.floor(Math.abs(n));
			}
		}
		if (n >= len) {
			return -1;
		}
		var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
		for (; k < len; k++) {
			if (k in t && t[k] === searchElement) {
				return k;
			}
		}
		return -1;
	};
}

if (!Date.now) {
    Date.now = function now() {
    	return new Date().getTime();
	};
}

String.prototype.toCapitalized = function _String_prototype_toCapitalized() {
    return (this + '').replace(/^([a-z])|\s+([a-z])/g, function (found) {
		return found.toUpperCase();
	});
};

String.prototype.isUrl = function () {
    return this.match(new RegExp("^[A-Za-z]*:\/\/"));
};

// for browsers like IE8 and below
if (!window.console) {
    function nothing() {}
    window.console = {
        debug: nothing,
        dir: nothing,
        error: nothing,
        group: nothing,
        groupCollapsed: nothing,
        groupEnd: nothing,
        info: nothing,
        log: nothing,
        time: nothing,
        timeEnd: nothing,
        trace: nothing,
        warn: nothing
    };
}