/**
 * DElement
 * @fileoverview core.js es el fichero que se tiene que incluir en la
 * pagina para poder utilizar las funcionalidades de DElement. Al cargar
 * este fichero se inicializa el entorno necesario para la libreria.
 * @version $Revision: 1.7 $
 */
 
var EventCache = function(){
	var listEvents = [];
	
	return {
		listEvents : listEvents,
	
		add : function(node, sEventName, fHandler, bCapture){
			listEvents.push(arguments);
		},
	
		flush : function(){
			var i, item;
			for(i = listEvents.length - 1; i >= 0; i = i - 1){
				item = listEvents[i];
				
				if(item[0].removeEventListener){
					item[0].removeEventListener(item[1], item[2], item[3]);
				};
				
				/* From this point on we need the event names to be prefixed with 'on" */
				if(item[1].substring(0, 2) != "on"){
					item[1] = "on" + item[1];
				};
				
				if(item[0].detachEvent){
					item[0].detachEvent(item[1], item[2]);
				};
				
				item[0][item[1]] = null;
			};
		}
	};
}();

/**
 * Es un URI que apunta a la carpeta raiz de DElement. Es establecido en la
 * primera llamada a <code>DElement.include</code>
 * @type String
 */
var DElementRootDir;

/**
 * Devuelve el numero de pixeles de scroll horizontal que se ha realizado.
 * @type Number
 */
document.getScrollLeft = function () {
    if (window.pageXOffset) return window.pageXOffset;
    else if (document.documentElement && document.documentElement.scrollLeft) return document.documentElement.scrollLeft;
	else if (document.body) return document.body.scrollLeft;	
};

/**
 * Devuelve el numero de pixeles de scroll vertical que se ha realizado.
 * @type Number
 */
document.getScrollTop = function () {
    if (window.pageYOffset) return window.pageYOffset;
    else if (document.documentElement && document.documentElement.scrollTop) return document.documentElement.scrollTop;
	else if (document.body) return document.body.scrollTop;	
};

/**
 * Devuelve el ancho de la ventana del navegador en pixeles.
 * @type Number
 */
document.getW = function () {
    if (window.innerWidth) return window.innerWidth;
    else if (document.documentElement && document.documentElement.clientWidth) return document.documentElement.clientWidth;
	else if (document.body) return document.body.clientWidth;
};

/**
 * Devuelve el ancho de la ventana del navegador en pixeles.
 * @type Number
 */
document.getH = function () {
    if (window.innerHeight) return window.innerHeight;
    else if (document.documentElement && document.documentElement.clientHeight) return document.documentElement.clientHeight;
	else if (document.body) return document.body.clientHeight;
};

if (!Node) {
/**
 * Internet explorer no implementa la interfaz DOM Node.
 */
var Node = {
		ELEMENT_NODE 				: 	1,
		ATTRIBUTE_NODE 				: 	2,
		TEXT_NODE					:	3,
		CDATA_SECTION_NODE			:	4,
		ENTITY_REFERENCE_NODE		:	5,
		ENTITY_NODE					: 	6,
		PROCESSING_INSTRUCTION_NODE	:	7,
		COMMENT_NODE				:	8,
		DOCUMENT_NODE				:	9,
		DOCUMENT_TYPE_NODE			:	10,
		DOCUMENT_FRAGMENT_NODE		:	11,
		NOTATION_NODE				:	12
	}
};

/**
 * DElement es una envoltura a un elemento DOM. Es el constructor base para
 * todos los elementos visuales.
 * @param arg Puede ser una cadena que representa una etiqueta HTML, un 
 * elemento HTML o un DElement. Si no se especifica este argumento se creara
 * un DElement con la etiqueta HTML <code>div</code>.
 * @type DElement
 */
function DElement (arg) {
	switch (typeof(arg)) {
        case "string" :
			// creamos un elemento con la etiqueta arg.
            this.elm = document.createElement(arg);
            break;
        case "object" :
			if (arg != null) { // null tambien es un objeto.
				if (arg.DElement) { this.elm = arg; return arg.DElement; } //this.elm = arg;//return arg.DElement; // arg es el elemento HTML de un DElement previamente creado
				if (arg.elm && arg.elm.DElement) { this.elm = arg.elm; return arg; }//arg = arg.elm; // arg es un DElement ya creado.
				this.elm = arg // arg es un elemento HTML;
	            break;
			}
        default :
			// por defecto creamos un elemento con la etiqueta "div"
            this.elm = document.createElement("div");
	};
	this.elm.DElement = this;
	this.style = this.elm.style;
	DElement.delements.push(this);
};

