// intentionally a class method, not an instance method - this allows copying objects that not *real* arrays, such as function arguments.
Array.Copy = function(original){
  var i,result = [];
  for(i=0;i<original.length;i++){
    result.push(original[i]);
  }
  return result;
}
// first parameters is the object to which the method will be bound. All additional parameters will be passed as parameters to the method;
// can be handy when used in conjunction with events
/*
  example:
  var myObject = {
    name:"fred"
  };
  function doTest(param1,param2){
    alert(this.name +'\n'+ param1 +'\n'+ param2);
  }
  var boundMethod = doTest.bind(myObject,"12","jane");
  boundMethod();
*/
Function.prototype.bind = function() {
  var method = this;
  var args = Array.Copy(arguments);
  var obj = args.shift();
  return function() {
    return method.apply(obj, args);
  };
}

// JavaScript 1.6 methods
if(!Array.forEach){
  // perform action on each item of array - used in place of: for(i=0;i<myArray.length;i++) {...}
  /*
    example:
    var myArray = ['apple','banana','pear'];
    myArray.forEach(function(fruit){
      document.write(fruit);
    });
  */
	Array.prototype.forEach = function(fn, thisObj) {
    var scope = thisObj || window;
    for ( var i=0, j=this.length; i < j; ++i){
      fn.call(scope, this[i], i, this);
    }
  }
}
if(!Array.every){
  // check if every item in array matches some criteria
  /*
    example:
    var myArray = [
      {name:'apple',type:'fruit'},
      {name:'steak',type:'meat'},
      {name:'pear',type:'fruit'}
    ];
    // returns false
    var allItemsAreFruits = myArray.every(function(food){
      return (food.type == "fruit");
    });
  */
  Array.prototype.every =  function(fn, thisObj) {
    var scope = thisObj || window;
    for ( var i=0, j=this.length; i < j; ++i){
      if(!fn.call(scope, this[i], i, this)){
        return false;
      }
    }
    return true;
  }
}
if(!Array.some){
  // check if every item in array matches some criteria
  /*
    example:
    var myArray = [
      {name:'apple',type:'fruit'},
      {name:'steak',type:'meat'},
      {name:'pear',type:'fruit'}
    ];
    // returns true
    var someItemsAreFruits = myArray.some(function(food){
      return (food.type == "fruit");
    });
  */
  Array.prototype.some = function(fn, thisObj) {
      var scope = thisObj || window;
    for ( var i=0, j=this.length; i < j; ++i){
          if(fn.call(scope, this[i], i, this)){
              return true;
          }
      }
      return false;
  }
}
if(!Array.map){
  // create a new array based on contents of original array
  /*
    example:
    var myArray = [
      {name:'apple',type:'fruit'},
      {name:'steak',type:'meat'},
      {name:'pear',type:'fruit'}
    ];
    var arrayOfHtml = myArray.map(function(food){
      return "<div>"+ food.name +" ("+ food.type +")</div>";
    });
  */
  Array.prototype.map = function(fn, thisObj) {
      var scope = thisObj || window;
      var a = [];
      for ( var i=0, j=this.length; i < j; ++i){
          a.push(fn.call(scope, this[i], i, this));
      }
      return a;
  }
}
if(!Array.filter){
  // create a new array of filtered results
  /*
    example:
    var myArray = [
      {name:'apple',type:'fruit'},
      {name:'steak',type:'meat'},
      {name:'pear',type:'fruit'}
    ];
    // returns true
    var fruits = myArray.map(function(food){
      return (food.type == "fruit");
    });
  */
  Array.prototype.filter =  function(fn, thisObj) {
      var scope = thisObj || window;
      var a = [];
      for ( var i=0, j=this.length; i < j; ++i){
          if(!fn.call(scope, this[i], i, this)){
              continue;
          }
          a.push(this[i]);
      }
      return a;
  }
}
if(!Array.indexOf){
  // returns index of specified element (-1 if not found)
  Array.prototype.indexOf = function(el, start) {
      var start = start || 0;
      for ( var i=start, j=this.length; i < j; ++i){
          if(this[i] === el){
              return i;
          }
      }
      return -1;
  }
}
if(!Array.lastIndexOf){
  // returns the last index of specified element (-1 if not found)
  Array.prototype.lastIndexOf = function(el, start) {
      var start = start || this.length;
      if(start >= this.length){
          start = this.length;
      }
      if(start < 0){
           start = this.length + start;
      }
      for ( var i=start; i >= 0; --i){
          if(this[i] === el){
              return i;
          }
      }
      return -1;
  }
}
