////////////////////////////////////////////////////////////////////////////////
// Some tricks for making it seem like we're in Facebook even when we're not.
// Just be sure to use fbCreateEl and fbGetEl to get elements.

// If you wanted to be a little sneaky, you could do something like:
/*
  document.getElementById = fbGetEl;
  document.createElement = fbCreateEl;
*/

var fbMethods = {};

function copyMethods(el)
{
  for (var fn in fbMethods) {
    el[fn] = fbMethods[fn];
  }
  return el;
}

function fbGetEl(elId)
{
  var el = document.getElementById(elId);
  if (el) {
    return copyMethods(el);
  } else {
    return null;
  }
}

function fbCreateEl(elType)
{
  var el = document.createElement(elType);
  if (el) {
    return copyMethods(el);
  } else {
    return null;
  }
}

function makeSetter(arg) {
  return function(val) {
    this[arg] = val;
    return this;
  };
}

function makeGetter(arg) {
  return function() {
    return this[arg];
  };
}

function capitalize(str)
{
  return str.charAt(0).toUpperCase() + str.substr(1);
}

////
// Takes an array of property names, and makes a getter and a setter
// for each of them.
function makeGettersSetters(properties)
{
  ForEach(properties, function(prop) {
    var capProp = capitalize(prop);
    fbMethods['set' + capProp] = makeSetter(prop);
    fbMethods['get' + capProp] = makeGetter(prop);
  });
}

////
// Takes an array of property names, and makes a getter and a setter
// for each of them.
function makeGetters(properties)
{
  ForEach(properties, function(prop) {
    fbMethods['get' + capitalize(prop)] = makeGetter(prop);
  });
}

makeGettersSetters([
  'accessKey',
  'action',
  'checked',
  'className',
  'cols',
  'colSpan',
  'dir',
  'disabled',
  'firstChild',
  'href',
  'id',
  'lastChild',
  'name',
  'nextSibling',
  'parentNode',
  'previousSibling',
  'readOnly',
  'rows',
  'rowSpan',
  'scrollLeft',
  'scrollTop',
  'selected',
  'selectedIndex',
  'src',
  'tabIndex',
  'target',
  'title',
  'type',
  'value']);

makeGetters([
  'clientHeight',
  'clientWidth',
  'form',
  'offsetHeight',
  'offsetWidth',
  'scrollHeight',
  'scrollWidth',
  'tagName']);


fbMethods.getChildNodes = function()
{
  var ret = this.childNodes;

  return Map(ret, copyMethods);
};

fbMethods.getAbsoluteLeft = function()
{
  var left = 0, e = this;

  while (e){
    left += e.offsetLeft;
    e     = e.offsetParent;
  }
  return left;
};

fbMethods.getAbsoluteTop = function()
{
  var top = 0, e = this;

  while (e){
    top += e.offsetTop;
    e = e.offsetParent;
  }
  return top;
};

function setOneStyle(el, arg, val)
{
  el.style[arg] = val;
  if (arg == 'opacity') {
    var a = parseFloat(val);
    if (!isNaN(a)) {
      a = Math.floor(a * 100);
      try {
	el.style.filter = 'alpha(opacity=' + a + ')';
      } catch (e) { };
    }
  }
}

fbMethods.setStyle = function(arg1, arg2)
{
  if (typeof(arg1) == 'object') {
    for (var v in arg1) {
      setOneStyle(this, v, arg1[v]);
    }
  } else {
    setOneStyle(this, arg1, arg2);
  }
  return this;
};

fbMethods.getStyle = function(st)
{
  return this.style[st];
};

function getClassNames(el) {
  return el.className.split(' ');
}

fbMethods.addClassName = function(className) {
  var classNames = getClassNames(this);
  ArrayAddUnique(classNames, className);
  this.className = classNames.join(' ');
};

fbMethods.removeClassName = function (className) {
  var classNames = getClassNames(this);
  ArrayRemove(classNames, className);
  this.className = classNames.join(' ');
};

fbMethods.hasClassName = function(className) {
  var classNames = getClassNames(this);
  return (ArrayIndexOf(classNames, className) != -1);
};

fbMethods.toggleClassName = function(className) {
  var classNames = getClassNames(this);
  if (!ArrayRemove(classNames, className)) {
    // It wasn't there. Add it.
    classNames.push(className);
  }
  this.className = classNames.join(' ');
};

fbMethods.purgeEventListeners = function(evt)
{
  this['on' + evt] = null;
  return this;
};

fbMethods.setTextValue = function(txt)
{
  this.innerHTML = txt.replace(/</g, '&lt;').replace(/>/g, '&gt;');
  return this;
};