/**
 * Mantiene una lista de todos los DElements que se han creado.
 * @type Array
 * @static
 */
DElement.delements = new Array();

/**
 * Mantiene una mapa de todos los DElements que se han buscado por id.
 * @type Object
 * @static 
 */ 
DElement.ids = new Object();

/**
 * Determina si una instancia de DElement es la misma que el que pasamos 
 * como argumento.
 * @type Boolean
 * @returns Un Boolean que indica la igualdad.
 */
DElement.prototype.equals = function (elm) {
	if (elm && elm.elm && this.elm == elm.elm) return true;
	else if (elm && this.elm == elm) return true;
	return false;
};

/**
 * Encuentra los elementos con el attribute id especificado como parametro.
 * @returns Array
 * @static
 */
DElement.getElementById = function (id) {
	if (!DElement.ids[id]) {
		DElement.ids[id] = new DElement(document.getElementById(id));
	};
	return DElement.ids[id];
};

/**
 * Encuentra los elementos cuyo etiqueta es igual al especificado como 
 * parametro.
 * @param {String} tag La etiqueta que deben tener los elementos.
 * @returns Array
 * @static
 */
DElement.getElementsByTagName = function (tag) {
	var elms = document.getElementsByTagName(tag);
	var delms = new Array();
	for (var i = 0; i < elms.length; i++) { 
		delms.push(new DElement(elms[i]));
	};
	return delms; 
};

/**
 * Encuentra los elementos hijos cuyo etiqueta es igual al especificado como 
 * parametro.
 * @param {String} tag La etiqueta que deben tener los elementos.
 * @returns Array
 */
DElement.prototype.getElementsByTagName = function (tag) {
    var elms = this.elm.getElementsByTagName(tag);
    var delms = new Array();
    for (var i = 0; i < elms.length; i++) {
        if (elms[i].nodeType == Node.ELEMENT_NODE) delms.push(new DElement(elms[i]));
    }
    return delms;
};

/**
 * Determina si el elemento tiene el elemento especificado entre sus 
 * elementos hijos.
 * @param {DElement} elm El elemento a buscar entro los nodos descendientes.
 * @returns Boolean
 */
DElement.prototype.hasDescendant = function (elm) {
	return elm.hasParent(this);
};

/**
 * Determina si el elemento es un descendiente del elemento especificado.
 * @param elm {DElement} el elemento a buscar entro los nodos ascendientes.
 * @returns Boolean
 */
DElement.prototype.hasParent = function (elm) {
	if (elm.elm) elm = elm.elm;
	var node = this.elm;
	while (node.parentNode) {
		if (node == elm) return true;
		else node = node.parentNode;
	}
	return false;
};

/**
 * Devuelve una lista con los elementos que son hijos directos del elemento.
 * @returns Array
 */
DElement.prototype.getChildNodes = function () {
    var elms = this.elm.childNodes;
    var delms = [];
    for (var i = 0; i < elms.length; i++) {
        if (elms[i].nodeType == Node.ELEMENT_NODE) delms.push(new DElement(elms[i]));
    }
    return delms;
};

/*
 *	STRUCTURAL CHANGES
 */
/**
 * Anyade un elemento como hijo al elemento.
 * @param {DElement} elm El elemento a anyadir como nodo hijo.
 */
DElement.prototype.appendChild = function (elm) {
    if (elm.constructor == DElement) elm = elm.elm;
    this.elm.appendChild(elm);	
};

/**
 * Elimina el elemento especificado de los hijos del elemento.
 * @param {DElement} elm El elemento a eliminar de los nodos hijo.
 */
DElement.prototype.removeChild = function (elm) {
    if (elm.constructor == DElement) elm = elm.elm;
    this.elm.removeChild(elm);
};

/**
 * Anyade un elemento como hijo al elemento antes del elemento de referencia.
 * @elm {DElement} El elemento a anyadir como nodo hijo.
 * @ref {DElement} El elemento donde hay que insertar el elemento.
 */ 
