var nav = navigator.userAgent.toLowerCase();

var isIE = nav.indexOf('msie') != -1 && nav.indexOf('opera') == -1;
var isNS = nav.indexOf('netscape') != -1;
var isOpera = nav.indexOf('opera') != -1;
var isFirefox = nav.indexOf('firefox') != -1;
var isEpiphany = nav.indexOf('epiphany') != -1;
var isKonqueror = nav.indexOf('konqueror') != -1;
var isW3C = document.documentElement ? true : false;

var scriptFragment = '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)';

function isDef() {
  for(var i=0; i < arguments.length; ++i)
    if (typeof(arguments[i]) == 'undefined')
      return false;
  return true;
}

function isNum() {
  for (var i=0; i<arguments.length; ++i) {
    if (isNaN(arguments[i]) || typeof(arguments[i]) != 'number')
      return false;
  }
  return true;
}

// EVENTOS *****************************
function aEvent(evt) {
  var e = evt || window.event;
  if (!e)
    return;

  this.type = e.type;
  this.target = e.target || e.srcElement;
  this.relatedTarget = e.relatedTarget;

  var pt;
  if (isDef(e.pageX)) {
    this.pageX = e.pageX;
    this.pageY = e.pageY;
  } else
    if (isDef(e.clientX)) {
      pt = Position.get.Scroll();
      this.pageX = e.clientX + pt.left;
      this.pageY = e.clientY + pt.top;
    }

  if (isDef(e.offsetX)) {
    this.offsetX = e.offsetX;
    this.offsetY = e.offsetY;
  } else
    if (isDef(e.layerX)) {
      this.offsetX = e.layerX;
      this.offsetY = e.layerY;
    } else {
      pt = Position.get.All(this.target);
      this.offsetX = this.pageX - pt.x;
      this.offsetY = this.pageY - pt.y;
    }

  this.keyCode = e.keyCode || e.which || 0;
  this.shiftKey = e.shiftKey;
  this.ctrlKey = e.ctrlKey;
  this.altKey = e.altKey;

  if (typeof e.type == 'string') {
    if (e.type.indexOf('click') != -1)
      this.button = 0;
    else
      if (e.type.indexOf('mouse') != -1)
        this.button = e.button;
  }
}

function attachEvent2(elem, eventType, fn, cap) {
  if (!(elem = getElem(elem)))
    return;
  eventType = eventType.toLowerCase();
  if (elem.addEventListener)
    elem.addEventListener(eventType, fn, cap || false);
  else
    if (elem.attachEvent)
      elem.attachEvent('on' + eventType, fn);
    else {
      var o = e['on' + eventType];
      elem['on' + eventType] = typeof o == 'function' ? function (v) { o(v); fn(v); } : fn;
    }
}

function detachEvent2(elem, eventType, fn, cap) {
  if (!(elem = getElem(elem)))
    return;
  eventType = eventType.toLowerCase();
  if (elem.removeEventListener)
    elem.removeEventListener(eventType, fn, cap || false);
  else
    if (elem.detachEvent)
      elem.detachEvent('on' + eventType, fn);
    else
      elem['on' + eventType] = null;
}

function preventDefault(e) {
  if (e && e.preventDefault)
    e.preventDefault();
  else
    if (window.event)
      window.event.returnValue = false;
}


function getElement(elem) {
  if (document.all)
    return document.all[elem];
  if (document.getElementById)
    return document.getElementById(elem);
  if (document.layers)
    return document.layers[elem];
  return null;
}

function getElem(elem) {
  switch (typeof(elem)) {
    case 'string':
      return getElement(elem);
    case 'object':
      return elem;
  }
  return false;
}

//Devuelve el/los argumentos como elemento(s)
function $() {
  var elements = new Array();
  var al = arguments.length;
  for (var i = 0; i < al; i++) {
    var element = arguments[i];

    if (typeof element == 'string')
      element = getElement(element);

    if (al == 1)
      return element;

    elements.push(element);
  }

  return elements;
}

function setInnerText(obj, text) {
  try {
    if (typeof(obj.innerText) == 'string') //(isIE || isOpera)
      obj.innerText = text;
    else {
      if (obj.nodeType == 3)
        obj.nodeValue = text;
      else {
        if (typeof(obj.textContent) == 'string')
          obj.textContent = text;
        else
          if (obj.childNodes.length) {
            var nobj = document.createElement(obj.tagName);
            if (nobj.nodeType == 3)
              nobj.nodeValue = text;
            else
              nobj.textContent = text;
            obj.parentNode.replaceChild(nobj, obj);
          }
      }
    }
  } catch(e){}
}

