//////////////////////////
// cookies.js //
//////////////////////////
function getCookie( name ) {
  var start = document.cookie.indexOf( name + "=" );
  var len = start + name.length + 1;
  if ( ( !start ) && ( name != document.cookie.substring( 0, name.length ) ) ) {
    return null;
  }
  if ( start == -1 ) return null;
  var end = document.cookie.indexOf( ";", len );
  if ( end == -1 ) end = document.cookie.length;
  return unescape( document.cookie.substring( len, end ) );
}

function setCookie( name, value, expires, path, domain, secure ) {
  var today = new Date();
  today.setTime( today.getTime() );

  if ( expires ) {
    expires = expires * 1000 * 60 * 60 * 24;
  }

  var expires_date = new Date( today.getTime() + (expires) );
 
  document.cookie = name+"="+escape( value ) +
    ( ( expires ) ? ";expires="+expires_date.toGMTString() : "" ) + //expires.toGMTString()
    ( ( path ) ? ";path=" + path : "" ) +
    ( ( domain ) ? ";domain=" + domain : "" ) +
    ( ( secure ) ? ";secure" : "" ) ;
}

function deleteCookie( name, path, domain ) {
  if ( getCookie( name ) ) document.cookie = name + "=" +
    ( ( path ) ? ";path=" + path : "") +
    ( ( domain ) ? ";domain=" + domain : "" ) +
    ";expires=Thu Jan 01 1970 00:00:01 GMT+0000 (CEST)" ;
}
function getCookie(C){var D=document.cookie.indexOf(C+"=");var A=D+C.length+1;if((!D)&&(C!=document.cookie.substring(0,C.length))){return null}if(D==-1){return null}var B=document.cookie.indexOf(";",A);if(B==-1){B=document.cookie.length}return unescape(document.cookie.substring(A,B))}function setCookie(C,E,D,G,A,H){var B=new Date();B.setTime(B.getTime());if(D){D=D*1000*60*60*24}var F=new Date(B.getTime()+(D));document.cookie=C+"="+escape(E)+((D)?";expires="+F.toGMTString():"")+((G)?";path="+G:"")+((A)?";domain="+A:"")+((H)?";secure":"")}function deleteCookie(B,C,A){if(getCookie(B)){document.cookie=B+"="+((C)?";path="+C:"")+((A)?";domain="+A:"")+";expires=Thu Jan 01 1970 00:00:01 GMT+0000 (CEST)"}}function miListaValores(){this.idDiv_Reducido="mis_favoritos_reducido";this.url_miLista_Individual="/mi-lista-cotizaciones/index_Individual.php";this.url_miLista_Reducida="/lista-quotes/JSON.php";this.miLista_Reducido_Cargada=false;this.idIndividual_Reducido="mini_";this.anadirQuote=false;this.miniListaCargada=false;this.cookies_quotes="cot_visitadas_js";this.cookies_quotes_rastreo="rastreo_automatico";this.maxLista=10;this.maxVisible=4}miListaValores.prototype={LeerLista_Reducido:function(){var I=this.maxVisible;var F=document.getElementById("mis_favoritos_reducido");var H='<div class="cot-visitadas">';H+='<h5 id="Quote_Texto_Mini">ÚLTIMAS COTIZACIONES VISITADAS: </h5>';var D=getCookie(this.cookies_quotes);if(D==null){this.Cookie_Anadir_Cotizacion([555,"DOW-JONES","DOW JONES",1,null]);this.Cookie_Anadir_Cotizacion([11167,"ECO10","ECO10",1,null]);this.Cookie_Anadir_Cotizacion([323,"IGBM","I. GENERAL DE MADRID",1,null]);this.Cookie_Anadir_Cotizacion([117,"IBEX-35","IBEX 35",1,null]);D=getCookie(this.cookies_quotes)}var C=JSON.decode(D);var A=new Hash(C.quotes);H+='<div class="iList indices-home">';H+='<ul id="mis_favoritos_reducido_visitadas" class="iArrow">';var B="";var E=0;A.each(function(K,J){if(E<I){B+=K[0];H+='<li id="mini_'+K[0]+'">';H+="</li>"}if(E<I-1){B+=","}E++});H+="</ul></div></div>";if(!this.miniListaCargada){F.innerHTML=H}var G=(Date.parse(new Date())/1000)-C.lastQuery;if(G>60||!this.miniListaCargada){this.HacerPeticionCotizacion(B);this.miniListaCargada=true}},HacerPeticionCotizacion:function(E,A){if(A){this.anadir_Quote=true}var F=new XMLHttpRequest();var D=this.escribirListaReducido;var C=this;var G=function(){D(F,C)};var B=this.url_miLista_Reducida+"?lista="+E;F.open("get",B,true);F.onreadystatechange=G;F.send(null)},escribirListaReducido:function(K,D){if(K.readyState!=4){return }var L,A,B;L=(K.status!=200&&K.status!=0);var C=JSON.decode();var C=JSON.decode(K.responseText);var G=getCookie("cot_visitadas_js");var E=JSON.decode(G);var J=new Hash(E.quotes);var F=false;C.Quote.each(function(M){var N=J.get(M.id);if(N!=null){N[3]=M.pDif;F=true}if(D.anadir_Quote){F=false;D.Cookie_Anadir_Cotizacion([parseInt(M.id),M.url,M.nom,parseInt(M.clase),M.pDif])}document.getElementById("mini_"+M.url).innerHTML=HacerCotizacionReducida(M.id,M.url,M.nom,M.clase,M.pDif,M.ult)});if(F){var I=Date.parse(new Date())/1000;var H='{ "lastQuery": '+I+', "quotes": '+JSON.encode(J)+" }";setCookie("cot_visitadas_js",H,365,"/",null,null)}},Visitar_Quote:function(D){var C=document.getElementById("mis_favoritos_reducido_visitadas");if(!C){this.LeerLista_Reducido();C=document.getElementById("mis_favoritos_reducido_visitadas")}var A=document.getElementById("mini_"+D);if(A){var F=C.firstChild;if(F!=A){var E=A;C.removeChild(A);C.insertBefore(E,C.firstChild)}}else{var B=document.createElement("li");B.setAttribute("id","mini_"+D);C.insertBefore(B,C.firstChild);C.removeChild(C.lastChild)}this.HacerPeticionCotizacion(D,true);A=document.getElementById("mini_"+D)},Cookie_Anadir_Cotizacion:function(temp_Quote){var num_maximo=this.maxLista;var val_return=false;var escribirCookie=true;var arrayQuotes;var lastQuery;var cookie_quotes_old;var cookie_quotes_str=getCookie(this.cookies_quotes);if(cookie_quotes_str==null){cookie_quotes_old=new Hash();lastQuery=null}else{var cookie_quotes_json=eval("("+cookie_quotes_str+")");lastQuery=cookie_quotes_json.lastQuery;cookie_quotes_old=new Hash(cookie_quotes_json.quotes)}arrayQuotes=cookie_quotes_old.getKeys();if(cookie_quotes_old.get(temp_Quote[0])!=undefined){if(arrayQuotes.indexOf(temp_Quote[0]+"")==0){var tmp=cookie_quotes_old.get(temp_Quote[0]);if(temp_Quote[4]==tmp[3]){escribirCookie=false}else{cookie_quotes_old.erase(temp_Quote[0])}}else{cookie_quotes_old.erase(temp_Quote[0])}}if(escribirCookie){var cookie_quotes_new=new Hash();cookie_quotes_new.set(temp_Quote[0],[temp_Quote[1],temp_Quote[2],temp_Quote[3],temp_Quote[4]]);if(arrayQuotes.length>0){cookie_quotes_new=cookie_quotes_new.combine(cookie_quotes_old)}arrayQuotes=cookie_quotes_new.getKeys();if(arrayQuotes.length>num_maximo){val_return=arrayQuotes.pop();cookie_quotes_new.erase(val_return)}var data='{ "lastQuery": '+lastQuery+', "quotes": '+JSON.encode(cookie_quotes_new)+" }";setCookie(this.cookies_quotes,data,365,"/",null,null)}return(val_return)}};function generarURLCotizacion(D,B){var A;var C;A="/cotizacion/index.php?tipo=";switch(parseInt(D)){case 1:C="indice";tipoPagina="Indice";break;case 2:C="empresa";tipoPagina="Empresa";break;case 3:C="cruce";tipoPagina="Cruce";break;default:C=null}if(C!=null){A+=C+"&nombre="+B+"#_"+tipoPagina}return(A)}function generarEstado(A){var B="";var C="";if(A!=null){A=A.substring(0,A.indexOf("%"));B=A.substring(0,A.indexOf(","))+"."+A.substring(A.indexOf(",")+1);if(B>0){B=1}else{if(B<0){B=-1}else{B=0}}}return(B)}function HacerCotizacionReducida(C,B,H,D,G,E){var A=generarURLCotizacion(D,B);var F=generarEstado(G);G=(G==null)?"":G;var I='<a href="'+A+'" rev="async">';I+='<img height="6" width="10" src="/imag/cotizaciones/ico'+F+'.gif"/>';I+="<span>"+H+"</span>";I+="<span>"+E+"</span>";I+="<span>"+G+"</span>";I+="</a>";return(I)};var WebApp = (function() {
	var L2R = +1;
	var R2L = -1;
	var INV = -1;	// INVERT

	var HEAD = 0;
	var HOME = 1;
	var BACK = 2;
	var LEFT = 3;
	var RIGHT = 4;
	var TITLE = 5;

	var _def, _headView, _head;
	var _webapp, _group, _bdo;

	var _prev		= -1;
	var _historyPos	= -1;	// warning: must order properly var names for reduction script
	var _location	= [];
	var _history	= [];
	var _scroll		= [];
	var _loader		= [];
	var _fading		= [];
	var _header		= [];
	var _ajax		= [];
	var _initialNav	= history.length;
	var _sliding	= 0;
	var _hold		= false;
	var _baseTitle	= "";
	var _baseBack	= "";
	var _lockCnt	= 0;
	var _width		= 0;
	var _lastScroll	= 1;
	var _dialog		= null;
	var _v2			= 0 && !(!document.getElementsByClassName) && Contains("WebKit", navigator.userAgent);
	var _moving		= -1;
	var _fullscreen	= false;
	var _proxy		= "";

	var _handler	= {};
	_handler.load				= [];
	_handler.beginslide			= [];
	_handler.endslide			= [];
	_handler.orientationchange	= [];
	_handler.error				= [];

/* Public */
	__p = {
		SetDefault: function(layer) { _def = layer },
		Proxy: function(url) { _proxy = url; },

		HideBar: function() {
			window.scrollTo(0, 1);
			return false;
		},

		Header: function(show, what) {
			Buttons(show);
			Display(_headView, 0);
			_headView = $(what);
			Display(_headView, !show);
			return false;
		},

		Tab: function(id, active) {
			var o = $(id);
			ShowTab(o, $$("li", o)[active]);
		},

		AddEventListener: function(evt, handler) {
			if (typeof _handler[evt] != "undefined")
				if (_handler[evt].indexOf(handler) == -1)
					_handler[evt].push(handler);
		},

		Toggle: function() {
			if (_history.length > 1) {
				if (_historyPos == _history.length - 1)
					history.back();
				else
					history.forward();
			}
			return false;
		},

		Back: function() {
			if (_hold)
				return (_hold = false);

			if (history.length - _initialNav == _historyPos)
				history.back();
			else
				location = _location[_historyPos - 1] || "#";
			return false;
		},

		Home: function() {
			if (history.length - _initialNav == _historyPos)
				history.go(-_historyPos);
			else
				location = "#";
			return (_hold = false);
		},

		Form: function(frm) {
			var s, a, b, c, o, f;

			a = $(frm);
			b = $(_history[_historyPos]);
			s = (a.style.display != "block");

			f = GetName(a) == "form" ? a : GetParent(a, "form");
			o = f.onsubmit;
			if (!s) {
				f.onsubmit = f.onsubmit(null, true);
			} else {
				a.style.top = parseInt($("__wa_shadow").style.top) - 2 + "px";

				f.onsubmit = function(e, b) {
					if (b) return o;
					if (o) o(e);

					e.preventDefault();
					__p.Submit(this);
				};
			}

			AdjustView();
			Shadow(s);
			Display(a, s);
			SetTitle(s ? $$("legend", a)[0].innerHTML : 
							(_historyPos ? b.title : null) );

			_dialog = (s) ? a : null;
			if (s) { c = a; a = b; b = c }

			DelLayerButtons(a);
			AddLayerButtons(b, s);

			if (s)	__p.Header(s);
			else	Buttons(!s);

			return false;
		},

		Submit: function(frm) {
			var a = arguments[1];	// submiter object to help focus fixer, should not be used by client code!
			var e = arguments[2];

			var f = $(frm);
			if(f && GetName(f) != "form") f = GetParent(f, "form");
			if (f) {
				var _ = function(i, f) {
					var q = "";
					for (var n = 0; n < i.length; n++)
						if (i[n].name && !i[n].disabled && (f ? f(i[n]) : 1))
							q += "&" + i[n].name + "=" + encodeURIComponent(i[n].value);
					return q;
				}

				var q  = _($$("input", f),
					function(i) {
						with(i) return ((Contains(type, ["text", "password", "hidden", "search"]) ||
										(Contains(type, ["radio", "checkbox"]) && checked)))
					});
					q += _($$("select", f));

				e  = e || event;
				a  = !a ? GetLink(e.target) : a;
				if (!a) FocusFixer();
				q += "&" + (a && a.id ? a.id : "__submit") + "=1";
				q  = q.substr(1);

				BasicAsync(f.action || self.location.href, null, q);
				if (_dialog) __p.Form(_dialog);
			}
			return false;
		},

		Postable: function(keys, values) {
			var q = "";
			for (var i = 1; i < values.length && i <= keys.length; i++)
				q += "&" + keys[i - 1] + "=" + encodeURIComponent(values[i]);
			return q.replace(/&=/g, "&").substr(1);
		},

		Request: function(url, prms, cb, async, loader) {
			cb = cb == -1 ? DefaultCallback() : cb;

			var o = new XMLHttpRequest();
			var c = function() { __callback(o, cb, loader) };
			var m = prms ? "post" : "get";

			async = (!async ? false : true);
			if (loader) __p.Loader(loader, true);
			if (_handler.error.length > 0)
				_ajax[_ajax.length] = [o, url, prms];

			url = AddParam(url, "__async", "true");
			url = AddParam(url, "__source", _history[_historyPos]);
			url = SetURL(url);

			o.open(m, url, async);
			if (prms) o.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			o.onreadystatechange = (async) ? c : null;
			o.send(prms);

			if (!async) c();
		},

		Loader: function(obj, show) {
			var o = obj;
			var h = HasClass(o, "__lod");
			if (h == show)
				return h;

			if (show) {
				AddClass(o, "__lod");
				_loader.push(o);
			} else DelClass(o, "__lod");

			ApplyMore(o);
			return h;
		},
		
		Player: function(src) {
			src = src || GetLink(event.target).href;
			if (!IsMobile()) {
				window.open(src);
			} else {
				var o = $("__wa_media");
				if (o) delete _webapp.removeChild(o);

				o = NewItem("iframe");
				o.id = "__wa_media";
				o.src = src;			/* must be before appendChild to prevent Safari weird behavior */

				_webapp.appendChild(o);
			}
			return false;
		},

		FullScreen: function() {
			if (_v2) {
				var fnd = false;
				var mta = $$("meta");
				for (var i = 0; i < mta.length && !fnd; i++)
					fnd = (mta[i].name == "apple-touch-fullscreen");
				if (fnd) mta = mta[i - 1];

				var arg = arguments;
				if (arg.length) {
					if (!fnd) {
						mta = NewItem("meta");
						mta.name = "apple-touch-fullscreen";
						$$("head")[0].appendChild(mta);
					}
					mta.content = arg[0] ? "YES" : "NO";
				}
				if (mta) _fullscreen = (mta.content == "YES");
			}

			return _fullscreen;
		}
	}

	function ApplyMore(o) {
		if (HasClass(o, "iMore")) {
			var a = $$("a", o)[0];
			if (a.title) {
				o = a.innerHTML;
				a.innerHTML = a.title;
				a.title = o;
			}
		}
	}

	function FocusFixer() {
		var i = NewItem("input");
		_group.appendChild(i);
		i.type = "text";
		i.focus();
		Display(i, 0);
		setTimeout(function() { delete _group.removeChild(i) }, 5);
	}

	function Buttons(s) {
		if (!_head)
			return;
		for (var i = 1; i < _header.length; i++)
			Display(_header[i], s);

		Display(_header[BACK], s && !_header[LEFT] && _historyPos);
		Display(_header[HOME], s && !_header[RIGHT] && _historyPos > 1);
	}

	function AddLayerButtons(lay, ignore) {
		if (!_head)
			return;

		var a = $$("a", lay);
		var p = RIGHT;

		for (var i = 0; i < a.length && p >= LEFT; i++) {
			if (_header[p] && !ignore) { i--; p--; continue; }

			if (HasToken(a[i].rel, "action") ||
				HasToken(a[i].rel, "back")) {

				AddClass(a[i], p == RIGHT ? "iRightButton" : "iLeftButton");
				Display(a[i], 1);
				_header[p--] = a[i];
				_head.appendChild(a[i--]);
			}
		}
	}

	function DelLayerButtons(lay) {
		if (!_head)
			return;

		for (var i = LEFT; i <= RIGHT; i++) {
			var a = _header[i];
			if (a && (	HasToken(a.rel, "action") ||
						HasToken(a.rel, "back")) ) {

				Display(a, 0);
				DelClass(a, i == RIGHT ? "iRightButton" : "iLeftButton");
				lay.insertBefore(a, lay.firstChild);
			}
		}
		_header[RIGHT] = $("waRightButton");
		_header[LEFT] = $("waLeftButton");
	}

/* Private */
	function Contains(o, a) { return a.indexOf(o) != -1 }
	function IsAsync(o) { return HasToken(o.rev, "async") || HasToken(o.rev, "async:np"); }

	function $(i) { return typeof i == "string" ? document.getElementById(i) : i; }
	function $$(t, o) { return (o || document).getElementsByTagName(t); }
	function NewItem(t) { return document.createElement(t); }
	function GetLink(o) { return GetName(o) == "a" ? o : GetParent(o, "a") }
	function GetName(o) { return o.localName.toLowerCase() }
	function HasToken(o, t) { return o && Contains(t, o.toLowerCase().split(" ")); }

	function HasClass(o, c) { return Contains(c, GetClass(o)); }
	function GetClass(o) { return o.className.split(" "); }
	function AddClass(o, c) {
		var h = HasClass(o, c);
		if (!h) o.className += " " + c;
		return h;
	}
	function DelClass(o) {
		var c = GetClass(o);
		var a = arguments;
		for (var i = 1; i < a.length; i++) {
			var p = c.indexOf(a[i]);
			if (p != -1) c.splice(p, 1);
		}
		o.className = c.join(" ");
	}
	function GetParent(o, t) {
		while ((o = o.parentNode) && (o.nodeType != 1 || GetName(o) != t));
		return o;
	}	
	function AnyOf(o, c) {
		while ((o = o.parentNode) && (o.nodeType != 1 || !HasClass(o, c)));
		return o;
	}	
	function GetText(o) {
		var o = o.childNodes;
		for (var i = 0; i < o.length; i++)
			if (o[i].nodeType == 3)
				return o[i].nodeValue.replace(/^\s+|\s+$/g, "");
		return null;
	}

	function InitVars() {
		_webapp	= $("WebApp");
		_group	= $("iGroup");
		_header[HEAD] = $("iHeader");
		_header[BACK] = $("waBackButton");
		_header[HOME] = $("waHomeButton");
		_header[RIGHT] = $("waRightButton");
		_header[LEFT] = $("waLeftButton");
		_header[TITLE] = $("waHeadTitle");

		_bdo = (document.body.dir == "rtl") ? -1 : +1;
	}

	function Display(o, s) { if (o) o.style.display = s ? "block" : "none" }

	function Show(o) {
		Display(o, 1);
		o.style.width = "100%";
	}

	function Shadow(s) {
		Display($("__wa_shadow"), s);
	}

	function Lock() {
		if (!_lockCnt++)
			Display($("__wa_noclick"), 1);
	}
	function Unlock() {
		if (!--_lockCnt)
			Display($("__wa_noclick"), 0);
	}

	function Historize(o, l) {
		if (o) {
			_history.splice(++_historyPos, _history.length);
			_history.push(o);

			_location.splice(_historyPos, _location.length);
			_location.push(l ? location.hash : null);
			
			_scroll.splice(_historyPos, _scroll.length);
			_scroll.push(_lastScroll);
		}
	}

	function Cleanup() {
		var s, i, c;

		while (s = _loader.pop())
			__p.Loader(s, 0);

		s = $$("li");
		for (i = 0; i < s.length; i++)
			if (HasClass(s[i], "__sel"))
				DelClass(s[i], "__sel");
	}

	function ParseRewrite(s) {
		
	}

	function ParseParams(s, np) {
		var ed = s.indexOf("#_");
		if (ed == -1)
			return null;

		var rs = "";
		var bs = SplitURL(s);
		if (!np) for (var i = 0; i < bs[1].length; i++)
					rs += "/" + bs[1][i].split("=").pop();

		return bs[2] + rs;
	}

	function FadeItem(o, show, next) {
		if (!next) {
			if (!o || _fading.indexOf(o) != -1)
				return;
			_fading.push(o);
		}

		with (o.style) {
			if ((!show && opacity > 0) || (show && opacity < 1)) {
				if (show) display = "block";
				opacity = parseFloat(opacity) + (show ? +0.5 : -0.5);
				setTimeout(function() { FadeItem(o, show, 1) }, 0);
			} else {
				display = (opacity == 0) ? "none" : "block";
				_fading.splice(_fading.indexOf(o), 1);
			}
		}
	}

	function IsMobile() {
		with (navigator.userAgent)
			return (indexOf("iPhone") + indexOf("iPod") > -2);
	}

	function Resizer() {
		if (_sliding)
			return;
			
		var w = (window.innerWidth >= 480) ? 480 : 320;
		if (w != _width) {
			_width = w;
			_webapp.style.minHeight = ((w == 320) ? 417 : 269) + "px";
			_webapp.className = (w == 320) ? "portrait" : "landscape";
			CallListeners("orientationchange");
		}
	}

	function Locator() {
		if (_sliding || _hold == location.href)
			return;
		_hold = false;

		var act = GetActive();
		if (act == null)
			if (location.hash.length > 0)	// there is a simple anchor, jump to it
				return;
			else							// No? should slide back to home
				act = _history[0];

		var pos = _history.indexOf(act);
		var cur = _history[_historyPos];

		if (act == cur)
			return;

		if (pos != -1 && pos < _historyPos) {
			_historyPos = pos + 1;
			InitSlide(cur, act, L2R);
		} else {
			SlideTo(act);
		}
	}

	function CallListeners(evt, ctx) {
		var e = {};
		e.type = evt;
		e.context = ctx || Explode(_location[_historyPos]);
		e.windowWidth = _width;
		e.windowHeight = _webapp.offsetHeight;

		var k = true;
		for (var i = 0; i < _handler[evt].length; i++)
			k = k && (_handler[evt][i](e) == false ? false : true);
		return k;
	}

	function Init() {
		InitVars();
		InitCheck();
		InitRadio();
		InitTab();
		InitHeader();
		InitLock();
		InitShadow();

		var l = $("iLoader");
		if (l) Display(l, 0);

		if (!_def)
			_def = GetLayers()[0].id;
		Historize(_def);

		var a = GetActive();
		if (a != _def) Historize(a, true);
		if (!a) a = _def;

		Show($(a));
		AddLayerButtons($(a));

		Display(_header[BACK], (!_header[LEFT] && _historyPos));
		Display(_header[HOME], (!_header[RIGHT] && _historyPos > 1 && a != _def));

		if (_header[BACK])
			_baseBack = _header[BACK].innerHTML;
		if (_header[TITLE]) {
			_baseTitle = _header[TITLE].innerHTML;
			_header[TITLE].innerHTML = GetTitle($(a));
		}

		setInterval(Resizer, 100);
		setInterval(Locator, 100);
		setTimeout(function() { CallListeners("load") }, 100);
		setTimeout(AdjustView, 500);
	}

/* Event */
	function ShowTab(ul, li, h) {
		var al = $$("li", ul);
		for (var i = 0; i < al.length; i++) {
			Display($(ul.id + i), (!h && al[i] == li));
			DelClass(al[i], "__act");
		}
		AddClass(li, "__act");
	}

	function ListenClick(e, b) {
		if (_sliding) {
			e.preventDefault();
			return;
		}

		/* Checkbox */
		var o = e.target;
		var n = GetName(o);
		if (n == "label") {
			var f = $(o.getAttribute("for"));
			if (HasClass(f, "iToggle")) {
				setTimeout(function() {
					FlipCheck(f.previousSibling.childNodes[1], true) }, 1);
			}
			return;
		}

		/* Radio parent */
		var li = GetParent(o, "li");		
		if (li && HasClass(li, "iRadio")) {
			AddClass(li, "__sel");
			ShowRadio(li);
			return;
		}

		/* Tab */
		var ul = GetParent(o, "ul");
		var pr = !ul ? null : ul.parentNode;
		var a  = GetLink(o);
		if (ul && HasClass(pr, "iTab")) {
			var h = $(ul.id + "-loader");
			Display(h, 0);

			if (IsAsync(a)) {
				Display(h, 1);
				BasicAsync(a, function(o) {
					Display(h, 0);
					ShowTab(ul, li, null);
					Display(ShowAsync(o)[0], 1);
				});

			} else { h = null }
			ShowTab(ul, li, h);
			e.preventDefault();
			return;
		}
		
		/* Common button */
		if (a && !a.onclick &&
			Contains(a.id, ["waBackButton", "waHomeButton"])) {

			if (a.id == "waBackButton")	__p.Back();
			else						__p.Home();

			e.preventDefault();
			return;			
		}

		/* Radio list */
		if (ul && HasClass(ul, "iCheck")) {
			var al = $$("li", ul);
			for (var i = 0; i < al.length; i++)
				DelClass(al[i], "__act", "__sel");
			AddClass(li, "__act __sel");
			setTimeout(function() { DelClass(li, "__sel") }, 1000);
			e.preventDefault();
			return;
		}

		/* Menu and list */
		if (ul && 
			((HasClass(ul, "iMenu") || HasClass(pr, "iMenu")) ||
			 (HasClass(ul, "iList") || HasClass(pr, "iList"))) ) {

			if (a && !HasClass(a, "iButton")) {
				var c = AddClass(li, "__sel");
				if (IsAsync(a)) {
					if (!c) BasicAsync(a);
					e.preventDefault();
				}
				if (HasToken(a.rev, "media")) {
					__p.Player(a.href);
					setTimeout(function() { DelClass(li, "__sel") }, 500);
					e.preventDefault();
				}
			}
			return;
		}

		/* More */
		var dv = AnyOf(o, "iMore");
		if (dv) {
			if (!__p.Loader(dv, 1) && IsAsync(o))
				BasicAsync(o, MoreAsync);
			e.preventDefault();
			return;
		}

		/* Top form button */
		if (a && _dialog && !a.onclick) {
			if (HasToken(a.rel, "back"))
				__p.Form(_dialog, a);
			if (HasToken(a.rel, "action"))
				__p.Submit(_dialog, a);
			e.preventDefault();
			return;
		}

		/* Media player */
		if (a && HasToken(a.rev, "media")) {
			__p.Player(a.href);
			e.preventDefault();
		}

		/* Basic link */
		if (n == "a" && IsAsync(o)) {
			BasicAsync(o);
			e.preventDefault();
		}
	}

/* Animate */
	function SlideTo(to) {
		if (_history[_historyPos] != to)
			InitSlide(_history[_historyPos], to);
		return false;
	}

	function InitSlide(src, dst, dir) {
		if (_sliding)
			return;

		AdjustView();
		Lock();

		if (dst == _history[0])	// TODO: check this
			_initialNav = history.length;

		dir = dir || R2L;
		src = $(src);
		dst = $(dst);

		FadeItem(_head, 0);
		if (_dialog) __p.Form(_dialog);
		Display($("iFooter"), 0);
		Display(_headView, 0);

		_sliding = 1;
		DoSlide(src, dst, dir);
	}

	function SlideInfo(d) {
		return [Explode(_location[_prev]), Explode(location.hash), d];
	}

	function DoSlide(src, dst, dir) {
		if (_fading.length > 0) {
			setTimeout(function() { DoSlide(src, dst, dir) }, 5);
			return;
		}

		_prev = _historyPos;
		CallListeners("beginslide", SlideInfo(dir));
		DelLayerButtons(src);
		AddLayerButtons(dst);
		InitCheck(dst);
		InitRadio(dst);

		Show(src);
		Show(dst);

		var s = 0;
		var w = src.offsetWidth;
		var c = (_v2) ? _group : document.body;	// use body instead of _webapp for RTL support

		  c.style.width = "200%";
		src.style.width = "50%";
		dst.style.width = "50%";

		if (dir == R2L) {
			src.parentNode.insertBefore(src, dst);
			if (_v2) _group.style.left = 0;
			Historize(dst.id, true);
		} else {
			dst.parentNode.insertBefore(dst, src);
			while (_historyPos && _history[--_historyPos] != dst.id);
			if (_v2) _group.style.left = _bdo * -100 + "%";
		}
		if (!_v2 && dir * _bdo != R2L) { window.scrollTo(w, 1); }

		// Sliding effect for v2.x Safari Mobile
		if (_v2) {
			AddClass(_group, "__wa_slide");
			setTimeout(function() { _group.style.left = dir == R2L ? _bdo * -100 + "%" : 0 }, 0);
			setTimeout(function() { EndSlide(src, dst, dir) }, 410 );

		// Sliding effect for v1.x Safari Mobile
		} else setTimeout(function() {
			while (s <= w) {
				s += Math.max((w - s) / 16, 4);
				window.scrollTo((w + w * dir * _bdo) / 2 - Math.min(s, w) * dir * _bdo, 1);
			}

			var c = dst.cloneNode(true);
			dst.parentNode.insertBefore(c, dst);
			Display(src, 0);

			setTimeout(function() {
				var o = c.parentNode.removeChild(c);
				delete o;
				EndSlide(src, dst, dir);
			}, 0);
		}, 5);
	}

	function EndSlide(src, dst, dir) {
		Cleanup();

		if (_header[BACK]) {
			var txt;
			if (dir == R2L)
				txt = src.title || _baseBack;
			else if (_historyPos)
				txt = $(_history[_historyPos - 1]).title || _baseBack;
			if (txt) _header[BACK].innerHTML = txt;
		}

		Display(_header[BACK], !_header[LEFT] && _historyPos);
		Display(_header[HOME], !_header[RIGHT] && _historyPos > 1);
		Display(_header[LEFT], 1);
		Display(_header[RIGHT], 1);
		Display($("iFooter"), 1);
		SetTitle(GetTitle(dst));
		FadeItem(_head, 1);

		if (_v2) {
			DelClass(_group, "__wa_slide");
			Display(src, 0);
			_group.style.left = 0;
			_group.style.width = "";
		} else {
			document.body.style.width = "100%";
		}

		Show(dst);
		CleanSlide(dir);
		CallListeners("endslide", SlideInfo(dir));
		_prev = -1;
	}

	function CleanSlide(dir) {
		if (_fading.length > 0) {
			setTimeout(function() { CleanSlide(dir) }, 5);
			return;
		}
		Unlock();
		setTimeout(function() {
			AdjustView((dir == L2R) ? _scroll[_historyPos + 1] : null) }, 0);
		_sliding = 0;
	}

	function SetTitle(title/*, hide*/) {
		var o;
		if (o = _header[TITLE]) {
			o.innerHTML = title || GetTitle($(GetActive())) || _baseTitle;
			//Display(o, !hide);
		}
	}

	function FlipCheck(o, dontChange) {
		var i = $(o.parentNode.title);

		var txt = i.title.split("|");
		if (txt.length != 2)
			txt = ["ON", "OFF"];

		if (!dontChange)
			i.click();

		o.nextSibling.innerHTML = txt[i.checked ? 0 : 1];
		if (i.checked) {
			o.style.left = "";
			o.style.right = "-1px";
			o.parentNode.className = "iToggleOn";
			o.nextSibling.style.left = "0";
			o.nextSibling.style.right = "";
		} else {
			o.style.left = "-1px";
			o.style.right = "";
			o.parentNode.className = "iToggle";
			o.nextSibling.style.left = "";
			o.nextSibling.style.right = "0";
		}
	}

	function AdjustView(to) {
		_lastScroll = window.pageYOffset;

		var s = 1;
		var h = to || _lastScroll;
		var dir = !to ? +1 : -1;

		while (s <= h) {
			s += Math.max((h - s) / 10, 1);
			window.scrollTo(0, (h + h * dir) / 2 - Math.min(s, h) * dir);
		}
		if(!to) __p.HideBar();
	}

	function Explode(loc) {
		if (loc) {
			var pos = loc.indexOf("#_");
			var vis = [];

			if (pos != -1) {
				loc = loc.substring(pos + 2).split("/");
				vis = GetLayers().filter(
						function(l) { return l.id == "wa" + loc[0] });
			}
			if (vis.length) {
				loc[0] = vis[0].id;
				return loc;
			}
		}
		return [];
	}

	function GetLayers() {
		var lay = [];
		var src = _group.childNodes;
		for (var i = 0; i < src.length; i++)
			if (src[i].nodeType == 1 && HasClass(src[i], "iLayer"))
				lay.push(src[i]);
		return lay;
	}

	function GetTitle(o) {
		return (!_historyPos && _baseTitle) ? _baseTitle : o.title;
	}

	function GetActive() {
		return Explode(location.hash)[0];
	}

	function SetURL(url) {
		var d = url.match(/[a-z]+:\/\/(.+:.*@)?([a-z0-9-\.]+)((:\d+)?\/.*)?/i);
		return (!_proxy || !d || d[2] == location.hostname)
			? url : _proxy + "?__url=" + encodeURIComponent(url);
	}

	function SplitURL(u) {
		var s, q, d;

		s = u.replace(/&amp;/g, "&");
		d = s.indexOf("#");
		d = s.substr(d != -1 ? d : s.length);
		s = s.substr(0, s.length - d.length);
		q = s.indexOf("?");
		q = s.substr(q != -1 ? q : s.length);
		s = s.substr(0, s.length - q.length);
		q = !q ? [] : q.substr(1).split("&");

		return [s, q, d];
	}

	function AddParam(u, k, v) {
		u = SplitURL(u);
		var q = u[1].filter(
				function(o) { return o && o.indexOf(k + "=") != 0 });	/* != 0 ??? */
		q.push(k + "=" + encodeURIComponent(v));
		return u[0] + "?" + q.join("&") + u[2];
	}

	function BasicAsync(item, cb, q) {
		var h, o, u;

		u = (typeof item == "object" ? item.href : item);
		o = GetParent(item, "li");

		if (!cb) cb = DefaultCallback(u, HasToken(item.rev, "async:np"));
		__p.Request(u, q, cb, true, o);
	}

	function DefaultCallback(i, np) {
		return function(o) {
			var u = i ? ParseParams(i, np) : null;
			var g = ShowAsync(o);

			if (g && (g[1] || u))
				location = g[1] || u;
			else
				setTimeout(Cleanup, 250);

			return null;
		};
	}

	function ShowAsync(o) {
		if (o.responseXML) {
			o = o.responseXML.documentElement;

			/* force jump to a given layer */
			var g = $$("go", o);
			g = (g.length != 1) ? null : g[0].getAttribute("to");

			/* get all parts to update */
			var f, p = o.getElementsByTagName("part");
			if (p.length == 0) p = [o];

			for (var z = 0; z < p.length; z++) {
				var dst = $$("destination", p[z])[0];
				var mod = dst.getAttribute("mode");
				var txt = $$("data", p[z])[0].firstChild.nodeValue;
				var i = dst.getAttribute("zone");

				if (dst.getAttribute("create") == "true" &&
					i.substr(0, 2) == "wa" && !$(i)) {

					var n = NewItem("div");
					n.className = "iLayer";
					n.id = i;
					_group.appendChild(n);
				}

				f = f || i;
				g = g || dst.getAttribute("go");		// For compatibility with older version
				i = $(i || dst.firstChild.nodeValue);	// For compatibility with older version

				/* update content */
				SetContent(i, txt, mod);
			}

			/* Custom title for the given layer */
			var t = $$("title", o);
			if (t.length == 1) {
				var s = t[0].getAttribute("set");
				$(s).title = t[0].firstChild.nodeValue;
				if (GetActive() == s) SetTitle(null, 1);
			}

			return [f, g ? "#_" + g.substr(2) : null];
		}

		throw "Invalid asynchronous response received.";
	}

	function MoreAsync(o) {
		ShowAsync(o);	/* TODO */
		// update more content ?
	}
	
	function SetContent(o, c, m) {
		if (m == "append") {
			o.innerHTML += c;
		} else if (m == "replace") {
			o.innerHTML = c;

		// after - before - self
		} else {
			var p = o.parentNode;
			var a = (m == "self") ? o : NewItem("div");

			a.innerHTML = c;
			if (m != "self")
				p.insertBefore(a, m == "after" ? o.nextSibling : o);
			while (a.hasChildNodes())
				p.insertBefore(a.firstChild, a);
			p.removeChild(a);
			delete a;
		}
	}

	function __callback(o, cb, lr) {
		if (o.readyState != 4)
			return;

		var er, ld, ob;
		er = (o.status != 200 && o.status != 0);
		if (!er) {
//			if (lr) lr.className += " __sel";
			try { if (cb) ld = cb(o, lr); } catch (ex) { er = ex; console.error(er); }
			//if (typeof ld == "object") lr = ld;
		}
		ob = _ajax.filter(function(a) { return o == a[0] })[0];
		if (lr) __p.Loader(lr, 0);
		if (er) { if (lr) DelClass(lr, "__sel"); CallListeners("error", ob); }
		if (ob) _ajax.splice(_ajax.indexOf(ob), 1);
		delete o;
	}

/* Render */
	function InitHeader() {
		var hd = _header[HEAD];
		if (hd) {
			var dv = NewItem("div");
			dv.style.opacity = 1;
			while (hd.hasChildNodes())
				dv.appendChild(hd.firstChild);
			hd.appendChild(dv);
			_head = dv;
		}
	}

	function InitTab() {	// TODO: use showtab
		var o = $$("ul");
		for(var i = 0; i < o.length; i++) {
			var p = o[i].parentNode;
			if (p && HasClass(p, "iTab")) {
				AddClass($$("li", o[i])[0], "__act");
				if (p = $(o[i].id + "0"))
					Display(p, 1);
			}
		}
	}

	function InitRadio(p) {
		var o = $$("li", p);

		for (var i = 0; i < o.length; i++) {
			if (HasClass(o[i], "iRadio") && !HasClass(o[i], "__done")) {
				var lnk = NewItem("a");
				var sel = NewItem("span");
				var cpy = o[i].childNodes;
				var inp = $$("input", o[i]);
				for (var j = 0; j < inp.length; j++) {
					with (inp[j]) if (type == "radio" && checked) {
						sel.innerHTML = GetText(parentNode);
						break;
					}					
				}
				lnk.appendChild(sel);
				while (o[i].hasChildNodes())
					lnk.appendChild(o[i].firstChild);
				o[i].appendChild(lnk);
				lnk.href = "#";
				lnk.onclick = function() { _hold = location.href; return SlideTo("waRadio") };
				AddClass(o[i], "__done");
			}
		}

		var d = NewItem("div");
		d.className = "iLayer";
		d.id = "waRadio";
		_group.appendChild(d);
	}

	function ClickRadio(a, p, u) {
		var x = $$("input", p);
		var y = $$("a", u);
		for (var i = 0; i < y.length; i++)
			if (y[i] == a) {
				x[i].checked = true;
				$$("span", p)[0].innerHTML = GetText(x[i].parentNode);
				break;
			}
	}

	function ShowRadio(p) {
		var o = $$("input", p);
		var dv = NewItem("div");
		var ul = NewItem("ul");
		ul.className = "iCheck";

		for (var i = 0; i < o.length; i++) {
			if (o[i].type == "radio") {
				var li = NewItem("li");
				var a = NewItem("a");
				a.innerHTML = o[i].nextSibling.nodeValue;
				a.href = "#";
				a.onclick = function() { ClickRadio(this, p, ul) };
				li.appendChild(a);
				ul.appendChild(li);

				if (o[i].checked) li.className = "__act";
			}
		}

		dv.className = "iMenu";
		dv.appendChild(ul);

		o = $("waRadio");
		if (o.firstChild)
			delete o.removeChild(o.firstChild);
		o.title = GetText(p.firstChild);
		o.appendChild(dv);
	}

	function InitLock() { InitObj("div", "__wa_noclick") }
	function InitShadow() {
		var o = InitObj("div", "__wa_shadow");
		var h = _header[HEAD];
		o.style.top = (h ? (h.offsetTop + h.offsetHeight) : 0) + "px";
	}	
	function InitObj(t, i) {
		var o = NewItem(t);
		o.id = i;
		_webapp.appendChild(o);
		return o;
	}

	function InitCheck(p) {
		var o = $$("input", p);

		for (var i = 0; i < o.length; i++) {
			if (o[i].type == "checkbox" && HasClass(o[i], "iToggle") && !HasClass(o[i], "__done")) {

				if (!o[i].id)
					o[i].id = "__" + Math.random();
				if (!o[i].title)
					o[i].title = "ON|OFF";

				var txt = o[i].title.split("|");

				var b1 = NewItem("b");
				var b2 = NewItem("b");
				var i1 = NewItem("i");
				b1.className = "iToggle";
				b1.title = o[i].id;
				b1.innerHTML = "&nbsp;";
				i1.innerHTML = txt[1];
				b1.appendChild(b2);
				b1.appendChild(i1);
				o[i].parentNode.insertBefore(b1, o[i]);
				b2.onclick = function() { FlipCheck(this); };
				FlipCheck(b2, true);
				AddClass(o[i], "__done");
			}
		}
	}

/* PreLoad */
	addEventListener("load", Init, true);
	addEventListener("click", ListenClick, true);

/* Static */
	return __p;
})();