DElement.prototype.insertBefore = function (elm, ref) {
    if (elm.constructor == DElement) elm = elm.elm;
    if (ref.constructor == DElement) ref = ref.elm;
    this.elm.insertBefore(elm,ref);
};

/**
 * Establece un elemento como el hijo del elemento.
 * @param {DElement} par El elemento que sera el nodo padre del elemento.
 */
DElement.prototype.setParent = function (par) {
    var elm = (par.constructor == DElement)?this:this.elm;
    par.appendChild(elm);
};

/**
 * Devuelve el elemento padre del elemento.
 * @type DElement
 */
DElement.prototype.getParent = function () {
    var elm = this.elm;
	if (elm.parentNode != null) return new DElement(elm.parentNode);
};

/**
 * Devuelve el elemento padre del elemento si tiene el attributo className
 * establecido al especificado como parametro.
 * @type DElement
 */
DElement.prototype.getParentByClass = function (cn) {
	var elm = this.elm;
	while (elm != document.body) {
		if (elm.className.indexOf(cn) != -1 ) return new DElement(elm);
		elm = elm.parentNode;
	}
};
/*
 *	VISUAL STYLE CHANGES
 */
/**
 * Devuelve los clases CSS asociados al elemento como una cadena que 
 * contiene los clases separados por un espacio.
 * @type String
 */
DElement.prototype.getClass = function () {
	return this.elm.className;
};
/**
 * Establece la clase CSS del elemento.
 * @param {String} La clase CSS que aplicar al elemento.
 */ 
DElement.prototype.setClass = function (cn) {
	this.elm.className = cn;
};

/**
 * Indica si el elemento tiene entre los clases CSS asociados a ello la 
 * clase especificado como parametro.
 * @type Boolean
 */
DElement.prototype.hasClass = function (cn) {
	var c = this.getClass();
	var cs = c.split(" ");
	if (cs.indexOf(cn) != -1) {
		return true;
	}
	return false;
};

/**
 * Anyade una clase CSS a los asociados con el elemento.
 * @param {String} cn La clase CSS a anyadir a los que se aplican al 
 * elemento.
 */
DElement.prototype.addClass = function (cn) {
	var c = this.getClass();
	var cs = c.split(" ");
	if (cs.indexOf(cn) == -1) {
		cs.push(cn);
		this.setClass(cs.join(" "));
	}
};

/**
 * Elimina una clase CSS de los asociados con el elemento.
 * @param {String} cn El nombre de la clase a eliminar de los que se aplican
 * al elemento.
 */
DElement.prototype.removeClass = function (cn) {
	var c = this.getClass();
	var cs = c.split(" ");
	var i = cs.indexOf(cn);
	if (i > -1) {
		cs.splice(i,1);
		this.setClass(cs.join(" "));
	}
};

/*
 *	ATTRIBUTES
 */
/**
 * Devuelve el valor del atributo especificado como parametro.
 * @param {String} a El nombre del attributo.
 * @type {Object}
 */
DElement.prototype.getAttribute = function (a) {
	return this.elm[a];
};

/**
 * Establece el valor del atributo especificado al valor especificado.
 * @param {String} El nombre del attributo.
 * @param {Object} El valor del attributo.
 */
DElement.prototype.setAttribute = function (a,v) {
	this.elm[a] = v;
};

/**
 * Elmina el attributo especificado del elemento.
 * @param {String} a El nombre del atributo a eliminar.
 */
DElement.prototype.removeAttribute = function (a) {
	this.elm[a] = null;
	this.elm.removeAttribute(a);
};

/*
 *	EVENTS
 */
/**
 * Anyade un manejador de evento al elemento.
 * @param {String} t El tipo de evento.
 * @param {Function} f La funcion a ejecutar cuando se dispara el evento.
 */
DElement.prototype.addEventListener = function (t, f) {
    var elm = this.elm;
	if (elm.addEventListener) elm.addEventListener(t, f, true);
	if (elm.attachEvent) {
        this.removeEventListener(t, f);
        elm.attachEvent("on" + t, f);
	}
	EventCache.add(elm, t, f, true);
};

/**
 * Elimina un manejador de evento del elemento.
 * @param {String} t El tipo de evento.
 * @param {Function} f La funcion a ejecutar cuando se dispara el evento.
 */
DElement.prototype.removeEventListener = function (t, f) {
    var elm = this.elm;
	if (elm.removeEventListener) elm.removeEventListener(t, f, true);
	if (elm.detachEvent) {
		elm.detachEvent("on" + t, f);
	}
};