function setInnerHTML(e, value) {
  try {
    e = getElem(e);
    if (typeof(e.innerHTML) == 'string') //(isIE || isOpera)
      e.innerHTML = value;
    else
      if (isW3C)
        e.childNodes[0].nodeValue = value;
  } catch (e) {}
}

function getInnerHTML(e) {
  try {
    e = getElem(e);
    if (typeof(e.innerHTML) == 'string') //(isIE || isOpera)
      return e.innerHTML;
    return isW3C ? e.childNodes[0].nodeValue : '';
  } catch (e) {}
}

function getText(obj) {
  var st = '';
  var j, l;
  l = obj.childNodes.length;
  for(j = 0; j < l; j++) {
    node = obj.childNodes[j];
    st += node.nodeType == 3 ? node.nodeValue : getText(node);
  }

  return st;
}

function getInnerText(obj) {
  if (isOpera)
    return getText(obj);

  if (typeof(obj.innerText) == 'string') //(isIE)
    return obj.innerText;

  return getText(obj);
}

Point = function(ax, ay) {
  this.x = ax;
  this.y = ay;
  this.toString = function() {
    return this.x + ', ' + this.y;
  }
}


each = function(fn) { //, str|obj, str|obj, ...
  if (typeof(fn) != 'function' || arguments.length < 2)
    return;

  var e, i, al = arguments.length;
  for (i = 1; i < al; i++)
    if (e = $(arguments[i]))
      fn(e);
}

function hideElem(e) { if (e = $(e)) if (e.style) e.style.display = 'none'; else e.display = 'none'; }
function showElem(e) { if (e = $(e)) if (e.style) e.style.display = 'block'; else e.display = 'block'; }
function showElemInline(e) { if (e = $(e)) if (e.style) e.style.display = 'inline'; else e.display = 'inline'; }
function visibleElem(e) { if (e = $(e)) if (e.style) e.style.visibility = 'visible'; else e.visibility = 'visible'; }
function invisibleElem(e) { if (e = $(e)) if (e.style) e.style.visibility = 'hidden'; else e.visibility = 'hidden'; }
function displayElem(e, d) { if (d) showElem(e); else hideElem(e); }

function setDisabled(p) { p = $(p); p.disabled = !(p.enabled = false); }
function setEnabled(p) { p = $(p); p.disabled = !(p.enabled = true); }
function setEnableState(p, e) { p = $(p); p.disabled = !(p.enabled = e); }

function setElemSize(elem, width, height) {
  elem = $(elem);
  try {
    if (width !== null) elem.style.width = width + 'px';
    if (height !== null) elem.style.height = height + 'px';
  } catch (e) {
    try {
      if (width !== null) elem.style.width = width;
      if (height !== null) elem.style.height = height;
    } catch (e) {
      try {
        if (width !== null) elem.style.pixelWidth = width;
        if (height !== null) elem.style.pixelHeight = height;
      } catch (e) { }
    }
  }
}

function setElemPos(e, x, y) {
  e = $(e);
  if (isDef(e.style)) {
    if (typeof (e.style.top) == 'string') {
      try {
        if (x !== null) e.style.left = x + 'px';
        if (y !== null) e.style.top = y + 'px';
      } catch (e) {
        if (x !== null) e.style.left = x;
        if (y !== null) e.style.top = y;
      }
    }
    else if (isDef(e.style.pixelTop)) {
      try {
        if (x !== null) e.style.pixelLeft = x;
        if (y !== null) e.style.pixelTop = y;
      } catch (e) { }
    }
  }
}

function getElemPos(e) {
  e = $(e);
  r = {};
  if (typeof (e.offsetLeft) != 'undefined') {
    r.x = e.offsetLeft;
    r.y = e.offsetTop;
  } else {
    if (typeof (e.left) != 'undefined') {
      r.x = e.left;
      r.y = e.top;
    } else {
      if (typeof (e.x) != 'undefined') {
        r.x = e.x;
        r.y = e.y;
      } else
        return { x: 0, y: 0 }
    }
  }
  return r;
}

function getElemSize(e) {
  e = $(e);
  r = { width: 0, height: 0 }
  if (typeof (e.offsetWidth) != 'undefined') {
    r.width = e.offsetWidth;
    r.height = e.offsetHeight;
  } else {
    if (e.style && typeof (e.style.pixelWidth) != 'undefined') {
      r.width = e.style.pixelWidth;
      r.height = e.style.pixelHeight;
    }
  }
  return r;
}