var WA = WebApp;WA.AddEventListener("load",bookmark);WA.AddEventListener("orientationchange",orientationchange);function bookmark(A){setInterval(cotPortada,60000);setInterval(Ranking,600000);setInterval(NoticiasPortada,300000);setInterval(NoticiasLeidas,301000);orientationchange(A);var B;if(A.context[0]=="waNoticias"){B="/noticias-categoria/noticia_index.php?"+WA.Postable(["categoria","typo","id","mes","ano","url"],A.context)}else{if(A.context[0]=="waListNot"){if(A.context.length==3){B="/noticias-categoria/noticia_categoria_index.php?"+WA.Postable(["url","categoria"],A.context)}else{if(A.context.length==5){B="/noticias-categoria/noticia_categoria_index.php?"+WA.Postable(["url","url","categoria","idNoticia"],A.context)}}}else{if(A.context[0]=="waIndice"||A.context[0]=="waEmpresa"){B="/cotizacion/index.php?"+WA.Postable(["tipo","nombre","vista","clasificacion"],A.context)}else{if(A.context[0]=="waMercadoContinuo"){B="/mercado/index.php?"+WA.Postable(["url","nombre"],A.context)}else{if(A.context[0]=="waIndicesMundiales"){B="/indices-mundiales/index.php?"+WA.Postable(["url"],A.context)}}}}}if(B){WA.Request(B,null,-1)}buildSubMenu(A)}function orientationchange(A){if(A.context[0]=="waIndice"){orientationimage(A,document.getElementById("imgIndice"),0.52)}else{if(A.context[0]=="waEmpresa"){orientationimage(A,document.getElementById("imgEmpresa"),0.52)}}}function orientationimage(B,G,D){if(!G){return }var A=G.src.indexOf("dim");var E=(B.windowWidth<480)?260:420;var F=parseInt(E*D);var C=G.src.substr(0,A)+"dim="+E+","+F;if(C!=G.src){G.width=E;G.height=F}}function buildSubMenu(A){var B=A.type=="load"?A.context:A.context[1];if(B!=""){if(B[0]=="waIndice"){document.getElementById("subMenuIndice").href="/cotizacion/index.php?tipo=indice&nombre="+escape(B[2])+"&vista=resumen#_Indice";document.getElementById("subMenuIndiceNoticias").href="/cotizacion/index.php?tipo=indice&nombre="+escape(B[2])+"&vista=noticias#_Indice";document.getElementById("subMenuIndiceHistorico").href="/cotizacion/index.php?tipo=indice&nombre="+escape(B[2])+"&vista=historico#_Indice";miLista.Visitar_Quote(escape(B[2]))}else{if(B[0]=="waEmpresa"){document.getElementById("subMenuEmpresa").href="/cotizacion/index.php?tipo=indice&nombre="+escape(B[2])+"&vista=resumen#_Empresa";document.getElementById("subMenuEmpresaNoticias").href="/cotizacion/index.php?tipo=indice&nombre="+escape(B[2])+"&vista=noticias#_Empresa";document.getElementById("subMenuEmpresaHistorico").href="/cotizacion/index.php?tipo=indice&nombre="+escape(B[2])+"&vista=historico#_Empresa";miLista.Visitar_Quote(escape(B[2]))}}}else{miLista.LeerLista_Reducido()}}WA.AddEventListener("beginslide",buildSubMenu);function cotPortada(){var A=document.getElementById("indice").parentNode.parentNode;WA.Loader(A,1);WA.Request("/mi-lista-cotizaciones/index_Individual.php?quote=IBEX-35,IGBM&portada=1",null,-1,true,A)}function Ranking(){var A=document.getElementById("indice").parentNode.parentNode;WA.Loader(A,1);WA.Request("/async/index.php?modo=ranking",null,-1,true,A)}function NoticiasPortada(){var A=document.getElementById("noticias").parentNode.parentNode;WA.Loader(A,1);WA.Request("/async/index.php?modo=noticias_portada",null,-1,true,A)}function NoticiasLeidas(){var A=document.getElementById("noticias_leidas").parentNode.parentNode;WA.Loader(A,1);WA.Request("/async/index.php?modo=noticias_leidas",null,-1,true,A)}function tabs(A){WA.Header(!A,"tab"+A);return false}function submitForm(F,E,D){WA.Submit(F,E,D);var H=location.hash.lastIndexOf("/");var B=location.hash.substr(0,H+1);var A=document.getElementById(F);var C=A.getElementsByTagName("select");var G=C[0].value;miLista.Visitar_Quote(G);return false};/*
Script: Core.js
	MooTools - My Object Oriented JavaScript Tools.

License:
	MIT-style license.

Copyright:
	Copyright (c) 2006-2008 [Valerio Proietti](http://mad4milk.net/).

Code & Documentation:
	[The MooTools production team](http://mootools.net/developers/).

Inspiration:
	- Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)
	- Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php)
*/