/**
 * Es un "wrapper" del evento nativo de navegador. Proporciona informacion
 * sobre un evento ocurrido en la pagina.
 * @param {HTMLEvent} e El evento original.
 */
function DEvent (e) {
	var e = window.event || e;
	this.e = e;
    this.type = e.type;
	var target = e.target || e.srcElement;
    this.target = new DElement(target);
	var relatedTarget = e.relatedTarget?e.relatedTarget:((e.type == "mouseover")?e.fromElement : e.toElement);

	if (relatedTarget != null) this.relatedTarget = new DElement(relatedTarget);
	this.clientX = e.clientX;
	this.clientY = e.clientY;
	this.offsetX = e.offsetX || e.layerX;
	this.offsetY = e.offsetY || e.layerY;
	this.screenX = e.screenX || 0;
	this.screenY = e.screenY || 0;
	
	this.x = document.getScrollLeft() + e.clientX;
	this.y = document.getScrollTop() + e.clientY;
	
	if (typeof(this.offsetX) == "undefined") this.offsetX = 0;
	if (typeof(this.offsetY) == "undefined") this.offsetY = 0;
	
	this.keyCode = e.keyCode || e.charCode;
	this.altKey = e.altKey;
	this.ctrlKey = e.ctrlKey;
	this.metaKey = e.metaKey;
	this.shiftKey = e.shiftKey;
};

/**
 * Previene que el evento se propague hacia elementos padres del elemento
 * que capturo el evento.
 */
DEvent.prototype.stopPropagation = function () {
	if (this.e.stopPropagation) this.e.stopPropagation();
	else this.e.cancelBubble = true;
};


/**
 * EventBroadcaster anyade metodos y propiedades a cualquier objeto javascript
 * que permiten que emita mensajes. Es la manera preferida del propagar 
 * informacion sobre eventos. Anyade los siguientes campos al objeto:
 * <ul>
 *   <li>_listeners</li>
 *   <li>broadcast</li>
 *   <li>addListener</li>
 *   <li>removeListener</li>
 * </ul>
 */

var EventBroadcaster = {};

/**
 * Inicializa al objeto especificado.
 * @param {Object} obj El objeto a inicializar.
 */
EventBroadcaster.initialize = function(obj) {
	obj._listeners = [];
	obj.broadcast = this._broadcast;
	obj.addListener = this._addListener;
	obj.removeListener = this._removeListener;
	
	if (obj.constructor == DElement) {
		obj.addEventListener("mousedown", function (e) {obj.broadcast("mousedown",new DEvent(e))});
		obj.addEventListener("mouseup", function (e) {obj.broadcast("mouseup",new DEvent(e))});
		obj.addEventListener("click", function (e) {obj.broadcast("click", new DEvent(e))});
		
		obj.addEventListener("mouseover", function (e) {obj.broadcast("mouseover", new DEvent(e))});
		//obj.addEventListener("mousemove", function (e) {obj.broadcast("mousemove", new DEvent(e))});
		obj.addEventListener("mouseout", function (e) {obj.broadcast("mouseout",new DEvent(e))});
	}
};

EventBroadcaster._broadcast = function () {
	var args = [];
	for(var i = 0; i < arguments.length; i++) { args[i] = arguments[i]; }
	var eventName = args.shift();
	var list = this._listeners;
	var max = list.length;
	for (var i = 0; i<max; ++i) {
		if (list[i][eventName]) list[i][eventName].apply(list[i], args);
	}
};

EventBroadcaster._addListener = function(obj) {
	this.removeListener(obj);
	this._listeners.push(obj);
	return (true);
};

EventBroadcaster._removeListener = function(obj) {
	var list = this._listeners;
	var i = list.length;
	while (i--) {
		if (list[i] == obj) {
			list.splice(i, 1);
			return (true);
		}
	}
	return (false);
};

/**
 * Devuelve el HTML del elemento.
 * @type String
 */
DElement.prototype.getHTML = function () { return this.elm.innerHTML; };

/**
 * Establece el HTML del elemento.
 * @param {String} s EL HTML interno del elemento.
 */
DElement.prototype.setHTML = function (s) { this.elm.innerHTML = s; };