var Position = {
  get: {
    Mouse: function(event) {
      var x, y;

      try {
        if (isIE) {
          x = (window.event ? window.event.clientX : 0) + document.documentElement.scrollLeft + document.body.scrollLeft;
          y = (window.event ? window.event.clientY : 0) + document.documentElement.scrollTop  + document.body.scrollTop;
        } else {
          x = event.clientX + window.scrollX;
          y = event.clientY + window.scrollY;
        }
        return new Point(x,y);
      } catch (e) {
        return false;
      }
    },

    Scroll: function(e, bWin) {
      var res = {left: 0, top: 0};
      if (!isDef(e) || bWin || e == document || e.tagName.toLowerCase() == 'html' || e.tagName.toLowerCase() == 'body') {
        var w = window;
        if (bWin && e)
          w = e;
        if (w.document.body && isDef(w.document.body.scrollLeft)) {
          res.left = w.document.body.scrollLeft;
          res.top  = w.document.body.scrollTop;
        } else
          if (isDef(w.document.documentElement) && isDef(w.document.documentElement.scrollLeft)) {
            res.left = w.document.documentElement.scrollLeft;
            res.top  = w.document.documentElement.scrollTop;
          }
      } else {
        e = getElem(e);
        if (e && isNum(e.scrollLeft)) {
          res.left = e.scrollLeft;
          res.top = e.scrollTop;
        }
      }
      return res;
    },

    Abs: function(element) {
      var result = {x: 0, y: 0}

      if (element = getElem(element)) {
        if (typeof(element.offsetParent) != 'undefined') {
          try {
          while (element) {
            result.x += element.offsetLeft;
            result.y += element.offsetTop;
            if (element = element.offsetParent) {
              var tagName = element.tagName.toLowerCase();
              if (tagName != "table" && tagName != "body" && tagName != "html" && tagName != "div" &&
                  (parent.clientTop || parent.clientLeft)) {
                result.x += element.clientLeft;
                result.y += element.clientTop;
              }
            }
          }
          }catch (e){}
        } else
          if (element.left || element.top) {
            result.x = element.left;
            result.y = element.top;
          } else
            if (element.x || element.y) {
              result.x = element.x;
              result.y = element.y;
            }
      }

      return result;
    },

    All: function(element) {
      var result = Position.get.Abs(element);

      if (typeof(element.offsetWidth) != 'undefined') {
        result.width = element.offsetWidth;
        result.height = element.offsetHeight;
      } else
        if (element.style && typeof(element.style.pixelWidth) != 'undefined') {
          result.width = element.style.pixelWidth;
          result.height = element.style.pixelHeight;
        } else
          result.width = result.height = 0;

      return result;
    }
  },

  set: {
    Dims: function(element, width, height) {
      if (element = getElem(element)) {
        if (width != null && element && element.style)
          element.style.width = width;// + "px";
        if (height != null && element && element.style)
          element.style.height = height;// + "px";
      }
    },

    Pos: function(element, x, y) {
      if (element = getElem(element)) {
        if (x != null && element && element.style)
          element.style.left = x;
        if (y != null && element && element.style)
          element.style.top = y;
      }
    }
  }
}


var $A = Array.from = function(iterable) {
  var results = [];

  if (iterable) {
    if (iterable.toArray)
      results = iterable.toArray();
    else
      for (var i = 0; i < iterable.length; i++)
        results.push(iterable[i]);
  }

  return results;
}

Function.prototype.bind = function() {
  var __method = this;
  var args = $A(arguments);
  var object = args.shift();

  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}

/**************************************************************************/
Object.extend = function(destination, source) {
  for (property in source) {
    destination[property] = source[property];
  }
  return destination;
}

Object.prototype.clone = function() {
  var res = {};
  for(var i in this)
    if (this.hasOwnProperty(i))
      res[i] = this[i];
  return res;
}

Object.prototype.hasOwnProperty = function(strProperty) {
  try {
    var objPrototype = this.constructor.prototype;
    while (objPrototype) {
      if (objPrototype[strProperty] == this[strProperty])
        return false;
      objPrototype = objPrototype.prototype;
    }
  } catch (objException) {}
  return true;
}


Object.extend(Function.prototype, {
  empty: function(){}
})


Object.extend(Array.prototype, {
  addItem : function(A) {
    var i = this.length;
    this[i] = A;
    return i;
  },

  indexOf : function(A) {
    for(var i = 0; i < this.length; i++)
      if (this[i] == A)
        return i;
    return -1;
  },

  merge : function(arr) {
    if (arr)
      for(i in arr)
        this.addItem(arr[i]);
  },

  each : function(f) {
    var i = 0, l = this.length;
    while (i < l)
      f(this[i++]);
  },

  eachId : function(f) {
    var i = 0, l = this.length;
    while (i < l)
      f($(this[i++]));
  },

  kill : function(index) { //Solo para claves numéricas 0..n
    if (index >= 0 && index < this.length) {
      for(var i = index + 1; i < this.length; i++)
        this[i - 1] = this[i];
      this.pop();
    }
  }
})