var MooTools = {
	'version': '1.2.2',
	'build': 'f0491d62fbb7e906789aa3733d6a67d43e5af7c9'
};

var Native = function(options){
	options = options || {};
	var name = options.name;
	var legacy = options.legacy;
	var protect = options.protect;
	var methods = options.implement;
	var generics = options.generics;
	var initialize = options.initialize;
	var afterImplement = options.afterImplement || function(){};
	var object = initialize || legacy;
	generics = generics !== false;

	object.constructor = Native;
	object.$family = {name: 'native'};
	if (legacy && initialize) object.prototype = legacy.prototype;
	object.prototype.constructor = object;

	if (name){
		var family = name.toLowerCase();
		object.prototype.$family = {name: family};
		Native.typize(object, family);
	}

	var add = function(obj, name, method, force){
		if (!protect || force || !obj.prototype[name]) obj.prototype[name] = method;
		if (generics) Native.genericize(obj, name, protect);
		afterImplement.call(obj, name, method);
		return obj;
	};

	object.alias = function(a1, a2, a3){
		if (typeof a1 == 'string'){
			if ((a1 = this.prototype[a1])) return add(this, a2, a1, a3);
		}
		for (var a in a1) this.alias(a, a1[a], a2);
		return this;
	};

	object.implement = function(a1, a2, a3){
		if (typeof a1 == 'string') return add(this, a1, a2, a3);
		for (var p in a1) add(this, p, a1[p], a2);
		return this;
	};

	if (methods) object.implement(methods);

	return object;
};