/**
 * Devuelve la posicion calculado del elemento relativo al lado izquierdo del 
 * primer elemento padre posicionado.
 * @type Number
 */
DElement.prototype.getX = function () { return this.elm.offsetLeft; };

/**
 * Establece la posicion del elemento relativo al lado izquierdo del 
 * primer elemento padre posicionado.
 * @param {Number} i El numero de pixeles de distancia del lado izquierdo.
 */
DElement.prototype.setX = function (i) { this.moveTo(i,null); };

/**
 * Devuelve la posicion calculado del elemento relativo al lado superior del 
 * primer elemento padre posicionado.
 * @type Number
 */
DElement.prototype.getY = function () { return this.elm.offsetTop; };

/**
 * Establece la posicion del elemento relativo al lado izquierdo del 
 * primer elemento padre posicionado.
 * @param {Number} i El numero de pixeles de distancia del lado superior.
 */
DElement.prototype.setY = function (i) { this.moveTo(null,i); };


/**
 * Devuelve la posicion del elemento relativo al lado superior del 
 * primer elemento padre posicionado.
 * @type Number
 */
DElement.prototype.getL = function () { 
	var l = parseInt(this.elm.style.left);
	return (l && l != NaN? l : 0);
};

/**
 * Devuelve la posicion del elemento relativo al lado superior del 
 * primer elemento padre posicionado.
 * @type Number
 */
DElement.prototype.getT = function () { 
	var t = parseInt(this.elm.style.top);
	return (t && t != NaN? t : 0);
};

/**
 * Devuelve la posicion del elemento relativo al lado izquierdo del documento.
 * @type Number
 */
DElement.prototype.getPageX = function () {
	var x = 0, currentNode = this.elm;
	while (currentNode.offsetParent && currentNode != document.body) {
		x += currentNode.offsetLeft;
		x -= currentNode.scrollLeft;
		currentNode = currentNode.offsetParent; 
	} 
	return x; 
};

/**
 * Devuelve la posicion del elemento relativo al lado superior del documento.
 * @type Number
 */
DElement.prototype.getPageY = function () {
	var y = 0, currentNode = this.elm;
	while (currentNode.offsetParent && currentNode != document.body) {
		y += currentNode.offsetTop;
		y -= currentNode.scrollTop;
		currentNode = currentNode.offsetParent; 
	} 
	return y; 
};

/**
 * Devuelve el ancho calculado del elemento.
 * @type Number
 */ 
DElement.prototype.getW = function () { return this.elm.offsetWidth; };
/**
 * Establece el ancho del elemento.
 * @param {Number} i El ancho del elemento en pixeles.
 */
DElement.prototype.setW = function (i) { this.setSize(i,null); };
/**
 * Devuelve la altura calculado del elemento.
 * @type Number
 */ 
DElement.prototype.getH = function () { return this.elm.offsetHeight; };
/**
 * Establece la altura del documento.
 * @param {Number} i la nueva altura del elemento.
 */
DElement.prototype.setH = function (i) { this.setSize(null,i); };

/**
 * Devuelve el indice Z del elemento.
 * @type Number
 */
DElement.prototype.getZ = function () { return this.style.zIndex; };
/**
 * Establece el indice Z del elemento.
 * @param {Number} i El nuevo indice z del elemento.
 */
DElement.prototype.setZ = function (i) { this.style.zIndex = i; };

/**
 * Mueve el elemento a las coordenadas especificado relativo al primer 
 * elemento padre posicionado.
 * @param {Number} x La distancia horizontal.
 * @param {Number} y La distancia vertical.
 */
DElement.prototype.moveTo = function (x,y) { 
	if (x != null) this.style.left = x + "px";
	if (y != null) this.style.top = y + "px";
};

/**
 * Mueve el elemento por las cantidades especificadas..
 * @param {Number} x La distancia horizontal.
 * @param {Number} y La distancia vertical.
 */
DElement.prototype.moveBy = function (x,y) { 
	var newX = this.getX() + x;
	var newY = this.getY() + y;
	this.moveTo(newX, newY);
};

/**
 * Establece el tamanyo del elemento a los cantidades especificadas.
 * @param {Number} w El ancho del elemento.
 * @param {Number} h La altura del elemento.
 */
