
// LANGUAGE EXTENSIONS
// -------------------
//
// Don't mess with Object.prototype:  doing so breaks for(in) loops.  Messing with other built-in
// types is fine; note that this assumes that you shouldn't attempt to treat Array objects as 
// dictionaries, ever.  Use Object for that.
//
//
// Mozilla JS 1.5 forEach.
// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach
//
if (!Array.prototype.forEach) {
    Array.prototype.forEach = function(fun /*, thisp */) {
        var len = this.length;
        if (typeof fun != "function") {
            throw new TypeError();
        }
        
        var thisp = arguments[1];
        for (var i = 0; i < len; i++) {
            if (i in this) {
                fun.call(thisp, this[i], i, this);
            }
        }
    };
}

// Mozilla JS 1.5 Array.filter()
// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:filter
//
if (!Array.prototype.filter) {
    Array.prototype.filter = function(fun /*, thisp*/) {
        var len = this.length;
        if (typeof fun != "function") {
            throw new TypeError();
        }
        
        var res = new Array();
        var thisp = arguments[1];
        for (var i = 0; i < len; i++) {
            if (i in this) {
                var val = this[i]; // in case fun mutates this
                if (fun.call(thisp, val, i, this)) {
                    res.push(val);
                }
            }
        }
        
        return res;
    };
}   


// Mozilla JS 1.5 Array.map
// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:map
//
if (!Array.prototype.map) {
    Array.prototype.map = function(fun /*, thisp*/) {
        var len = this.length;
        if (typeof fun != "function") {
            throw new TypeError();
        }
        
        var res = new Array(len);
        var thisp = arguments[1];
        for (var i = 0; i < len; i++) {
            if (i in this) {
                res[i] = fun.call(thisp, this[i], i, this);
            }
        }

        return res;
    };
}


// Mozilla JS 1.5 Array.every
// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:every
//
if (!Array.prototype.every) {
    Array.prototype.every = function(fun /*, thisp*/) {
        var len = this.length;
        if (typeof fun != "function") {
            throw new TypeError();
        }
        
        var thisp = arguments[1];
        for (var i = 0; i < len; i++) {
            if (i in this && !fun.call(thisp, this[i], i, this)) {
                return false;
            }
        }
        
        return true;
    };
}


// Mozilla JS 1.5 Array.some
// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some
//
if (!Array.prototype.some) {
    Array.prototype.some = function(fun /*, thisp*/) {
        var len = this.length;
        if (typeof fun != "function") {
            throw new TypeError();
        }
        
        var thisp = arguments[1];
        for (var i = 0; i < len; i++) {
            if (i in this && fun.call(thisp, this[i], i, this)) {
                return true;
            }
        }
        
        return false;
    };
}

// http://developer.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:lastIndexOf
if (!Array.prototype.indexOf) {
	Array.prototype.indexOf = function (obj, fromIndex) {
		if (fromIndex == null) {
			fromIndex = 0;
		} else if (fromIndex < 0) {
			fromIndex = Math.max(0, this.length + fromIndex);
		}
		for (var i = fromIndex; i < this.length; i++) {
			if (this[i] === obj) {
				return i;
            }
		}
		return -1;
	};
}

// http://developer.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:lastIndexOf
if (!Array.prototype.lastIndexOf) {
	Array.prototype.lastIndexOf = function (obj, fromIndex) {
		if (fromIndex == null) {
			fromIndex = this.length - 1;
		} else if (fromIndex < 0) {
			fromIndex = Math.max(0, this.length + fromIndex);
		}
		for (var i = fromIndex; i >= 0; i--) {
			if (this[i] === obj) {
				return i;
            }
		}
		return -1;
	};
}


Array.prototype.contains = function (obj) {
	return this.indexOf(obj) != -1;
};

//
//
var object_forEach = function(object, callback, scope) 
{
    if (!scope) {
        scope = this;
    }
    for (var i in object) {
        callback.call(scope, object[i], i, object);
    }
};
    
var object_map = function(object, callback, scope)
{
    if (!scope) {
        scope = this;
    }
    var rv = {};
    for (var i in object) {
        var result = callback.call(scope, object[i], i, object);
        rv[i] = result;
    }
    return rv;
};

var object_filter = function(object, callback, scope)
{
    if (!scope) {
        scope = this;
    }
    var rv = {};
    for (var i in object) {
        var val = object[i]; // in case callback mutates object
        if (callback.call(scope, val, i, object)) {
            rv[i] = val;
        }
    }
    return rv;
};