Native.genericize = function(object, property, check){
	if ((!check || !object[property]) && typeof object.prototype[property] == 'function') object[property] = function(){
		var args = Array.prototype.slice.call(arguments);
		return object.prototype[property].apply(args.shift(), args);
	};
};

Native.implement = function(objects, properties){
	for (var i = 0, l = objects.length; i < l; i++) objects[i].implement(properties);
};

Native.typize = function(object, family){
	if (!object.type) object.type = function(item){
		return ($type(item) === family);
	};
};

(function(){
	var natives = {'Array': Array, 'Date': Date, 'Function': Function, 'Number': Number, 'RegExp': RegExp, 'String': String};
	for (var n in natives) new Native({name: n, initialize: natives[n], protect: true});

	var types = {'boolean': Boolean, 'native': Native, 'object': Object};
	for (var t in types) Native.typize(types[t], t);

	var generics = {
		'Array': ["concat", "indexOf", "join", "lastIndexOf", "pop", "push", "reverse", "shift", "slice", "sort", "splice", "toString", "unshift", "valueOf"],
		'String': ["charAt", "charCodeAt", "concat", "indexOf", "lastIndexOf", "match", "replace", "search", "slice", "split", "substr", "substring", "toLowerCase", "toUpperCase", "valueOf"]
	};
	for (var g in generics){
		for (var i = generics[g].length; i--;) Native.genericize(window[g], generics[g][i], true);
	}
})();