DElement.prototype.setSize = function (w,h) { 
	if (w && w >= 0) this.style.width = w + "px";
	if (h && h >= 0) this.style.height = h + "px"; 
};
/**
 * Cambia el tamanyo del elemetno por las cantidades especificadas.
 * @param {Number} w La cantidad que se debe modificar el ancho del elemento.
 * @param {Number} h La cantidad que se debe modificar la altura del elemento.
 */
DElement.prototype.setSizeBy = function (w,h) { this.setSize(this.getW() + w, this.getH() + h); };

/**
 * Oculta al elemento.
 */
DElement.prototype.show = function () { this.style.visibility = "inherit"; };

/**
 * Muestra el elemento.
 */
DElement.prototype.hide = function () { this.style.visibility = "hidden"; };

/**
 * Muestra todos los elementos que tienen una etiqueta en concreto.
 * @param elems {Array} Una lista de etiquetas.
 * @static
 */
DElement.showElements = function (elms) {
	for (var i = 0; i < elms.length; i++) {
		var arr = DElement.getElementsByTagName(elms[i]);
		for (var j = 0; j < arr.length; j++) arr[j].show();
	}
};

/**
 * Oculta todos los elementos que tienen una etiqueta en concreto.
 * @param elems {Array} Una lista de etiquetas.
 * @static
 */ 
DElement.hideElements = function (elms) {
	for (var i = 0; i < elms.length; i++) {
		var arr = DElement.getElementsByTagName(elms[i]);
		for (var j = 0; j < arr.length; j++) arr[j].hide();
	}
};

/*
 *	PACKAGE LOADING
 */
/**
 * El registro de paquetes.
 * @type Object
 * @static
 */

DElement.packages = {
	bcf	 : {
		datepicker	:	{	requires : ["gui.datepicker"] }
	},
	data : {
		dataset		:	{}
	},
	ext	: {
		drag		:	{	requires : ["ext.opacity"] },
		dropdown	:	{	requires : ["ext.focus"] },
		focus		:	{},
		grow		:	{},
		opacity		:	{},
		slide		:	{}
	},
	gui : {
		calendar 	: 	{ 	requires : ["gui.table","lang.date"],
							css : "styles/gui/calendar.css"	},
		datatable	:	{	requires : ["data.dataset","gui.table"] },
		datepicker	:	{	requires : ["ext.dropdown", "gui.calendar"] },
		list		:	{	css : "styles/gui/list.css" },
		menu		:	{	requires : ["util.command"],
							css : "styles/gui/menu.css" },
		monthcalendar : {	requires : ["gui.table", "lang.date"],
							css : "styles/gui/monthcalendar.css" },
		monthpicker :	{	requires : ["ext.dropdown","gui.monthcalendar"] },
		orderablelist : {	requires : ["ext.drag", "gui.list"] },
		pageddatatable :{	requires : ["data.dataset","gui.table"]},
		tabbedpanel :	{	css : "styles/gui/tabbedpanel.css" },
		table 		: 	{	},
		tree		:	{	requires : ["util.command"],
							css : "styles/gui/tree.css"	},
		ulmenu		:	{	requires : ["gui.menu"] },
		ultree		:	{	requires : ["gui.tree"] },
		xmlmenu		:	{	requires : ["gui.menu","xml.xmlextras"] },
		xmltree		:	{	requires : ["gui.tree","util.namevalueparser","xml.xmlextras"] }
	},
	lang : {
		array 		: 	{},
		date 		:	{	requires : ["lang.string"] },
		error 		: 	{},
		func 		: 	{},
		string 		: 	{}
	},
	request : {
		cookie		:	{	requires : ["util.namevalueparser"] },
		querystring :	{	requires : ["util.namevalueparser"] }
	},
	util : {
		command			:	{},
		log 			:	{	requires : ["lang.date", "lang.string"]	},
		namevalueparser : 	{},
		statesaver 		:	{	requires : ["request.cookie"] }
	},
	xml	: {
		wddx		:	{	requires : ["data.dataset","lang.date","xml.xmlextras"] },
		xmlextras	:	{}
	}
};

DElement.packages.cepsa = {
	intranet : {
		intranettree	: 	{	requires : ["gui.xmltree"], css : "styles/cepsa/intranet/intranettree.css" }
	},
	web : {
		homexmlmenu		:	{	requires : ["gui.xmlmenu"], css : "styles/cepsa/web/homexmlmenu.css"	},
		interiorxmlmenu	:	{	requires : ["gui.xmlmenu"], css : "styles/cepsa/web/interiorxmlmenu.css"	}
	}
}

