new function () {

function generic (c) {
  Array.prototype.slice.call(arguments, 1).forEach(function (n) {
    if (!c[n]) c[n] = function () {
      return Function.prototype.call.apply(c.prototype[n], arguments);
    }
  });
}
/* -------------------------------------------------------------------- Array */
var p = Array.prototype;
if (!p.filter) {
  p.filter = function(fn, thisp) {
    for (var r = [], l = this.length, i = 0, v; --l >= 0; i++)
      if (i in this && fn.call(thisp, v = this[i], i, this)) r[r.length] = v;
    return r;
  };
}
if (!p.forEach) {
  p.forEach = function (fn, thisp) {
    for (var l = this.length, i = 0; --l >= 0; i++)
      if (i in this) fn.call(thisp, this[i], i, this);
  }
}
if (!p.indexOf) {
  p.indexOf = function (e, i) {
    var l = this.length;
    i = (i < 0) ? Math.ceil(i) : (i > 0) ? Math.floor(i) : 0;
    if (i < 0) i += l;
    for (; i < l; ++i)
      if (i in this && this[i] === e) return i;
    return -1;
  }
}
if (!p.map) {
  p.map = function (fn, thisp) {
    for (var r = new Array(l), l = this.length, i = 0; --l >= 0; ++i)
      if (i in this) r[i] = fn.call(thisp, this[i], i, this);
    return r;
  }
}
p.pushAll = function () {
  for (var a, l = arguments.length, i = 0; --l >= 0;) {
    a = arguments[i++];
    if (a instanceof Array) 
      Array.prototype.push.apply(this, a);
    else
      for (var j = a.length, k = 0; --j >= 0; this[this.length] = a[k++]);
  }
  return this;
}
generic(Array, 'filter', 'forEach', 'indexOf', 'map', 'pushAll', 'slice');
/* ------------------------------------------------------------------- Object */
Object.extend = function (a, b) {
  for (var p in b) a[p] = b[p];
  return a;
}
/* ------------------------------------------------------------------- String */
var p = String.prototype;
if (!p.trim) {
  p.trim = function () {
    var s = this.replace(/^\s\s*/, ''), ws = /\s/, i = s.length;
    while (ws.test(s.charAt(--i)));
    return s.slice(0, i + 1);
  }
}
/*
if (!p.endsWith) {
  p.endsWith = function (s) {
    return this.indexOf(s, this.length - s.length) != -1;
  }
}
p.format = function () {
  var a = arguments;
  return this.replace(/\$(\d)/g, function (m, i) { return a[i-1] });
}
*/
/* ------------------------------------------------------------------- Number */
Number.prototype.format = function (c, d, t) {
  var s = c >= 0 ? this.toFixed(c) : ''+this, i = s.lastIndexOf('.'), s = s.split(''), m = +(s[0] == '-'), g = 0;
  if (i == -1) i = s.length; else s[i] = d||'.';
  while (--i > m) if (!(++g % 3)) s.splice(i, 0, t||',');
  return s.join('');
}
Number.prototype.toPadString = function (w) {
  return ('000000000000' + this).slice(-w);
}  
/* --------------------------------------------------------------------- Math */
/*
Math.round2 = function (v, d) {
  var p = Math.pow(10, d)
  return Math.round(v * p) / p;
}
*/
/* --------------------------------------------------------------------- DOM */
var MSIE = /MSIE (\d+)/.exec(navigator.userAgent);
if (MSIE) MSIE = +MSIE[1];
var focusables   = { 'A':1,'BODY':1,'BUTTON':1,'FRAME':1,'IFRAME':1,'IMG':1,'INPUT':1,'ISINDEX':1,'OBJECT':1,'SELECT':1,'TEXTAREA':1 },
    formControls = { 'BUTTON':1,'INPUT':1,'SELECT':1,'TEXTAREA':1 };
window.DOM = {
  addEventListener: function (o, t, fn) {
    if (o.addEventListener) o.addEventListener(t, fn, false);
    else if (o.attachEvent) o.attachEvent('on'+t, fn);
    else o['on'+t] = fn;
  },
  removeEventListener: function (o, t, fn) {
    if (o.removeEventListener) o.removeEventListener(t, fn, false);
    else if (o.detachEvent) o.detachEvent('on'+t, o);
    else if (o[t = 'on'+t] === this) o[t] = null;
  },
  cancelEvent: function (e) {
    var e = e||window.event;
    if (e.stopPropagation) e.stopPropagation();
    else e.cancelBubble = true;
    if (e.preventDefault) e.preventDefault();
    else e.returnValue = false;
    return false;
  },
/*
  children: function (e) {
    return Array.filter(e.childNodes, function (n) { return n.nodeType === 1 });
  },
  getParentByTagName: function (e, n) {
    while (e = e.parentNode)
      if (e.nodeName == n) 
        return e;
  },
  firstElementChild: function (e) {
    e = e.firstChild;
    while (e && e.nodeType != 1)
      e = e.nextSibling;
    return e;
  },
  lastElementChild: function (e) {
    e = e.lastChild;
    while (e && e.nodeType != 1)
      e = e.previousSibling;
    return e;
  },
  nextElementSibling: function (e) {
    do {
      e = e.nextSibling;
    } while (e && e.nodeType != 1);
    return e;
  },
  getFollowingElement: function (e, fn) {
    var n;
    while (e) {
      if (n = e.nextSibling) {
        if (fn(e = n) || ((n = e.firstChild) && fn(e = n)))
          return e;
      }
      else e = e.parentNode;
    }
  },
*/
  removeChild: function (e) {
    e.parentNode.removeChild(e);
  },
  removeChildren: function (e) {
    with (e) while (firstChild) removeChild(firstChild);
    return e;
  },
  hasClass: function (e, c) {
    return (' '+e.className+' ').indexOf(' '+c+' ') !== -1;
  },
  addClass: function (e, c) {
    if (!DOM.hasClass(e, c))
      return e.className += ' '+c, true;
  },
  removeClass: function (e, c) {
    e.className = (' '+e.className+' ').replace(' '+c+' ', ' ').trim();
  },
  toggleClass: function (e, c, b) {
    return b ? DOM.addClass(e, c) : DOM.removeClass(e, c);
  },
  isDisabled: function (e) {
    return e.disabled;
  },
  isChecked: function (e) {
    return e.checked;
  },
  // http://nemisj.com/tag/tabindex/
  isFocusable: MSIE
  ? function (e) {
    return e.tabIndex >= 0 && !e.disabled && focusables[e.nodeName] && e.type != 'hidden';
  }
  : function (e) {
    return e.tabIndex >= 0 && !e.disabled;
  },
  isFormControl: function (e) {
    return formControls[e.nodeName] && e.type != 'hidden';
  },
  disable: function (e) {
    if ('disabled' in e)
      e.disabled = true;
  },
  enable: function (e) {
    if ('disabled' in e)
      e.disabled = false;
  },
  check: function (e) {
    if ('checked' in e)
      e.checked = true;
  },
  uncheck: function (e) {
    if ('checked' in e)
      e.checked = false;
  },
  getAbsolutePosition: function (e) {
    var l = 0, t = 0;
    do {
      l += e.offsetLeft;
      //l -= e.scrollLeft || 0;
      t += e.offsetTop;
      //t -= e.scrollTop || 0;
    } while (e = e.offsetParent);
    return { left: l, top: t };
  },
  focusNext: function (e) {
    var n, fn = DOM.isFocusable;
    while (e) {
      if (n = e.nextSibling) {
        if (fn(e = n) || ((n = e.firstChild) && fn(e = n))) {
          e.focus();
          return e;
        }
      }
      else e = e.parentNode;
    }
  } 
}
/* ---------------------------------------------------------------------- CSS */
window.CSS = {
  scroll: function (p) {
    var d = document, o = d.createElement('DIV'), i = o.appendChild(d.createElement('DIV')), s = d.styleSheets[1], w, v;
    with (o.style) position='absolute', visibility='hidden', width=height='100px', overflow='hidden';
    with (i.style) width=height='100%';
    d.body.appendChild(o);
    w = i.offsetWidth;
    o.style.overflow = 'scroll';
    v = i.offsetWidth;
    w -= (w == v) ? o.clientWidth : v;
    d.body.removeChild(o);
    if (p) for (var n in p) {
      if (s.insertRule) s.insertRule(n+'{'+p[n]+':'+w+'px}', 0);
      else if(s.addRule) s.addRule(n, p[n]+':'+w+'px');
    }
    return w;
  }
}
/* ----------------------------------------------------------------- Encoding */
new function () {
  var r = /([ %&+=?])/g,
      m = { ' ':'+', '%':'%25', '&':'%26', '+':'%2B', '=':'%3D', '?':'%3F' };
  window.URL = {
    encode: function (s) {
      return String(s).replace(r, function (_, c) { return m[c] });
    },
    build: function (o) {
      var s = '', v;
      for (var n in o) {
        if ((v = o[n]) != null && (v = String(v)).length) {
          if (s.length) s += '&'; 
          s += URL.encode(n)+'='+URL.encode(v);
        }
      }
      return s;
    }
  }
}
/* --------------------------------------------------------------------- JSON */
if (!window.JSON) new function () {
  var r = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, 
      m = { '\b':'\\b', '\t':'\\t', '\n':'\\n', '\f':'\\f', '\r':'\\r', '"':'\\"', '\\':'\\\\' };
  function q (s) {
    return '"'+s.replace(r, function (c) {
      return m[c] || '\\u'+('0000'+c.charCodeAt(0).toString(16)).slice(-4);
    })+'"';
  }
  window.JSON = {
    parse: function (s) {
      if (typeof s === 'string' && s.length) 
        return new Function('return ('+s+')')();
    },
    stringify: function (v) {
      switch (typeof v) {
        case 'string':
          return q(v);
        case 'boolean':
          return String(v);
        case 'number':
          return isFinite(v) ? String(v) : 'null';
        case 'object':
          if (v) {
            var r = [];
            if (Object.prototype.toString.apply(v) === '[object Array]') {
              for (var i = v.length; --i >= 0; r[i] = JSON.stringify(v[i]));
              return '['+r.join(',')+']';
            }
            for (var k in v) {
              if (Object.hasOwnProperty.call(v, k))
                r[r.length] = q(String(k))+':'+JSON.stringify(v[k]);
            }
            return '{'+r.join(',')+'}';
          }
        case 'null':
        case 'undefined':
          return 'null';
        default:
          throw new TypeError('Illegal type for JSON: ' + typeof v);
      }
    }
  }
}
/* ----------------------------------------------------------- XMLHttpRequest */
if (!window.XMLHttpRequest && window.ActiveXObject) {
  window.XMLHttpRequest = function () {
    var x = function (p) {
      try { return new ActiveXObject(p) } catch(e) {}
    }
    return x('Msxml3.XMLHTTP')
        || x("Msxml2.XMLHTTP.6.0")
        || x("Msxml2.XMLHTTP.3.0")
        || x("Msxml2.XMLHTTP")
        || x("Microsoft.XMLHTTP");
  };
}
/* ---------------------------------------------------------------- innerText */
if (window.Element) {
  p = window.Element.prototype;
  if (!('innerText' in p)) {
    p.__defineGetter__('innerText', function () {
      return this.textContent;
    });
    p.__defineSetter__('innerText', function (t) {
      this.textContent = t;
    });
  }
}

}