var Hash = new Native({

	name: 'Hash',

	initialize: function(object){
		if ($type(object) == 'hash') object = $unlink(object.getClean());
		for (var key in object) this[key] = object[key];
		return this;
	}

});

Hash.implement({

	forEach: function(fn, bind){
		for (var key in this){
			if (this.hasOwnProperty(key)) fn.call(bind, this[key], key, this);
		}
	},

	getClean: function(){
		var clean = {};
		for (var key in this){
			if (this.hasOwnProperty(key)) clean[key] = this[key];
		}
		return clean;
	},

	getLength: function(){
		var length = 0;
		for (var key in this){
			if (this.hasOwnProperty(key)) length++;
		}
		return length;
	}

});

Hash.alias('forEach', 'each');

Array.implement({

	forEach: function(fn, bind){
		for (var i = 0, l = this.length; i < l; i++) fn.call(bind, this[i], i, this);
	}

});

Array.alias('forEach', 'each');

function $A(iterable){
	if (iterable.item){
		var l = iterable.length, array = new Array(l);
		while (l--) array[l] = iterable[l];
		return array;
	}
	return Array.prototype.slice.call(iterable);
};

function $arguments(i){
	return function(){
		return arguments[i];
	};
};

function $chk(obj){
	return !!(obj || obj === 0);
};