/**
 * Indica si se debe cargar las hojas de estilo por defecto.
 * @type Boolean
 * @static
 */
DElement.loadCss = true;

/**
 * Una lista de los paquetes que se han cargado.
 * @type Array
 * @static
 */
DElement.loaded = [];

/**
 * Incluye un paquete. Se puede especificar tambien las hoja de estilo que 
 * se debe cargar en lugar de la hoja de estilo por defecto.
 * @param {String} pkg El identificador del paquete a cargar.
 * @static
 */
DElement.include = function (pkg) {
	for (var i = 0; i < DElement.loaded.length; i++) {
		if (DElement.loaded[i] == pkg) { return; };
	}

	// try to automagically set the root dir
	if (!DElementRootDir) {
		var scripts = document.getElementsByTagName("script");
		for (var i = 0; i < scripts.length; i++) {
			var src = scripts[i].getAttribute("src");
			if (src) {
				var index = src.indexOf("js/core.js");
				if (index > -1) { 
					DElementRootDir = src.substring(0,index);
					break;
				}
			}
		}
	}
	
	var parts = pkg.split(".");
	var curPackage = DElement.packages;
	var js = "";
	var css = "";
	for (var i = 0; i < parts.length; i++) {
		var pkgPart = parts[i]
		curPackage = curPackage[pkgPart];
	}
	if (curPackage.requires) {
		for (var j = 0; j < curPackage.requires.length; j++) {
			DElement.include(curPackage.requires[j]);
		}
	}
	if (curPackage.css) css = curPackage.css;
	
	js = DElementRootDir + "js/" + pkg.replace(new RegExp("\\.","g"), "/") + ".js";
	document.write("<script type=\"text/javascript\" src=\"" + js + "\">\<\/\script>");
	if (css != "" && DElement.loadCss == true) document.write("<link rel=\"stylesheet\" type=\"text/css\" href=\"" + DElementRootDir + css + "\" />");
	DElement.loaded[DElement.loaded.length] = pkg;
};

/**
 * Contiene las funciones que se ejecutar cuando se carga la pagina.
 * @static
 */
DElement.onLoadFunctions = [];
/**
 * Contiene las funciones que se ejecutar cuando se descarga la pagina.
 * @static
 */
DElement.onUnloadFunctions = [];

/**
 * Anyade una funcion a la lista de funciones que se deben ejecutar al cargarse
 * la pagina.
 * @static
 */
DElement.addOnLoad = function (f) {
	DElement.onLoadFunctions.push(f);
};

/**
 * Anyade una funcion a la lista de funciones que se deben ejecutar al descargarse
 * la pagina.
 * @static
 */
DElement.addOnUnload = function (f) {
	DElement.onUnloadFunctions.push(f);
};

/**
 * Se ejecuta cuando se carga la pagina.
 * @static
 */ 
DElement.load = function () {
	if (document.readyState && document.readyState != "complete") return;
	for (var i = 0; i < DElement.onLoadFunctions.length; i++) { 
		DElement.onLoadFunctions[i]();
	}
};

/**
 * Se ejecuta cuando la pagina es descargada del navegador.
 * @static
 */
DElement.unload = function () {
	for (var i = 0; i < DElement.onUnloadFunctions.length; i++) { DElement.onUnloadFunctions[i](); DElement.onUnloadFunctions[i] = null; }
	EventCache.flush();
	for (var i = (DElement.delements.length-1); i > 0; i--) {
		for (var j in DElement.delements[i]) { DElement.delements[i][j] = null; }
		DElement.delements[i] = null;
	}
	if (typeof document.oldOnUnload == "function") document.oldOnUnload();
};


if(window.addEventListener) window.addEventListener( "load", function() {DElement.load()}, false);
else if(typeof document.onreadystatechange != "undefined") document.onreadystatechange = function () { DElement.load() };
else { document.onload = function () { DElement.load() } }

if (window.addEventListener) window.addEventListener( "unload", function() {DElement.unload()}, false);
else {
	if (typeof onunload == "function") document.oldOnUnload = document.onunload;
	onunload = function() { DElement.unload() }
};

DElement.include("lang.array");
DElement.include("lang.error");
DElement.include("lang.func");
