function number_format(number, decimals, point, separator)
{
    number=new String(number);
    if(!isNaN(number))
    {
        point = point ? point : '.';
        number = number.split('.');
        if(!(separator===undefined))
        {
            var tmp_number = new Array();
            for(var i = number[0].length, j = 0; i > 0; i -= 3)
            {
                var pos = i > 0 ? i - 3 : i;
                tmp_number[j++] = number[0].substring(i, pos);
            }
            number[0] = tmp_number.reverse().join(separator);
        }

        if(decimals && number[1]) {
            number[1] = number[1].substr(0,decimals);
//                    number[1] = Math.round(parseFloat(number[1].substr(0, decimals) + '.' + number[1].substr(decimals, number[1].length), 10));
            if (decimals)number=number.join(point);
            return(number);
        } else if (decimals=="0" && number[1]) {
            number[1] = number[1].substr(0,decimals);
            return(number.join(""));
        } return number;
    }
	else return("0");
}

function str_repeat(subject, length)
{
   var output = subject;
   for (var i = 1; i < length; i++) { output += subject; }
   return output;
}
function str_pad(subject, length, string, type)
{
    subject=""+subject;
    if (type != 'STR_PAD_LEFT' && type != 'STR_PAD_RIGHT' && type != 'STR_PAD_BOTH') { type = 'STR_PAD_LEFT'; }
    if (subject.length < length)
    {
        length = length - subject.length;
        if (type == 'STR_PAD_LEFT') { subject = str_repeat(string, length) + subject; }
        else if (type == 'STR_PAD_RIGHT') { subject = subject + str_repeat(string, length); }
        else if (type == 'STR_PAD_BOTH') { subject = str_repeat(string, length / 2) + subject + str_repeat(string, length / 2); }
    }
    return subject;
}

String.PAD_LEFT  = 0;
String.PAD_RIGHT = 1;
String.PAD_BOTH  = 2;
String.prototype.pad = function(size, pad, side) {
  var str = this, append = "", size = (size - str.length);
  var pad = ((pad != null) ? pad : " ");
  if ((typeof size != "number") || ((typeof pad != "string") || (pad == ""))) {
    throw new Error("Wrong parameters for String.pad() method.");
  }
  if (side == String.PAD_BOTH) {
    str = str.pad((Math.floor(size / 2) + str.length), pad, String.PAD_LEFT);
    return str.pad((Math.ceil(size / 2) + str.length), pad, String.PAD_RIGHT);
  }
  while ((size -= pad.length) > 0) {
    append += pad;
  }
  append += pad.substr(0, (size + pad.length));
  return ((side == String.PAD_LEFT) ? append.concat(str) : str.concat(append));
}
String.prototype.trim = function() {
    return this.replace(/^\s+|\s+$/g, ''); 
} 

String.prototype.rtrim = function() { 
    return this.replace(/\s+$/, ''); 
} 

String.prototype.ltrim = function() { 
    return this.replace(/^\s+/, ''); 
} 

String.prototype.ucfirst = function() { 
    return this.charAt(0).toUpperCase() + this.substr(1);
} 
String.prototype.repeat = function(multiplier) { 
    var newString = ''; 

    for (var i = 0; i < multiplier; i++) { 
        newString += this; 
    } 

    return newString; 
} 

String.prototype.lpad = function(padLength, padString) { 
    return (this._padString(padLength, padString) + this); 
} 

String.prototype.rpad = function(padLength, padString) { 
    return (this + this._padString(padLength, padString)); 
} 

/* Private method */
String.prototype._padString = function(padLength, padString) { 
    if (this.length >= padLength) {
        return ''; 
    } 

    var multiplier = Math.ceil((padLength - this.length) / padString.length); 
    padString = padString.repeat(multiplier); 

    return padString.substr(0, padLength - this.length); 
}
Function.prototype.wrap = function(subClass, functions)
{
   var name = subClass.getName();
   // wrap sub-class' prototype functions
   for ( var i in subClass.prototype )
   {
      if ( subClass.prototype[i] instanceof(Function) )
      {
         // but not instanceOf and typeOf
         if ( i == 'instanceOf' ) continue;
         if ( i == 'typeOf' ) continue;
         this.prototype[i] = new Function("return " + name + ".prototype." +
            i + ".apply(this." + name + ", arguments); " +
            "this.onMethodCall(" + name + ".prototype." + i + ",arguments);");
      }
   }
   // wrap any other user specified functions
   if ( functions )
   {
      for ( i = 0; i < functions.length; i++ )
      {
         var f = functions[i];
         this.prototype[f] = new Function("return " + name + ".prototype." +
            f + ".apply(this." + name + ", arguments); " +
            "this.onMethodCall(" + name + ".prototype." + f + ",arguments);");      }
   }
   // provide default onMethodCall()
   if ( !this.prototype.onMethodCall )
   {
      this.prototype.onMethodCall = function(){};
   }
}

