/**
 * EventMgr Class, by Martin Szyszlican.
 * Funcionalidades:
 * 
 *     * Evita perdidas (leaks) de memoria en Firefox (y tal vez algun otro navegador)
 *     * Permite ejecutar funciones una vez que el DOM está cargado sin esperar a cargar las imágenes (via DOMContentLoaded y defer para ie)
 *     * Es totalmente cross-browser: Engloba el manejo de eventos para no tener que preocuparse por las inconsistencias entre navegadores y versiones de javascript.
 *     * Si el usuario no tiene javascript, obviamente, nada se ejecuta. Si una un navegador con escaso soporte para eventos (solo eventos on* sin addListener) se ejecutará el último evento agregado al elemento.
 * 
 * Ejemplo de uso:
 * EventMgr.add(window,"load",init);

 * function init() {
 *		alert("Esta funcion se ejecutará antes de que se terminen de cargar las imágenes!");
 * }
 * 
 * Basado en el trabajo de ecmanaut:
 * http://ecmanaut.blogspot.com/2006/05/avoiding-javascript-leakage.html
 * La idea de usar comentarios condicionales y document.write para emular el defer 
 * es de Matthias Miller http://www.outofhanwell.com/blog/index.php?title=the_window_onload_problem_revisited
 * En colaboración con Dean Edwards: http://dean.edwards.name/weblog/2006/06/again
 *
 * Aquí hay otro método similar a esta clase, pero no evita leaks:
 * http://agileweb.org/articles/2006/07/28/onload-final-update
 */
var EventMgr = // avoid leaking event handlers, crossbrowser version
{
  _registry:null,
  initialize:function() {
    if(this._registry == null) {
      this._registry = [];
      EventMgr.add(window, "_unload", this.cleanup);
    }
  },
  add:function(o, t, fn, uc) {
    this.initialize();
    if(typeof o == "string")
      o = d.g(o);
    if(o == null || fn == null)
      return false;
    if(t == "unload") {
      // call later when cleanup is called. don't hook up
      this._registry.push({obj:o, type:t, fn:fn, useCapture:uc});
      return true;
    }
    var realType = t=="_unload"?"unload":t;

	this.realAdd(o,realType,fn,uc);

    this._registry[this._registry.length] = {obj:o, type:t, fn:fn, useCapture:uc};

    return true;
  },
  realAdd:function(o,realType,fn,uc) {
  	if (realType == "load") {
		fn = EventMgr.init;
  		this.realAdd(o,"error",fn,uc);
		this.realAdd(o,"DOMContentLoaded", fn, false);
		/* for Internet Explorer */
		/*@cc_on @*/
		/*@if (@_win32)
		if (document.getElementById) {
			script = document.getElementById("__ie_onload");
			if (script == window.undefined) {
				var proto = "javascript:void(0)";
				if (location.protocol == "https:") proto = "src=//0";
				document.write("<scr"+"ipt id=__ie_onload defer src=" + proto + "><\/scr"+"ipt>");

				var script = document.getElementById("__ie_onload");
				script.onreadystatechange = function() {
					if (this.readyState == "complete") {
						fn();
					}
				};
			}
		}
		/*@end @*/
		/* for Safari */
		if (/KHTML|WebKit/i.test(navigator.userAgent)) { // sniff
		    this._timer = setInterval(function() {
		        if (/loaded|complete/.test(document.readyState)) {
					clearInterval(this._timer);
					delete this._timer;
		            fn(); // call the onload handler
		        }
		    }, 10);
		}
	}
	if (o.addEventListener)
		o.addEventListener(realType,fn,uc);

    else if (o.attachEvent)
		o.attachEvent('on' + realType, fn);

	else {
		o["on"+realType] = fn;
		if (o["on"+realType] != fn) {
			alert("Error adding listener\nObject:"+o+" ID:"+o.id+" Name:"+o.name+" TagName:"+o.tagName+"\nEvent:"+realType);
		}
	}
  },
  init:function () {
	// quit if this function has already been called
	if (arguments.callee.done) return;
	// flag this function so we don't do the same thing twice
	arguments.callee.done = true;
	// execute each function in the stack in the order they were added
	for (var i=0;i < EventMgr._registry.length;i++) {
		if (EventMgr._registry[i].type=="load") {
			p=EventMgr._registry[i].fn();
		}
	}
  },
  remove:function (o,type,fn,uc) {
		if (o.removeEventListener)
			o.removeEventListener(type,fn,uc);
		else if (o.detachEvent)
			o.detachEvent("on" + type,fn);
		else {
			//TODO: Disabled 'cos it throws errors in IE4/Win
//			o["on"+type] = window.undefined;
//			if (o["on"+type]!=window.undefined) return false;
		}
		return true;
	},
  cleanup:function() {
    for(var i = 0; i < EventMgr._registry.length; i++)
      with(EventMgr._registry[i])
        if(type=="unload")
          fn();
        else {
          if(type == "_unload") type = "unload";
          EventMgr.remove(obj,type,fn,useCapture);
        }
    delete EventMgr._registry;
  }
};