Object.extend(String.prototype, {
  noQuotes : function() {
    return this.replace(/'/ig, '\\\'');
  },

  ltrim: function() {
    return (this.replace(/^\s+/,""));
  },

  rtrim: function () {
    return (this.replace(/\s+$/,""));
  },

  trim: function () {
    return (this.replace(/\s+$/, "").replace(/^\s+/, ""));
  },

  ucFirst: function() {
    return this.substr(0,1).toUpperCase() + this.substr(1, this.length);
  },

  nl2br: function() {
    return this.replace(/\n/g,'<br/>');
  },

  //removes n spaces in string to 1 (one) space
  superTrim: function() {
    return(this.replace(/\s+/g, " ").replace(/\s+$/, "").replace(/^\s+/, "")); //"
  },

  // removes all spaces from string
  removeWhiteSpaces: function() {
    return (this.replace(/\s+/g, ""));
  },

  repeat: function(number) {
    return new Array(number + 1).join(this);
  },

  // fills string with given char and count
  fillChar: function(fill_char, fill_count, fill_position) {
    var fill_position = (fill_position) ? fill_position : 'left';
    var str_len       = this.length;
    var tmp_str       = this;

    if (str_len < fill_count) {
      while (str_len < fill_count) {
        tmp_str = ('left' == fill_position)
                        ? (fill_char + tmp_str)
                        : (tmp_str   + fill_char);

        ++str_len;
      }
    }

    return tmp_str;
  },

  addSlashes: function() {
    return this.valueOf().pString.replace(/\\/g,"\\\\").replace(/\'/g,"\\'").replace(/\"/g,"\\\"");
  },

  stripSlashes: function() {
    return this.valueOf().replace(/(\\)([\\\'\"])/g, "$2");
  },

  stripTags: function(allowTags, eraseAttr) { //allowTags es opcional. Separar con / las etiquetas permitidas. Los scripts siempre se eliminan.
    var s = this.stripScripts();
    if (typeof(allowTags) == 'string' && allowTags.length) {
      if (allowTags.endsWith('/'))
        allowTags += '/';

      allowTags = allowTags.replace(/([^\/]+)\//gi, '|$1[\\s>]');
      allowTags = allowTags.substring(1);

      eval("s = s.replace(/<(\\/?(" + allowTags + "))/gi, ':««^»»:$1');");
      s = s.replace(/<\/?[^>]+>/gi, '').replace(/:««^»»:/gi, '<');

      if (isDef(eraseAttr) && eraseAttr)
        s = s.replace(/<([^\s>]+)[\r\n\s]([^>])+>/gim, '<$1>');
      return s;
    } else
      return s.replace(/<\/?[^>]+>/gi, '');
  },

  stripScripts: function() {
    return this.valueOf().replace(new RegExp(scriptFragment, 'img'), '');
  },

  extractScripts: function() {
    var matchAll = new RegExp(scriptFragment, 'img');
    var matchOne = new RegExp(scriptFragment, 'im');
    return (this.match(matchAll) || []).map(
      function(scriptTag) {
        return (scriptTag.match(matchOne) || ['', ''])[1];
      }
    );
  },

  evalScripts: function() {
    return this.extractScripts().map(eval);
  },

  escapeHTML: function() {
    var div = document.createElement('div');
    var text = document.createTextNode(this);
    div.appendChild(text);
    return div.innerHTML;
  },

  unescapeHTML: function() {
    var div = document.createElement('div');
    div.innerHTML = this.stripTags();
    return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
  },

  toArray: function() {
    return this.split('');
  },

  contains : function(A) {
    return (this.indexOf(A) > -1);
  },

  equals : function() {
    for (var i=0; i < arguments.length; i++)
      if (this == arguments[i])
        return true;
    return false;
  },

  startsWith : function(A) {
    return (this.substr(0, A.length) == A);
  },

  endsWith : function(ending, useRE) {
    var C = this.length;
    var D = ending.length;
    if (D > C)
      return false;
    if (useRE) {
      var E = new RegExp(ending + '$', 'i');
      return E.test(this);
    } else
      return (D == 0 || this.substr(C - D, D) == ending);
  },

  remove : function(from, to) {
    var s = '';
    if (from > 0)
      s = this.substring(0, from);
    if (from + to < this.length)
      s += this.substring(from + to, this.length);
    return s;
  }
});