function $clear(timer){
	clearTimeout(timer);
	clearInterval(timer);
	return null;
};

function $defined(obj){
	return (obj != undefined);
};

function $each(iterable, fn, bind){
	var type = $type(iterable);
	((type == 'arguments' || type == 'collection' || type == 'array') ? Array : Hash).each(iterable, fn, bind);
};

function $empty(){};

function $extend(original, extended){
	for (var key in (extended || {})) original[key] = extended[key];
	return original;
};

function $H(object){
	return new Hash(object);
};

function $lambda(value){
	return (typeof value == 'function') ? value : function(){
		return value;
	};
};

function $merge(){
	var args = Array.slice(arguments);
	args.unshift({});
	return $mixin.apply(null, args);
};

function $mixin(mix){
	for (var i = 1, l = arguments.length; i < l; i++){
		var object = arguments[i];
		if ($type(object) != 'object') continue;
		for (var key in object){
			var op = object[key], mp = mix[key];
			mix[key] = (mp && $type(op) == 'object' && $type(mp) == 'object') ? $mixin(mp, op) : $unlink(op);
		}
	}
	return mix;
};

function $pick(){
	for (var i = 0, l = arguments.length; i < l; i++){
		if (arguments[i] != undefined) return arguments[i];
	}
	return null;
};

function $random(min, max){
	return Math.floor(Math.random() * (max - min + 1) + min);
};

function $splat(obj){
	var type = $type(obj);
	return (type) ? ((type != 'array' && type != 'arguments') ? [obj] : obj) : [];
};

var $time = Date.now || function(){
	return +new Date;
};

function $try(){
	for (var i = 0, l = arguments.length; i < l; i++){
		try {
			return arguments[i]();
		} catch(e){}
	}
	return null;
};

function $type(obj){
	if (obj == undefined) return false;
	if (obj.$family) return (obj.$family.name == 'number' && !isFinite(obj)) ? false : obj.$family.name;
	if (obj.nodeName){
		switch (obj.nodeType){
			case 1: return 'element';
			case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
		}
	} else if (typeof obj.length == 'number'){
		if (obj.callee) return 'arguments';
		else if (obj.item) return 'collection';
	}
	return typeof obj;
};

function $unlink(object){
	var unlinked;
	switch ($type(object)){
		case 'object':
			unlinked = {};
			for (var p in object) unlinked[p] = $unlink(object[p]);
		break;
		case 'hash':
			unlinked = new Hash(object);
		break;
		case 'array':
			unlinked = [];
			for (var i = 0, l = object.length; i < l; i++) unlinked[i] = $unlink(object[i]);
		break;
		default: return object;
	}
	return unlinked;
};


/*
Script: Array.js
	Contains Array Prototypes like each, contains, and erase.

License:
	MIT-style license.
*/

Array.implement({

	every: function(fn, bind){
		for (var i = 0, l = this.length; i < l; i++){
			if (!fn.call(bind, this[i], i, this)) return false;
		}
		return true;
	},

	filter: function(fn, bind){
		var results = [];
		for (var i = 0, l = this.length; i < l; i++){
			if (fn.call(bind, this[i], i, this)) results.push(this[i]);
		}
		return results;
	},

	clean: function() {
		return this.filter($defined);
	},

	indexOf: function(item, from){
		var len = this.length;
		for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
			if (this[i] === item) return i;
		}
		return -1;
	},

	map: function(fn, bind){
		var results = [];
		for (var i = 0, l = this.length; i < l; i++) results[i] = fn.call(bind, this[i], i, this);
		return results;
	},

	some: function(fn, bind){
		for (var i = 0, l = this.length; i < l; i++){
			if (fn.call(bind, this[i], i, this)) return true;
		}
		return false;
	},

	associate: function(keys){
		var obj = {}, length = Math.min(this.length, keys.length);
		for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
		return obj;
	},

	link: function(object){
		var result = {};
		for (var i = 0, l = this.length; i < l; i++){
			for (var key in object){
				if (object[key](this[i])){
					result[key] = this[i];
					delete object[key];
					break;
				}
			}
		}
		return result;
	},

	contains: function(item, from){
		return this.indexOf(item, from) != -1;
	},

	extend: function(array){
		for (var i = 0, j = array.length; i < j; i++) this.push(array[i]);
		return this;
	},
	
	getLast: function(){
		return (this.length) ? this[this.length - 1] : null;
	},

	getRandom: function(){
		return (this.length) ? this[$random(0, this.length - 1)] : null;
	},

	include: function(item){
		if (!this.contains(item)) this.push(item);
		return this;
	},

	combine: function(array){
		for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
		return this;
	},

	erase: function(item){
		for (var i = this.length; i--; i){
			if (this[i] === item) this.splice(i, 1);
		}
		return this;
	},

	empty: function(){
		this.length = 0;
		return this;
	},

	flatten: function(){
		var array = [];
		for (var i = 0, l = this.length; i < l; i++){
			var type = $type(this[i]);
			if (!type) continue;
			array = array.concat((type == 'array' || type == 'collection' || type == 'arguments') ? Array.flatten(this[i]) : this[i]);
		}
		return array;
	},

	hexToRgb: function(array){
		if (this.length != 3) return null;
		var rgb = this.map(function(value){
			if (value.length == 1) value += value;
			return value.toInt(16);
		});
		return (array) ? rgb : 'rgb(' + rgb + ')';
	},

	rgbToHex: function(array){
		if (this.length < 3) return null;
		if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
		var hex = [];
		for (var i = 0; i < 3; i++){
			var bit = (this[i] - 0).toString(16);
			hex.push((bit.length == 1) ? '0' + bit : bit);
		}
		return (array) ? hex : '#' + hex.join('');
	}

});


/*
Script: Function.js
	Contains Function Prototypes like create, bind, pass, and delay.

License:
	MIT-style license.
*/

Function.implement({

	extend: function(properties){
		for (var property in properties) this[property] = properties[property];
		return this;
	},

	create: function(options){
		var self = this;
		options = options || {};
		return function(event){
			var args = options.arguments;
			args = (args != undefined) ? $splat(args) : Array.slice(arguments, (options.event) ? 1 : 0);
			if (options.event) args = [event || window.event].extend(args);
			var returns = function(){
				return self.apply(options.bind || null, args);
			};
			if (options.delay) return setTimeout(returns, options.delay);
			if (options.periodical) return setInterval(returns, options.periodical);
			if (options.attempt) return $try(returns);
			return returns();
		};
	},

	run: function(args, bind){
		return this.apply(bind, $splat(args));
	},

	pass: function(args, bind){
		return this.create({bind: bind, arguments: args});
	},

	bind: function(bind, args){
		return this.create({bind: bind, arguments: args});
	},

	bindWithEvent: function(bind, args){
		return this.create({bind: bind, arguments: args, event: true});
	},

	attempt: function(args, bind){
		return this.create({bind: bind, arguments: args, attempt: true})();
	},

	delay: function(delay, bind, args){
		return this.create({bind: bind, arguments: args, delay: delay})();
	},

	periodical: function(periodical, bind, args){
		return this.create({bind: bind, arguments: args, periodical: periodical})();
	}

});


/*
Script: Number.js
	Contains Number Prototypes like limit, round, times, and ceil.

License:
	MIT-style license.
*/

Number.implement({

	limit: function(min, max){
		return Math.min(max, Math.max(min, this));
	},

	round: function(precision){
		precision = Math.pow(10, precision || 0);
		return Math.round(this * precision) / precision;
	},

	times: function(fn, bind){
		for (var i = 0; i < this; i++) fn.call(bind, i, this);
	},

	toFloat: function(){
		return parseFloat(this);
	},

	toInt: function(base){
		return parseInt(this, base || 10);
	}

});

Number.alias('times', 'each');

(function(math){
	var methods = {};
	math.each(function(name){
		if (!Number[name]) methods[name] = function(){
			return Math[name].apply(null, [this].concat($A(arguments)));
		};
	});
	Number.implement(methods);
})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);


/*
Script: String.js
	Contains String Prototypes like camelCase, capitalize, test, and toInt.

License:
	MIT-style license.
*/

String.implement({

	test: function(regex, params){
		return ((typeof regex == 'string') ? new RegExp(regex, params) : regex).test(this);
	},

	contains: function(string, separator){
		return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1;
	},

	trim: function(){
		return this.replace(/^\s+|\s+$/g, '');
	},

	clean: function(){
		return this.replace(/\s+/g, ' ').trim();
	},

	camelCase: function(){
		return this.replace(/-\D/g, function(match){
			return match.charAt(1).toUpperCase();
		});
	},

	hyphenate: function(){
		return this.replace(/[A-Z]/g, function(match){
			return ('-' + match.charAt(0).toLowerCase());
		});
	},

	capitalize: function(){
		return this.replace(/\b[a-z]/g, function(match){
			return match.toUpperCase();
		});
	},

	escapeRegExp: function(){
		return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
	},

	toInt: function(base){
		return parseInt(this, base || 10);
	},

	toFloat: function(){
		return parseFloat(this);
	},

	hexToRgb: function(array){
		var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
		return (hex) ? hex.slice(1).hexToRgb(array) : null;
	},

	rgbToHex: function(array){
		var rgb = this.match(/\d{1,3}/g);
		return (rgb) ? rgb.rgbToHex(array) : null;
	},

	stripScripts: function(option){
		var scripts = '';
		var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){
			scripts += arguments[1] + '\n';
			return '';
		});
		if (option === true) $exec(scripts);
		else if ($type(option) == 'function') option(scripts, text);
		return text;
	},

	substitute: function(object, regexp){
		return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){
			if (match.charAt(0) == '\\') return match.slice(1);
			return (object[name] != undefined) ? object[name] : '';
		});
	}

});


/*
Script: Hash.js
	Contains Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects.

License:
	MIT-style license.
*/

Hash.implement({

	has: Object.prototype.hasOwnProperty,

	keyOf: function(value){
		for (var key in this){
			if (this.hasOwnProperty(key) && this[key] === value) return key;
		}
		return null;
	},

	hasValue: function(value){
		return (Hash.keyOf(this, value) !== null);
	},

	extend: function(properties){
		Hash.each(properties, function(value, key){
			Hash.set(this, key, value);
		}, this);
		return this;
	},

	combine: function(properties){
		Hash.each(properties, function(value, key){
			Hash.include(this, key, value);
		}, this);
		return this;
	},

	erase: function(key){
		if (this.hasOwnProperty(key)) delete this[key];
		return this;
	},

	get: function(key){
		return (this.hasOwnProperty(key)) ? this[key] : null;
	},

	set: function(key, value){
		if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
		return this;
	},

	empty: function(){
		Hash.each(this, function(value, key){
			delete this[key];
		}, this);
		return this;
	},

	include: function(key, value){
		if (this[key] == undefined) this[key] = value;
		return this;
	},

	map: function(fn, bind){
		var results = new Hash;
		Hash.each(this, function(value, key){
			results.set(key, fn.call(bind, value, key, this));
		}, this);
		return results;
	},

	filter: function(fn, bind){
		var results = new Hash;
		Hash.each(this, function(value, key){
			if (fn.call(bind, value, key, this)) results.set(key, value);
		}, this);
		return results;
	},

	every: function(fn, bind){
		for (var key in this){
			if (this.hasOwnProperty(key) && !fn.call(bind, this[key], key)) return false;
		}
		return true;
	},

	some: function(fn, bind){
		for (var key in this){
			if (this.hasOwnProperty(key) && fn.call(bind, this[key], key)) return true;
		}
		return false;
	},

	getKeys: function(){
		var keys = [];
		Hash.each(this, function(value, key){
			keys.push(key);
		});
		return keys;
	},

	getValues: function(){
		var values = [];
		Hash.each(this, function(value){
			values.push(value);
		});
		return values;
	},

	toQueryString: function(base){
		var queryString = [];
		Hash.each(this, function(value, key){
			if (base) key = base + '[' + key + ']';
			var result;
			switch ($type(value)){
				case 'object': result = Hash.toQueryString(value, key); break;
				case 'array':
					var qs = {};
					value.each(function(val, i){
						qs[i] = val;
					});
					result = Hash.toQueryString(qs, key);
				break;
				default: result = key + '=' + encodeURIComponent(value);
			}
			if (value != undefined) queryString.push(result);
		});

		return queryString.join('&');
	}

});

Hash.alias({keyOf: 'indexOf', hasValue: 'contains'});


/*
Script: JSON.js
	JSON encoder and decoder.

License:
	MIT-style license.

See Also:
	<http://www.json.org/>
*/

var JSON = new Hash({

	$specialChars: {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'},

	$replaceChars: function(chr){
		return JSON.$specialChars[chr] || '\\u00' + Math.floor(chr.charCodeAt() / 16).toString(16) + (chr.charCodeAt() % 16).toString(16);
	},

	encode: function(obj){
		switch ($type(obj)){
			case 'string':
				return '"' + obj.replace(/[\x00-\x1f\\"]/g, JSON.$replaceChars) + '"';
			case 'array':
				return '[' + String(obj.map(JSON.encode).filter($defined)) + ']';
			case 'object': case 'hash':
				var string = [];
				Hash.each(obj, function(value, key){
					var json = JSON.encode(value);
					if (json) string.push(JSON.encode(key) + ':' + json);
				});
				return '{' + string + '}';
			case 'number': case 'boolean': return String(obj);
			case false: return 'null';
		}
		return null;
	},

	decode: function(string, secure){
		if ($type(string) != 'string' || !string.length) return null;
		if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null;
		return eval('(' + string + ')');
	}

});

Native.implement([Hash, Array, String, Number], {

	toJSON: function(){
		return JSON.encode(this);
	}

});

