//MooTools, <http://mootools.net>, My Object Oriented (JavaScript) Tools. Copyright (c) 2006-2009 Valerio Proietti, <http://mad4milk.net>, MIT Style License.

var MooTools={version:"1.2.4",build:"0d9113241a90b9cd5643b926795852a2026710d4"};var Native=function(k){k=k||{};var a=k.name;var i=k.legacy;var b=k.protect;
var c=k.implement;var h=k.generics;var f=k.initialize;var g=k.afterImplement||function(){};var d=f||i;h=h!==false;d.constructor=Native;d.$family={name:"native"};
if(i&&f){d.prototype=i.prototype;}d.prototype.constructor=d;if(a){var e=a.toLowerCase();d.prototype.$family={name:e};Native.typize(d,e);}var j=function(n,l,o,m){if(!b||m||!n.prototype[l]){n.prototype[l]=o;
}if(h){Native.genericize(n,l,b);}g.call(n,l,o);return n;};d.alias=function(n,l,p){if(typeof n=="string"){var o=this.prototype[n];if((n=o)){return j(this,l,n,p);
}}for(var m in n){this.alias(m,n[m],l);}return this;};d.implement=function(m,l,o){if(typeof m=="string"){return j(this,m,l,o);}for(var n in m){j(this,n,m[n],l);
}return this;};if(c){d.implement(c);}return d;};Native.genericize=function(b,c,a){if((!a||!b[c])&&typeof b.prototype[c]=="function"){b[c]=function(){var d=Array.prototype.slice.call(arguments);
return b.prototype[c].apply(d.shift(),d);};}};Native.implement=function(d,c){for(var b=0,a=d.length;b<a;b++){d[b].implement(c);}};Native.typize=function(a,b){if(!a.type){a.type=function(c){return($type(c)===b);
};}};(function(){var a={Array:Array,Date:Date,Function:Function,Number:Number,RegExp:RegExp,String:String};for(var h in a){new Native({name:h,initialize:a[h],protect:true});
}var d={"boolean":Boolean,"native":Native,object:Object};for(var c in d){Native.typize(d[c],c);}var f={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 e in f){for(var b=f[e].length;b--;){Native.genericize(a[e],f[e][b],true);}}})();var Hash=new Native({name:"Hash",initialize:function(a){if($type(a)=="hash"){a=$unlink(a.getClean());
}for(var b in a){this[b]=a[b];}return this;}});Hash.implement({forEach:function(b,c){for(var a in this){if(this.hasOwnProperty(a)){b.call(c,this[a],a,this);
}}},getClean:function(){var b={};for(var a in this){if(this.hasOwnProperty(a)){b[a]=this[a];}}return b;},getLength:function(){var b=0;for(var a in this){if(this.hasOwnProperty(a)){b++;
}}return b;}});Hash.alias("forEach","each");Array.implement({forEach:function(c,d){for(var b=0,a=this.length;b<a;b++){c.call(d,this[b],b,this);}}});Array.alias("forEach","each");
function $A(b){if(b.item){var a=b.length,c=new Array(a);while(a--){c[a]=b[a];}return c;}return Array.prototype.slice.call(b);}function $arguments(a){return function(){return arguments[a];
};}function $chk(a){return !!(a||a===0);}function $clear(a){clearTimeout(a);clearInterval(a);return null;}function $defined(a){return(a!=undefined);}function $each(c,b,d){var a=$type(c);
((a=="arguments"||a=="collection"||a=="array")?Array:Hash).each(c,b,d);}function $empty(){}function $extend(c,a){for(var b in (a||{})){c[b]=a[b];}return c;
}function $H(a){return new Hash(a);}function $lambda(a){return($type(a)=="function")?a:function(){return a;};}function $merge(){var a=Array.slice(arguments);
a.unshift({});return $mixin.apply(null,a);}function $mixin(e){for(var d=1,a=arguments.length;d<a;d++){var b=arguments[d];if($type(b)!="object"){continue;
}for(var c in b){var g=b[c],f=e[c];e[c]=(f&&$type(g)=="object"&&$type(f)=="object")?$mixin(f,g):$unlink(g);}}return e;}function $pick(){for(var b=0,a=arguments.length;
b<a;b++){if(arguments[b]!=undefined){return arguments[b];}}return null;}function $random(b,a){return Math.floor(Math.random()*(a-b+1)+b);}function $splat(b){var a=$type(b);
return(a)?((a!="array"&&a!="arguments")?[b]:b):[];}var $time=Date.now||function(){return +new Date;};function $try(){for(var b=0,a=arguments.length;b<a;
b++){try{return arguments[b]();}catch(c){}}return null;}function $type(a){if(a==undefined){return false;}if(a.$family){return(a.$family.name=="number"&&!isFinite(a))?false:a.$family.name;
}if(a.nodeName){switch(a.nodeType){case 1:return"element";case 3:return(/\S/).test(a.nodeValue)?"textnode":"whitespace";}}else{if(typeof a.length=="number"){if(a.callee){return"arguments";
}else{if(a.item){return"collection";}}}}return typeof a;}function $unlink(c){var b;switch($type(c)){case"object":b={};for(var e in c){b[e]=$unlink(c[e]);
}break;case"hash":b=new Hash(c);break;case"array":b=[];for(var d=0,a=c.length;d<a;d++){b[d]=$unlink(c[d]);}break;default:return c;}return b;}var Browser=$merge({Engine:{name:"unknown",version:0},Platform:{name:(window.orientation!=undefined)?"ipod":(navigator.platform.match(/mac|win|linux/i)||["other"])[0].toLowerCase()},Features:{xpath:!!(document.evaluate),air:!!(window.runtime),query:!!(document.querySelector)},Plugins:{},Engines:{presto:function(){return(!window.opera)?false:((arguments.callee.caller)?960:((document.getElementsByClassName)?950:925));
},trident:function(){return(!window.ActiveXObject)?false:((window.XMLHttpRequest)?((document.querySelectorAll)?6:5):4);},webkit:function(){return(navigator.taintEnabled)?false:((Browser.Features.xpath)?((Browser.Features.query)?525:420):419);
},gecko:function(){return(!document.getBoxObjectFor&&window.mozInnerScreenX==null)?false:((document.getElementsByClassName)?19:18);}}},Browser||{});Browser.Platform[Browser.Platform.name]=true;
Browser.detect=function(){for(var b in this.Engines){var a=this.Engines[b]();if(a){this.Engine={name:b,version:a};this.Engine[b]=this.Engine[b+a]=true;
break;}}return{name:b,version:a};};Browser.detect();Browser.Request=function(){return $try(function(){return new XMLHttpRequest();},function(){return new ActiveXObject("MSXML2.XMLHTTP");
},function(){return new ActiveXObject("Microsoft.XMLHTTP");});};Browser.Features.xhr=!!(Browser.Request());Browser.Plugins.Flash=(function(){var a=($try(function(){return navigator.plugins["Shockwave Flash"].description;
},function(){return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version");})||"0 r0").match(/\d+/g);return{version:parseInt(a[0]||0+"."+a[1],10)||0,build:parseInt(a[2],10)||0};
})();function $exec(b){if(!b){return b;}if(window.execScript){window.execScript(b);}else{var a=document.createElement("script");a.setAttribute("type","text/javascript");
a[(Browser.Engine.webkit&&Browser.Engine.version<420)?"innerText":"text"]=b;document.head.appendChild(a);document.head.removeChild(a);}return b;}Native.UID=1;
var $uid=(Browser.Engine.trident)?function(a){return(a.uid||(a.uid=[Native.UID++]))[0];}:function(a){return a.uid||(a.uid=Native.UID++);};var Window=new Native({name:"Window",legacy:(Browser.Engine.trident)?null:window.Window,initialize:function(a){$uid(a);
if(!a.Element){a.Element=$empty;if(Browser.Engine.webkit){a.document.createElement("iframe");}a.Element.prototype=(Browser.Engine.webkit)?window["[[DOMElement.prototype]]"]:{};
}a.document.window=a;return $extend(a,Window.Prototype);},afterImplement:function(b,a){window[b]=Window.Prototype[b]=a;}});Window.Prototype={$family:{name:"window"}};
new Window(window);var Document=new Native({name:"Document",legacy:(Browser.Engine.trident)?null:window.Document,initialize:function(a){$uid(a);a.head=a.getElementsByTagName("head")[0];
a.html=a.getElementsByTagName("html")[0];if(Browser.Engine.trident&&Browser.Engine.version<=4){$try(function(){a.execCommand("BackgroundImageCache",false,true);
});}if(Browser.Engine.trident){a.window.attachEvent("onunload",function(){a.window.detachEvent("onunload",arguments.callee);a.head=a.html=a.window=null;
});}return $extend(a,Document.Prototype);},afterImplement:function(b,a){document[b]=Document.Prototype[b]=a;}});Document.Prototype={$family:{name:"document"}};
new Document(document);Array.implement({every:function(c,d){for(var b=0,a=this.length;b<a;b++){if(!c.call(d,this[b],b,this)){return false;}}return true;
},filter:function(d,e){var c=[];for(var b=0,a=this.length;b<a;b++){if(d.call(e,this[b],b,this)){c.push(this[b]);}}return c;},clean:function(){return this.filter($defined);
},indexOf:function(c,d){var a=this.length;for(var b=(d<0)?Math.max(0,a+d):d||0;b<a;b++){if(this[b]===c){return b;}}return -1;},map:function(d,e){var c=[];
for(var b=0,a=this.length;b<a;b++){c[b]=d.call(e,this[b],b,this);}return c;},some:function(c,d){for(var b=0,a=this.length;b<a;b++){if(c.call(d,this[b],b,this)){return true;
}}return false;},associate:function(c){var d={},b=Math.min(this.length,c.length);for(var a=0;a<b;a++){d[c[a]]=this[a];}return d;},link:function(c){var a={};
for(var e=0,b=this.length;e<b;e++){for(var d in c){if(c[d](this[e])){a[d]=this[e];delete c[d];break;}}}return a;},contains:function(a,b){return this.indexOf(a,b)!=-1;
},extend:function(c){for(var b=0,a=c.length;b<a;b++){this.push(c[b]);}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(a){if(!this.contains(a)){this.push(a);}return this;},combine:function(c){for(var b=0,a=c.length;b<a;b++){this.include(c[b]);}return this;
},erase:function(b){for(var a=this.length;a--;a){if(this[a]===b){this.splice(a,1);}}return this;},empty:function(){this.length=0;return this;},flatten:function(){var d=[];
for(var b=0,a=this.length;b<a;b++){var c=$type(this[b]);if(!c){continue;}d=d.concat((c=="array"||c=="collection"||c=="arguments")?Array.flatten(this[b]):this[b]);
}return d;},hexToRgb:function(b){if(this.length!=3){return null;}var a=this.map(function(c){if(c.length==1){c+=c;}return c.toInt(16);});return(b)?a:"rgb("+a+")";
},rgbToHex:function(d){if(this.length<3){return null;}if(this.length==4&&this[3]==0&&!d){return"transparent";}var b=[];for(var a=0;a<3;a++){var c=(this[a]-0).toString(16);
b.push((c.length==1)?"0"+c:c);}return(d)?b:"#"+b.join("");}});Function.implement({extend:function(a){for(var b in a){this[b]=a[b];}return this;},create:function(b){var a=this;
b=b||{};return function(d){var c=b.arguments;c=(c!=undefined)?$splat(c):Array.slice(arguments,(b.event)?1:0);if(b.event){c=[d||window.event].extend(c);
}var e=function(){return a.apply(b.bind||null,c);};if(b.delay){return setTimeout(e,b.delay);}if(b.periodical){return setInterval(e,b.periodical);}if(b.attempt){return $try(e);
}return e();};},run:function(a,b){return this.apply(b,$splat(a));},pass:function(a,b){return this.create({bind:b,arguments:a});},bind:function(b,a){return this.create({bind:b,arguments:a});
},bindWithEvent:function(b,a){return this.create({bind:b,arguments:a,event:true});},attempt:function(a,b){return this.create({bind:b,arguments:a,attempt:true})();
},delay:function(b,c,a){return this.create({bind:c,arguments:a,delay:b})();},periodical:function(c,b,a){return this.create({bind:b,arguments:a,periodical:c})();
}});Number.implement({limit:function(b,a){return Math.min(a,Math.max(b,this));},round:function(a){a=Math.pow(10,a||0);return Math.round(this*a)/a;},times:function(b,c){for(var a=0;
a<this;a++){b.call(c,a,this);}},toFloat:function(){return parseFloat(this);},toInt:function(a){return parseInt(this,a||10);}});Number.alias("times","each");
(function(b){var a={};b.each(function(c){if(!Number[c]){a[c]=function(){return Math[c].apply(null,[this].concat($A(arguments)));};}});Number.implement(a);
})(["abs","acos","asin","atan","atan2","ceil","cos","exp","floor","log","max","min","pow","sin","sqrt","tan"]);String.implement({test:function(a,b){return((typeof a=="string")?new RegExp(a,b):a).test(this);
},contains:function(a,b){return(b)?(b+this+b).indexOf(b+a+b)>-1:this.indexOf(a)>-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(a){return a.charAt(1).toUpperCase();});},hyphenate:function(){return this.replace(/[A-Z]/g,function(a){return("-"+a.charAt(0).toLowerCase());
});},capitalize:function(){return this.replace(/\b[a-z]/g,function(a){return a.toUpperCase();});},escapeRegExp:function(){return this.replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1");
},toInt:function(a){return parseInt(this,a||10);},toFloat:function(){return parseFloat(this);},hexToRgb:function(b){var a=this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
return(a)?a.slice(1).hexToRgb(b):null;},rgbToHex:function(b){var a=this.match(/\d{1,3}/g);return(a)?a.rgbToHex(b):null;},stripScripts:function(b){var a="";
var c=this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi,function(){a+=arguments[1]+"\n";return"";});if(b===true){$exec(a);}else{if($type(b)=="function"){b(a,c);
}}return c;},substitute:function(a,b){return this.replace(b||(/\\?\{([^{}]+)\}/g),function(d,c){if(d.charAt(0)=="\\"){return d.slice(1);}return(a[c]!=undefined)?a[c]:"";
});}});Hash.implement({has:Object.prototype.hasOwnProperty,keyOf:function(b){for(var a in this){if(this.hasOwnProperty(a)&&this[a]===b){return a;}}return null;
},hasValue:function(a){return(Hash.keyOf(this,a)!==null);},extend:function(a){Hash.each(a||{},function(c,b){Hash.set(this,b,c);},this);return this;},combine:function(a){Hash.each(a||{},function(c,b){Hash.include(this,b,c);
},this);return this;},erase:function(a){if(this.hasOwnProperty(a)){delete this[a];}return this;},get:function(a){return(this.hasOwnProperty(a))?this[a]:null;
},set:function(a,b){if(!this[a]||this.hasOwnProperty(a)){this[a]=b;}return this;},empty:function(){Hash.each(this,function(b,a){delete this[a];},this);
return this;},include:function(a,b){if(this[a]==undefined){this[a]=b;}return this;},map:function(b,c){var a=new Hash;Hash.each(this,function(e,d){a.set(d,b.call(c,e,d,this));
},this);return a;},filter:function(b,c){var a=new Hash;Hash.each(this,function(e,d){if(b.call(c,e,d,this)){a.set(d,e);}},this);return a;},every:function(b,c){for(var a in this){if(this.hasOwnProperty(a)&&!b.call(c,this[a],a)){return false;
}}return true;},some:function(b,c){for(var a in this){if(this.hasOwnProperty(a)&&b.call(c,this[a],a)){return true;}}return false;},getKeys:function(){var a=[];
Hash.each(this,function(c,b){a.push(b);});return a;},getValues:function(){var a=[];Hash.each(this,function(b){a.push(b);});return a;},toQueryString:function(a){var b=[];
Hash.each(this,function(f,e){if(a){e=a+"["+e+"]";}var d;switch($type(f)){case"object":d=Hash.toQueryString(f,e);break;case"array":var c={};f.each(function(h,g){c[g]=h;
});d=Hash.toQueryString(c,e);break;default:d=e+"="+encodeURIComponent(f);}if(f!=undefined){b.push(d);}});return b.join("&");}});Hash.alias({keyOf:"indexOf",hasValue:"contains"});
var Event=new Native({name:"Event",initialize:function(a,f){f=f||window;var k=f.document;a=a||f.event;if(a.$extended){return a;}this.$extended=true;var j=a.type;
var g=a.target||a.srcElement;while(g&&g.nodeType==3){g=g.parentNode;}if(j.test(/key/)){var b=a.which||a.keyCode;var m=Event.Keys.keyOf(b);if(j=="keydown"){var d=b-111;
if(d>0&&d<13){m="f"+d;}}m=m||String.fromCharCode(b).toLowerCase();}else{if(j.match(/(click|mouse|menu)/i)){k=(!k.compatMode||k.compatMode=="CSS1Compat")?k.html:k.body;
var i={x:a.pageX||a.clientX+k.scrollLeft,y:a.pageY||a.clientY+k.scrollTop};var c={x:(a.pageX)?a.pageX-f.pageXOffset:a.clientX,y:(a.pageY)?a.pageY-f.pageYOffset:a.clientY};
if(j.match(/DOMMouseScroll|mousewheel/)){var h=(a.wheelDelta)?a.wheelDelta/120:-(a.detail||0)/3;}var e=(a.which==3)||(a.button==2);var l=null;if(j.match(/over|out/)){switch(j){case"mouseover":l=a.relatedTarget||a.fromElement;
break;case"mouseout":l=a.relatedTarget||a.toElement;}if(!(function(){while(l&&l.nodeType==3){l=l.parentNode;}return true;}).create({attempt:Browser.Engine.gecko})()){l=false;
}}}}return $extend(this,{event:a,type:j,page:i,client:c,rightClick:e,wheel:h,relatedTarget:l,target:g,code:b,key:m,shift:a.shiftKey,control:a.ctrlKey,alt:a.altKey,meta:a.metaKey});
}});Event.Keys=new Hash({enter:13,up:38,down:40,left:37,right:39,esc:27,space:32,backspace:8,tab:9,"delete":46});Event.implement({stop:function(){return this.stopPropagation().preventDefault();
},stopPropagation:function(){if(this.event.stopPropagation){this.event.stopPropagation();}else{this.event.cancelBubble=true;}return this;},preventDefault:function(){if(this.event.preventDefault){this.event.preventDefault();
}else{this.event.returnValue=false;}return this;}});function Class(b){if(b instanceof Function){b={initialize:b};}var a=function(){Object.reset(this);if(a._prototyping){return this;
}this._current=$empty;var c=(this.initialize)?this.initialize.apply(this,arguments):this;delete this._current;delete this.caller;return c;}.extend(this);
a.implement(b);a.constructor=Class;a.prototype.constructor=a;return a;}Function.prototype.protect=function(){this._protected=true;return this;};Object.reset=function(a,c){if(c==null){for(var e in a){Object.reset(a,e);
}return a;}delete a[c];switch($type(a[c])){case"object":var d=function(){};d.prototype=a[c];var b=new d;a[c]=Object.reset(b);break;case"array":a[c]=$unlink(a[c]);
break;}return a;};new Native({name:"Class",initialize:Class}).extend({instantiate:function(b){b._prototyping=true;var a=new b;delete b._prototyping;return a;
},wrap:function(a,b,c){if(c._origin){c=c._origin;}return function(){if(c._protected&&this._current==null){throw new Error('The method "'+b+'" cannot be called.');
}var e=this.caller,f=this._current;this.caller=f;this._current=arguments.callee;var d=c.apply(this,arguments);this._current=f;this.caller=e;return d;}.extend({_owner:a,_origin:c,_name:b});
}});Class.implement({implement:function(a,d){if($type(a)=="object"){for(var e in a){this.implement(e,a[e]);}return this;}var f=Class.Mutators[a];if(f){d=f.call(this,d);
if(d==null){return this;}}var c=this.prototype;switch($type(d)){case"function":if(d._hidden){return this;}c[a]=Class.wrap(this,a,d);break;case"object":var b=c[a];
if($type(b)=="object"){$mixin(b,d);}else{c[a]=$unlink(d);}break;case"array":c[a]=$unlink(d);break;default:c[a]=d;}return this;}});Class.Mutators={Extends:function(a){this.parent=a;
this.prototype=Class.instantiate(a);this.implement("parent",function(){var b=this.caller._name,c=this.caller._owner.parent.prototype[b];if(!c){throw new Error('The method "'+b+'" has no parent.');
}return c.apply(this,arguments);}.protect());},Implements:function(a){$splat(a).each(function(b){if(b instanceof Function){b=Class.instantiate(b);}this.implement(b);
},this);}};var Chain=new Class({$chain:[],chain:function(){this.$chain.extend(Array.flatten(arguments));return this;},callChain:function(){return(this.$chain.length)?this.$chain.shift().apply(this,arguments):false;
},clearChain:function(){this.$chain.empty();return this;}});var Events=new Class({$events:{},addEvent:function(c,b,a){c=Events.removeOn(c);if(b!=$empty){this.$events[c]=this.$events[c]||[];
this.$events[c].include(b);if(a){b.internal=true;}}return this;},addEvents:function(a){for(var b in a){this.addEvent(b,a[b]);}return this;},fireEvent:function(c,b,a){c=Events.removeOn(c);
if(!this.$events||!this.$events[c]){return this;}this.$events[c].each(function(d){d.create({bind:this,delay:a,"arguments":b})();},this);return this;},removeEvent:function(b,a){b=Events.removeOn(b);
if(!this.$events[b]){return this;}if(!a.internal){this.$events[b].erase(a);}return this;},removeEvents:function(c){var d;if($type(c)=="object"){for(d in c){this.removeEvent(d,c[d]);
}return this;}if(c){c=Events.removeOn(c);}for(d in this.$events){if(c&&c!=d){continue;}var b=this.$events[d];for(var a=b.length;a--;a){this.removeEvent(d,b[a]);
}}return this;}});Events.removeOn=function(a){return a.replace(/^on([A-Z])/,function(b,c){return c.toLowerCase();});};var Options=new Class({setOptions:function(){this.options=$merge.run([this.options].extend(arguments));
if(!this.addEvent){return this;}for(var a in this.options){if($type(this.options[a])!="function"||!(/^on[A-Z]/).test(a)){continue;}this.addEvent(a,this.options[a]);
delete this.options[a];}return this;}});var Element=new Native({name:"Element",legacy:window.Element,initialize:function(a,b){var c=Element.Constructors.get(a);
if(c){return c(b);}if(typeof a=="string"){return document.newElement(a,b);}return document.id(a).set(b);},afterImplement:function(a,b){Element.Prototype[a]=b;
if(Array[a]){return;}Elements.implement(a,function(){var c=[],g=true;for(var e=0,d=this.length;e<d;e++){var f=this[e][a].apply(this[e],arguments);c.push(f);
if(g){g=($type(f)=="element");}}return(g)?new Elements(c):c;});}});Element.Prototype={$family:{name:"element"}};Element.Constructors=new Hash;var IFrame=new Native({name:"IFrame",generics:false,initialize:function(){var f=Array.link(arguments,{properties:Object.type,iframe:$defined});
var d=f.properties||{};var c=document.id(f.iframe);var e=d.onload||$empty;delete d.onload;d.id=d.name=$pick(d.id,d.name,c?(c.id||c.name):"IFrame_"+$time());
c=new Element(c||"iframe",d);var b=function(){var g=$try(function(){return c.contentWindow.location.host;});if(!g||g==window.location.host){var h=new Window(c.contentWindow);
new Document(c.contentWindow.document);$extend(h.Element.prototype,Element.Prototype);}e.call(c.contentWindow,c.contentWindow.document);};var a=$try(function(){return c.contentWindow;
});((a&&a.document.body)||window.frames[d.id])?b():c.addListener("load",b);return c;}});var Elements=new Native({initialize:function(f,b){b=$extend({ddup:true,cash:true},b);
f=f||[];if(b.ddup||b.cash){var g={},e=[];for(var c=0,a=f.length;c<a;c++){var d=document.id(f[c],!b.cash);if(b.ddup){if(g[d.uid]){continue;}g[d.uid]=true;
}if(d){e.push(d);}}f=e;}return(b.cash)?$extend(f,this):f;}});Elements.implement({filter:function(a,b){if(!a){return this;}return new Elements(Array.filter(this,(typeof a=="string")?function(c){return c.match(a);
}:a,b));}});Document.implement({newElement:function(a,b){if(Browser.Engine.trident&&b){["name","type","checked"].each(function(c){if(!b[c]){return;}a+=" "+c+'="'+b[c]+'"';
if(c!="checked"){delete b[c];}});a="<"+a+">";}return document.id(this.createElement(a)).set(b);},newTextNode:function(a){return this.createTextNode(a);
},getDocument:function(){return this;},getWindow:function(){return this.window;},id:(function(){var a={string:function(d,c,b){d=b.getElementById(d);return(d)?a.element(d,c):null;
},element:function(b,e){$uid(b);if(!e&&!b.$family&&!(/^object|embed$/i).test(b.tagName)){var c=Element.Prototype;for(var d in c){b[d]=c[d];}}return b;},object:function(c,d,b){if(c.toElement){return a.element(c.toElement(b),d);
}return null;}};a.textnode=a.whitespace=a.window=a.document=$arguments(0);return function(c,e,d){if(c&&c.$family&&c.uid){return c;}var b=$type(c);return(a[b])?a[b](c,e,d||document):null;
};})()});if(window.$==null){Window.implement({$:function(a,b){return document.id(a,b,this.document);}});}Window.implement({$$:function(a){if(arguments.length==1&&typeof a=="string"){return this.document.getElements(a);
}var f=[];var c=Array.flatten(arguments);for(var d=0,b=c.length;d<b;d++){var e=c[d];switch($type(e)){case"element":f.push(e);break;case"string":f.extend(this.document.getElements(e,true));
}}return new Elements(f);},getDocument:function(){return this.document;},getWindow:function(){return this;}});Native.implement([Element,Document],{getElement:function(a,b){return document.id(this.getElements(a,true)[0]||null,b);
},getElements:function(a,d){a=a.split(",");var c=[];var b=(a.length>1);a.each(function(e){var f=this.getElementsByTagName(e.trim());(b)?c.extend(f):c=f;
},this);return new Elements(c,{ddup:b,cash:!d});}});(function(){var h={},f={};var i={input:"checked",option:"selected",textarea:(Browser.Engine.webkit&&Browser.Engine.version<420)?"innerHTML":"value"};
var c=function(l){return(f[l]||(f[l]={}));};var g=function(n,l){if(!n){return;}var m=n.uid;if(Browser.Engine.trident){if(n.clearAttributes){var q=l&&n.cloneNode(false);
n.clearAttributes();if(q){n.mergeAttributes(q);}}else{if(n.removeEvents){n.removeEvents();}}if((/object/i).test(n.tagName)){for(var o in n){if(typeof n[o]=="function"){n[o]=$empty;
}}Element.dispose(n);}}if(!m){return;}h[m]=f[m]=null;};var d=function(){Hash.each(h,g);if(Browser.Engine.trident){$A(document.getElementsByTagName("object")).each(g);
}if(window.CollectGarbage){CollectGarbage();}h=f=null;};var j=function(n,l,s,m,p,r){var o=n[s||l];var q=[];while(o){if(o.nodeType==1&&(!m||Element.match(o,m))){if(!p){return document.id(o,r);
}q.push(o);}o=o[l];}return(p)?new Elements(q,{ddup:false,cash:!r}):null;};var e={html:"innerHTML","class":"className","for":"htmlFor",defaultValue:"defaultValue",text:(Browser.Engine.trident||(Browser.Engine.webkit&&Browser.Engine.version<420))?"innerText":"textContent"};
var b=["compact","nowrap","ismap","declare","noshade","checked","disabled","readonly","multiple","selected","noresize","defer"];var k=["value","type","defaultValue","accessKey","cellPadding","cellSpacing","colSpan","frameBorder","maxLength","readOnly","rowSpan","tabIndex","useMap"];
b=b.associate(b);Hash.extend(e,b);Hash.extend(e,k.associate(k.map(String.toLowerCase)));var a={before:function(m,l){if(l.parentNode){l.parentNode.insertBefore(m,l);
}},after:function(m,l){if(!l.parentNode){return;}var n=l.nextSibling;(n)?l.parentNode.insertBefore(m,n):l.parentNode.appendChild(m);},bottom:function(m,l){l.appendChild(m);
},top:function(m,l){var n=l.firstChild;(n)?l.insertBefore(m,n):l.appendChild(m);}};a.inside=a.bottom;Hash.each(a,function(l,m){m=m.capitalize();Element.implement("inject"+m,function(n){l(this,document.id(n,true));
return this;});Element.implement("grab"+m,function(n){l(document.id(n,true),this);return this;});});Element.implement({set:function(o,m){switch($type(o)){case"object":for(var n in o){this.set(n,o[n]);
}break;case"string":var l=Element.Properties.get(o);(l&&l.set)?l.set.apply(this,Array.slice(arguments,1)):this.setProperty(o,m);}return this;},get:function(m){var l=Element.Properties.get(m);
return(l&&l.get)?l.get.apply(this,Array.slice(arguments,1)):this.getProperty(m);},erase:function(m){var l=Element.Properties.get(m);(l&&l.erase)?l.erase.apply(this):this.removeProperty(m);
return this;},setProperty:function(m,n){var l=e[m];if(n==undefined){return this.removeProperty(m);}if(l&&b[m]){n=!!n;}(l)?this[l]=n:this.setAttribute(m,""+n);
return this;},setProperties:function(l){for(var m in l){this.setProperty(m,l[m]);}return this;},getProperty:function(m){var l=e[m];var n=(l)?this[l]:this.getAttribute(m,2);
return(b[m])?!!n:(l)?n:n||null;},getProperties:function(){var l=$A(arguments);return l.map(this.getProperty,this).associate(l);},removeProperty:function(m){var l=e[m];
(l)?this[l]=(l&&b[m])?false:"":this.removeAttribute(m);return this;},removeProperties:function(){Array.each(arguments,this.removeProperty,this);return this;
},hasClass:function(l){return this.className.contains(l," ");},addClass:function(l){if(!this.hasClass(l)){this.className=(this.className+" "+l).clean();
}return this;},removeClass:function(l){this.className=this.className.replace(new RegExp("(^|\\s)"+l+"(?:\\s|$)"),"$1");return this;},toggleClass:function(l){return this.hasClass(l)?this.removeClass(l):this.addClass(l);
},adopt:function(){Array.flatten(arguments).each(function(l){l=document.id(l,true);if(l){this.appendChild(l);}},this);return this;},appendText:function(m,l){return this.grab(this.getDocument().newTextNode(m),l);
},grab:function(m,l){a[l||"bottom"](document.id(m,true),this);return this;},inject:function(m,l){a[l||"bottom"](this,document.id(m,true));return this;},replaces:function(l){l=document.id(l,true);
l.parentNode.replaceChild(this,l);return this;},wraps:function(m,l){m=document.id(m,true);return this.replaces(m).grab(m,l);},getPrevious:function(l,m){return j(this,"previousSibling",null,l,false,m);
},getAllPrevious:function(l,m){return j(this,"previousSibling",null,l,true,m);},getNext:function(l,m){return j(this,"nextSibling",null,l,false,m);},getAllNext:function(l,m){return j(this,"nextSibling",null,l,true,m);
},getFirst:function(l,m){return j(this,"nextSibling","firstChild",l,false,m);},getLast:function(l,m){return j(this,"previousSibling","lastChild",l,false,m);
},getParent:function(l,m){return j(this,"parentNode",null,l,false,m);},getParents:function(l,m){return j(this,"parentNode",null,l,true,m);},getSiblings:function(l,m){return this.getParent().getChildren(l,m).erase(this);
},getChildren:function(l,m){return j(this,"nextSibling","firstChild",l,true,m);},getWindow:function(){return this.ownerDocument.window;},getDocument:function(){return this.ownerDocument;
},getElementById:function(o,n){var m=this.ownerDocument.getElementById(o);if(!m){return null;}for(var l=m.parentNode;l!=this;l=l.parentNode){if(!l){return null;
}}return document.id(m,n);},getSelected:function(){return new Elements($A(this.options).filter(function(l){return l.selected;}));},getComputedStyle:function(m){if(this.currentStyle){return this.currentStyle[m.camelCase()];
}var l=this.getDocument().defaultView.getComputedStyle(this,null);return(l)?l.getPropertyValue([m.hyphenate()]):null;},toQueryString:function(){var l=[];
this.getElements("input, select, textarea",true).each(function(m){if(!m.name||m.disabled||m.type=="submit"||m.type=="reset"||m.type=="file"){return;}var n=(m.tagName.toLowerCase()=="select")?Element.getSelected(m).map(function(o){return o.value;
}):((m.type=="radio"||m.type=="checkbox")&&!m.checked)?null:m.value;$splat(n).each(function(o){if(typeof o!="undefined"){l.push(m.name+"="+encodeURIComponent(o));
}});});return l.join("&");},clone:function(o,l){o=o!==false;var r=this.cloneNode(o);var n=function(v,u){if(!l){v.removeAttribute("id");}if(Browser.Engine.trident){v.clearAttributes();
v.mergeAttributes(u);v.removeAttribute("uid");if(v.options){var w=v.options,s=u.options;for(var t=w.length;t--;){w[t].selected=s[t].selected;}}}var x=i[u.tagName.toLowerCase()];
if(x&&u[x]){v[x]=u[x];}};if(o){var p=r.getElementsByTagName("*"),q=this.getElementsByTagName("*");for(var m=p.length;m--;){n(p[m],q[m]);}}n(r,this);return document.id(r);
},destroy:function(){Element.empty(this);Element.dispose(this);g(this,true);return null;},empty:function(){$A(this.childNodes).each(function(l){Element.destroy(l);
});return this;},dispose:function(){return(this.parentNode)?this.parentNode.removeChild(this):this;},hasChild:function(l){l=document.id(l,true);if(!l){return false;
}if(Browser.Engine.webkit&&Browser.Engine.version<420){return $A(this.getElementsByTagName(l.tagName)).contains(l);}return(this.contains)?(this!=l&&this.contains(l)):!!(this.compareDocumentPosition(l)&16);
},match:function(l){return(!l||(l==this)||(Element.get(this,"tag")==l));}});Native.implement([Element,Window,Document],{addListener:function(o,n){if(o=="unload"){var l=n,m=this;
n=function(){m.removeListener("unload",n);l();};}else{h[this.uid]=this;}if(this.addEventListener){this.addEventListener(o,n,false);}else{this.attachEvent("on"+o,n);
}return this;},removeListener:function(m,l){if(this.removeEventListener){this.removeEventListener(m,l,false);}else{this.detachEvent("on"+m,l);}return this;
},retrieve:function(m,l){var o=c(this.uid),n=o[m];if(l!=undefined&&n==undefined){n=o[m]=l;}return $pick(n);},store:function(m,l){var n=c(this.uid);n[m]=l;
return this;},eliminate:function(l){var m=c(this.uid);delete m[l];return this;}});window.addListener("unload",d);})();Element.Properties=new Hash;Element.Properties.style={set:function(a){this.style.cssText=a;
},get:function(){return this.style.cssText;},erase:function(){this.style.cssText="";}};Element.Properties.tag={get:function(){return this.tagName.toLowerCase();
}};Element.Properties.html=(function(){var c=document.createElement("div");var a={table:[1,"<table>","</table>"],select:[1,"<select>","</select>"],tbody:[2,"<table><tbody>","</tbody></table>"],tr:[3,"<table><tbody><tr>","</tr></tbody></table>"]};
a.thead=a.tfoot=a.tbody;var b={set:function(){var e=Array.flatten(arguments).join("");var f=Browser.Engine.trident&&a[this.get("tag")];if(f){var g=c;g.innerHTML=f[1]+e+f[2];
for(var d=f[0];d--;){g=g.firstChild;}this.empty().adopt(g.childNodes);}else{this.innerHTML=e;}}};b.erase=b.set;return b;})();if(Browser.Engine.webkit&&Browser.Engine.version<420){Element.Properties.text={get:function(){if(this.innerText){return this.innerText;
}var a=this.ownerDocument.newElement("div",{html:this.innerHTML}).inject(this.ownerDocument.body);var b=a.innerText;a.destroy();return b;}};}Element.Properties.events={set:function(a){this.addEvents(a);
}};Native.implement([Element,Window,Document],{addEvent:function(e,g){var h=this.retrieve("events",{});h[e]=h[e]||{keys:[],values:[]};if(h[e].keys.contains(g)){return this;
}h[e].keys.push(g);var f=e,a=Element.Events.get(e),c=g,i=this;if(a){if(a.onAdd){a.onAdd.call(this,g);}if(a.condition){c=function(j){if(a.condition.call(this,j)){return g.call(this,j);
}return true;};}f=a.base||f;}var d=function(){return g.call(i);};var b=Element.NativeEvents[f];if(b){if(b==2){d=function(j){j=new Event(j,i.getWindow());
if(c.call(i,j)===false){j.stop();}};}this.addListener(f,d);}h[e].values.push(d);return this;},removeEvent:function(c,b){var a=this.retrieve("events");if(!a||!a[c]){return this;
}var f=a[c].keys.indexOf(b);if(f==-1){return this;}a[c].keys.splice(f,1);var e=a[c].values.splice(f,1)[0];var d=Element.Events.get(c);if(d){if(d.onRemove){d.onRemove.call(this,b);
}c=d.base||c;}return(Element.NativeEvents[c])?this.removeListener(c,e):this;},addEvents:function(a){for(var b in a){this.addEvent(b,a[b]);}return this;
},removeEvents:function(a){var c;if($type(a)=="object"){for(c in a){this.removeEvent(c,a[c]);}return this;}var b=this.retrieve("events");if(!b){return this;
}if(!a){for(c in b){this.removeEvents(c);}this.eliminate("events");}else{if(b[a]){while(b[a].keys[0]){this.removeEvent(a,b[a].keys[0]);}b[a]=null;}}return this;
},fireEvent:function(d,b,a){var c=this.retrieve("events");if(!c||!c[d]){return this;}c[d].keys.each(function(e){e.create({bind:this,delay:a,"arguments":b})();
},this);return this;},cloneEvents:function(d,a){d=document.id(d);var c=d.retrieve("events");if(!c){return this;}if(!a){for(var b in c){this.cloneEvents(d,b);
}}else{if(c[a]){c[a].keys.each(function(e){this.addEvent(a,e);},this);}}return this;}});Element.NativeEvents={click:2,dblclick:2,mouseup:2,mousedown:2,contextmenu:2,mousewheel:2,DOMMouseScroll:2,mouseover:2,mouseout:2,mousemove:2,selectstart:2,selectend:2,keydown:2,keypress:2,keyup:2,focus:2,blur:2,change:2,reset:2,select:2,submit:2,load:1,unload:1,beforeunload:2,resize:1,move:1,DOMContentLoaded:1,readystatechange:1,error:1,abort:1,scroll:1};
(function(){var a=function(b){var c=b.relatedTarget;if(c==undefined){return true;}if(c===false){return false;}return($type(this)!="document"&&c!=this&&c.prefix!="xul"&&!this.hasChild(c));
};Element.Events=new Hash({mouseenter:{base:"mouseover",condition:a},mouseleave:{base:"mouseout",condition:a},mousewheel:{base:(Browser.Engine.gecko)?"DOMMouseScroll":"mousewheel"}});
})();Element.Properties.styles={set:function(a){this.setStyles(a);}};Element.Properties.opacity={set:function(a,b){if(!b){if(a==0){if(this.style.visibility!="hidden"){this.style.visibility="hidden";
}}else{if(this.style.visibility!="visible"){this.style.visibility="visible";}}}if(!this.currentStyle||!this.currentStyle.hasLayout){this.style.zoom=1;}if(Browser.Engine.trident){this.style.filter=(a==1)?"":"alpha(opacity="+a*100+")";
}this.style.opacity=a;this.store("opacity",a);},get:function(){return this.retrieve("opacity",1);}};Element.implement({setOpacity:function(a){return this.set("opacity",a,true);
},getOpacity:function(){return this.get("opacity");},setStyle:function(b,a){switch(b){case"opacity":return this.set("opacity",parseFloat(a));case"float":b=(Browser.Engine.trident)?"styleFloat":"cssFloat";
}b=b.camelCase();if($type(a)!="string"){var c=(Element.Styles.get(b)||"@").split(" ");a=$splat(a).map(function(e,d){if(!c[d]){return"";}return($type(e)=="number")?c[d].replace("@",Math.round(e)):e;
}).join(" ");}else{if(a==String(Number(a))){a=Math.round(a);}}this.style[b]=a;return this;},getStyle:function(g){switch(g){case"opacity":return this.get("opacity");
case"float":g=(Browser.Engine.trident)?"styleFloat":"cssFloat";}g=g.camelCase();var a=this.style[g];if(!$chk(a)){a=[];for(var f in Element.ShortStyles){if(g!=f){continue;
}for(var e in Element.ShortStyles[f]){a.push(this.getStyle(e));}return a.join(" ");}a=this.getComputedStyle(g);}if(a){a=String(a);var c=a.match(/rgba?\([\d\s,]+\)/);
if(c){a=a.replace(c[0],c[0].rgbToHex());}}if(Browser.Engine.presto||(Browser.Engine.trident&&!$chk(parseInt(a,10)))){if(g.test(/^(height|width)$/)){var b=(g=="width")?["left","right"]:["top","bottom"],d=0;
b.each(function(h){d+=this.getStyle("border-"+h+"-width").toInt()+this.getStyle("padding-"+h).toInt();},this);return this["offset"+g.capitalize()]-d+"px";
}if((Browser.Engine.presto)&&String(a).test("px")){return a;}if(g.test(/(border(.+)Width|margin|padding)/)){return"0px";}}return a;},setStyles:function(b){for(var a in b){this.setStyle(a,b[a]);
}return this;},getStyles:function(){var a={};Array.flatten(arguments).each(function(b){a[b]=this.getStyle(b);},this);return a;}});Element.Styles=new Hash({left:"@px",top:"@px",bottom:"@px",right:"@px",width:"@px",height:"@px",maxWidth:"@px",maxHeight:"@px",minWidth:"@px",minHeight:"@px",backgroundColor:"rgb(@, @, @)",backgroundPosition:"@px @px",color:"rgb(@, @, @)",fontSize:"@px",letterSpacing:"@px",lineHeight:"@px",clip:"rect(@px @px @px @px)",margin:"@px @px @px @px",padding:"@px @px @px @px",border:"@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)",borderWidth:"@px @px @px @px",borderStyle:"@ @ @ @",borderColor:"rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)",zIndex:"@",zoom:"@",fontWeight:"@",textIndent:"@px",opacity:"@"});
Element.ShortStyles={margin:{},padding:{},border:{},borderWidth:{},borderStyle:{},borderColor:{}};["Top","Right","Bottom","Left"].each(function(g){var f=Element.ShortStyles;
var b=Element.Styles;["margin","padding"].each(function(h){var i=h+g;f[h][i]=b[i]="@px";});var e="border"+g;f.border[e]=b[e]="@px @ rgb(@, @, @)";var d=e+"Width",a=e+"Style",c=e+"Color";
f[e]={};f.borderWidth[d]=f[e][d]=b[d]="@px";f.borderStyle[a]=f[e][a]=b[a]="@";f.borderColor[c]=f[e][c]=b[c]="rgb(@, @, @)";});(function(){Element.implement({scrollTo:function(h,i){if(b(this)){this.getWindow().scrollTo(h,i);
}else{this.scrollLeft=h;this.scrollTop=i;}return this;},getSize:function(){if(b(this)){return this.getWindow().getSize();}return{x:this.offsetWidth,y:this.offsetHeight};
},getScrollSize:function(){if(b(this)){return this.getWindow().getScrollSize();}return{x:this.scrollWidth,y:this.scrollHeight};},getScroll:function(){if(b(this)){return this.getWindow().getScroll();
}return{x:this.scrollLeft,y:this.scrollTop};},getScrolls:function(){var i=this,h={x:0,y:0};while(i&&!b(i)){h.x+=i.scrollLeft;h.y+=i.scrollTop;i=i.parentNode;
}return h;},getOffsetParent:function(){var h=this;if(b(h)){return null;}if(!Browser.Engine.trident){return h.offsetParent;}while((h=h.parentNode)&&!b(h)){if(d(h,"position")!="static"){return h;
}}return null;},getOffsets:function(){if(this.getBoundingClientRect){var j=this.getBoundingClientRect(),m=document.id(this.getDocument().documentElement),p=m.getScroll(),k=this.getScrolls(),i=this.getScroll(),h=(d(this,"position")=="fixed");
return{x:j.left.toInt()+k.x-i.x+((h)?0:p.x)-m.clientLeft,y:j.top.toInt()+k.y-i.y+((h)?0:p.y)-m.clientTop};}var l=this,n={x:0,y:0};if(b(this)){return n;
}while(l&&!b(l)){n.x+=l.offsetLeft;n.y+=l.offsetTop;if(Browser.Engine.gecko){if(!f(l)){n.x+=c(l);n.y+=g(l);}var o=l.parentNode;if(o&&d(o,"overflow")!="visible"){n.x+=c(o);
n.y+=g(o);}}else{if(l!=this&&Browser.Engine.webkit){n.x+=c(l);n.y+=g(l);}}l=l.offsetParent;}if(Browser.Engine.gecko&&!f(this)){n.x-=c(this);n.y-=g(this);
}return n;},getPosition:function(k){if(b(this)){return{x:0,y:0};}var l=this.getOffsets(),i=this.getScrolls();var h={x:l.x-i.x,y:l.y-i.y};var j=(k&&(k=document.id(k)))?k.getPosition():{x:0,y:0};
return{x:h.x-j.x,y:h.y-j.y};},getCoordinates:function(j){if(b(this)){return this.getWindow().getCoordinates();}var h=this.getPosition(j),i=this.getSize();
var k={left:h.x,top:h.y,width:i.x,height:i.y};k.right=k.left+k.width;k.bottom=k.top+k.height;return k;},computePosition:function(h){return{left:h.x-e(this,"margin-left"),top:h.y-e(this,"margin-top")};
},setPosition:function(h){return this.setStyles(this.computePosition(h));}});Native.implement([Document,Window],{getSize:function(){if(Browser.Engine.presto||Browser.Engine.webkit){var i=this.getWindow();
return{x:i.innerWidth,y:i.innerHeight};}var h=a(this);return{x:h.clientWidth,y:h.clientHeight};},getScroll:function(){var i=this.getWindow(),h=a(this);
return{x:i.pageXOffset||h.scrollLeft,y:i.pageYOffset||h.scrollTop};},getScrollSize:function(){var i=a(this),h=this.getSize();return{x:Math.max(i.scrollWidth,h.x),y:Math.max(i.scrollHeight,h.y)};
},getPosition:function(){return{x:0,y:0};},getCoordinates:function(){var h=this.getSize();return{top:0,left:0,bottom:h.y,right:h.x,height:h.y,width:h.x};
}});var d=Element.getComputedStyle;function e(h,i){return d(h,i).toInt()||0;}function f(h){return d(h,"-moz-box-sizing")=="border-box";}function g(h){return e(h,"border-top-width");
}function c(h){return e(h,"border-left-width");}function b(h){return(/^(?:body|html)$/i).test(h.tagName);}function a(h){var i=h.getDocument();return(!i.compatMode||i.compatMode=="CSS1Compat")?i.html:i.body;
}})();Element.alias("setPosition","position");Native.implement([Window,Document,Element],{getHeight:function(){return this.getSize().y;},getWidth:function(){return this.getSize().x;
},getScrollTop:function(){return this.getScroll().y;},getScrollLeft:function(){return this.getScroll().x;},getScrollHeight:function(){return this.getScrollSize().y;
},getScrollWidth:function(){return this.getScrollSize().x;},getTop:function(){return this.getPosition().y;},getLeft:function(){return this.getPosition().x;
}});Native.implement([Document,Element],{getElements:function(h,g){h=h.split(",");var c,e={};for(var d=0,b=h.length;d<b;d++){var a=h[d],f=Selectors.Utils.search(this,a,e);
if(d!=0&&f.item){f=$A(f);}c=(d==0)?f:(c.item)?$A(c).concat(f):c.concat(f);}return new Elements(c,{ddup:(h.length>1),cash:!g});}});Element.implement({match:function(b){if(!b||(b==this)){return true;
}var d=Selectors.Utils.parseTagAndID(b);var a=d[0],e=d[1];if(!Selectors.Filters.byID(this,e)||!Selectors.Filters.byTag(this,a)){return false;}var c=Selectors.Utils.parseSelector(b);
return(c)?Selectors.Utils.filter(this,c,{}):true;}});var Selectors={Cache:{nth:{},parsed:{}}};Selectors.RegExps={id:(/#([\w-]+)/),tag:(/^(\w+|\*)/),quick:(/^(\w+|\*)$/),splitter:(/\s*([+>~\s])\s*([a-zA-Z#.*:\[])/g),combined:(/\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)(["']?)([^\4]*?)\4)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g)};
Selectors.Utils={chk:function(b,c){if(!c){return true;}var a=$uid(b);if(!c[a]){return c[a]=true;}return false;},parseNthArgument:function(h){if(Selectors.Cache.nth[h]){return Selectors.Cache.nth[h];
}var e=h.match(/^([+-]?\d*)?([a-z]+)?([+-]?\d*)?$/);if(!e){return false;}var g=parseInt(e[1],10);var d=(g||g===0)?g:1;var f=e[2]||false;var c=parseInt(e[3],10)||0;
if(d!=0){c--;while(c<1){c+=d;}while(c>=d){c-=d;}}else{d=c;f="index";}switch(f){case"n":e={a:d,b:c,special:"n"};break;case"odd":e={a:2,b:0,special:"n"};
break;case"even":e={a:2,b:1,special:"n"};break;case"first":e={a:0,special:"index"};break;case"last":e={special:"last-child"};break;case"only":e={special:"only-child"};
break;default:e={a:(d-1),special:"index"};}return Selectors.Cache.nth[h]=e;},parseSelector:function(e){if(Selectors.Cache.parsed[e]){return Selectors.Cache.parsed[e];
}var d,h={classes:[],pseudos:[],attributes:[]};while((d=Selectors.RegExps.combined.exec(e))){var i=d[1],g=d[2],f=d[3],b=d[5],c=d[6],j=d[7];if(i){h.classes.push(i);
}else{if(c){var a=Selectors.Pseudo.get(c);if(a){h.pseudos.push({parser:a,argument:j});}else{h.attributes.push({name:c,operator:"=",value:j});}}else{if(g){h.attributes.push({name:g,operator:f,value:b});
}}}}if(!h.classes.length){delete h.classes;}if(!h.attributes.length){delete h.attributes;}if(!h.pseudos.length){delete h.pseudos;}if(!h.classes&&!h.attributes&&!h.pseudos){h=null;
}return Selectors.Cache.parsed[e]=h;},parseTagAndID:function(b){var a=b.match(Selectors.RegExps.tag);var c=b.match(Selectors.RegExps.id);return[(a)?a[1]:"*",(c)?c[1]:false];
},filter:function(f,c,e){var d;if(c.classes){for(d=c.classes.length;d--;d){var g=c.classes[d];if(!Selectors.Filters.byClass(f,g)){return false;}}}if(c.attributes){for(d=c.attributes.length;
d--;d){var b=c.attributes[d];if(!Selectors.Filters.byAttribute(f,b.name,b.operator,b.value)){return false;}}}if(c.pseudos){for(d=c.pseudos.length;d--;d){var a=c.pseudos[d];
if(!Selectors.Filters.byPseudo(f,a.parser,a.argument,e)){return false;}}}return true;},getByTagAndID:function(b,a,d){if(d){var c=(b.getElementById)?b.getElementById(d,true):Element.getElementById(b,d,true);
return(c&&Selectors.Filters.byTag(c,a))?[c]:[];}else{return b.getElementsByTagName(a);}},search:function(o,h,t){var b=[];var c=h.trim().replace(Selectors.RegExps.splitter,function(k,j,i){b.push(j);
return":)"+i;}).split(":)");var p,e,A;for(var z=0,v=c.length;z<v;z++){var y=c[z];if(z==0&&Selectors.RegExps.quick.test(y)){p=o.getElementsByTagName(y);
continue;}var a=b[z-1];var q=Selectors.Utils.parseTagAndID(y);var B=q[0],r=q[1];if(z==0){p=Selectors.Utils.getByTagAndID(o,B,r);}else{var d={},g=[];for(var x=0,w=p.length;
x<w;x++){g=Selectors.Getters[a](g,p[x],B,r,d);}p=g;}var f=Selectors.Utils.parseSelector(y);if(f){e=[];for(var u=0,s=p.length;u<s;u++){A=p[u];if(Selectors.Utils.filter(A,f,t)){e.push(A);
}}p=e;}}return p;}};Selectors.Getters={" ":function(h,g,j,a,e){var d=Selectors.Utils.getByTagAndID(g,j,a);for(var c=0,b=d.length;c<b;c++){var f=d[c];if(Selectors.Utils.chk(f,e)){h.push(f);
}}return h;},">":function(h,g,j,a,f){var c=Selectors.Utils.getByTagAndID(g,j,a);for(var e=0,d=c.length;e<d;e++){var b=c[e];if(b.parentNode==g&&Selectors.Utils.chk(b,f)){h.push(b);
}}return h;},"+":function(c,b,a,e,d){while((b=b.nextSibling)){if(b.nodeType==1){if(Selectors.Utils.chk(b,d)&&Selectors.Filters.byTag(b,a)&&Selectors.Filters.byID(b,e)){c.push(b);
}break;}}return c;},"~":function(c,b,a,e,d){while((b=b.nextSibling)){if(b.nodeType==1){if(!Selectors.Utils.chk(b,d)){break;}if(Selectors.Filters.byTag(b,a)&&Selectors.Filters.byID(b,e)){c.push(b);
}}}return c;}};Selectors.Filters={byTag:function(b,a){return(a=="*"||(b.tagName&&b.tagName.toLowerCase()==a));},byID:function(a,b){return(!b||(a.id&&a.id==b));
},byClass:function(b,a){return(b.className&&b.className.contains&&b.className.contains(a," "));},byPseudo:function(a,d,c,b){return d.call(a,c,b);},byAttribute:function(c,d,b,e){var a=Element.prototype.getProperty.call(c,d);
if(!a){return(b=="!=");}if(!b||e==undefined){return true;}switch(b){case"=":return(a==e);case"*=":return(a.contains(e));case"^=":return(a.substr(0,e.length)==e);
case"$=":return(a.substr(a.length-e.length)==e);case"!=":return(a!=e);case"~=":return a.contains(e," ");case"|=":return a.contains(e,"-");}return false;
}};Selectors.Pseudo=new Hash({checked:function(){return this.checked;},empty:function(){return !(this.innerText||this.textContent||"").length;},not:function(a){return !Element.match(this,a);
},contains:function(a){return(this.innerText||this.textContent||"").contains(a);},"first-child":function(){return Selectors.Pseudo.index.call(this,0);},"last-child":function(){var a=this;
while((a=a.nextSibling)){if(a.nodeType==1){return false;}}return true;},"only-child":function(){var b=this;while((b=b.previousSibling)){if(b.nodeType==1){return false;
}}var a=this;while((a=a.nextSibling)){if(a.nodeType==1){return false;}}return true;},"nth-child":function(g,e){g=(g==undefined)?"n":g;var c=Selectors.Utils.parseNthArgument(g);
if(c.special!="n"){return Selectors.Pseudo[c.special].call(this,c.a,e);}var f=0;e.positions=e.positions||{};var d=$uid(this);if(!e.positions[d]){var b=this;
while((b=b.previousSibling)){if(b.nodeType!=1){continue;}f++;var a=e.positions[$uid(b)];if(a!=undefined){f=a+f;break;}}e.positions[d]=f;}return(e.positions[d]%c.a==c.b);
},index:function(a){var b=this,c=0;while((b=b.previousSibling)){if(b.nodeType==1&&++c>a){return false;}}return(c==a);},even:function(b,a){return Selectors.Pseudo["nth-child"].call(this,"2n+1",a);
},odd:function(b,a){return Selectors.Pseudo["nth-child"].call(this,"2n",a);},selected:function(){return this.selected;},enabled:function(){return(this.disabled===false);
}});Element.Events.domready={onAdd:function(a){if(Browser.loaded){a.call(this);}}};(function(){var b=function(){if(Browser.loaded){return;}Browser.loaded=true;
window.fireEvent("domready");document.fireEvent("domready");};window.addEvent("load",b);if(Browser.Engine.trident){var a=document.createElement("div");
(function(){($try(function(){a.doScroll();return document.id(a).inject(document.body).set("html","temp").dispose();}))?b():arguments.callee.delay(50);})();
}else{if(Browser.Engine.webkit&&Browser.Engine.version<525){(function(){(["loaded","complete"].contains(document.readyState))?b():arguments.callee.delay(50);
})();}else{document.addEvent("DOMContentLoaded",b);}}})();var JSON=new Hash(this.JSON&&{stringify:JSON.stringify,parse:JSON.parse}).extend({$specialChars:{"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},$replaceChars:function(a){return JSON.$specialChars[a]||"\\u00"+Math.floor(a.charCodeAt()/16).toString(16)+(a.charCodeAt()%16).toString(16);
},encode:function(b){switch($type(b)){case"string":return'"'+b.replace(/[\x00-\x1f\\"]/g,JSON.$replaceChars)+'"';case"array":return"["+String(b.map(JSON.encode).clean())+"]";
case"object":case"hash":var a=[];Hash.each(b,function(e,d){var c=JSON.encode(e);if(c){a.push(JSON.encode(d)+":"+c);}});return"{"+a+"}";case"number":case"boolean":return String(b);
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);}});var Cookie=new Class({Implements:Options,options:{path:false,domain:false,duration:false,secure:false,document:document},initialize:function(b,a){this.key=b;
this.setOptions(a);},write:function(b){b=encodeURIComponent(b);if(this.options.domain){b+="; domain="+this.options.domain;}if(this.options.path){b+="; path="+this.options.path;
}if(this.options.duration){var a=new Date();a.setTime(a.getTime()+this.options.duration*24*60*60*1000);b+="; expires="+a.toGMTString();}if(this.options.secure){b+="; secure";
}this.options.document.cookie=this.key+"="+b;return this;},read:function(){var a=this.options.document.cookie.match("(?:^|;)\\s*"+this.key.escapeRegExp()+"=([^;]*)");
return(a)?decodeURIComponent(a[1]):null;},dispose:function(){new Cookie(this.key,$merge(this.options,{duration:-1})).write("");return this;}});Cookie.write=function(b,c,a){return new Cookie(b,a).write(c);
};Cookie.read=function(a){return new Cookie(a).read();};Cookie.dispose=function(b,a){return new Cookie(b,a).dispose();};var Swiff=new Class({Implements:[Options],options:{id:null,height:1,width:1,container:null,properties:{},params:{quality:"high",allowScriptAccess:"always",wMode:"transparent",swLiveConnect:true},callBacks:{},vars:{}},toElement:function(){return this.object;
},initialize:function(l,m){this.instance="Swiff_"+$time();this.setOptions(m);m=this.options;var b=this.id=m.id||this.instance;var a=document.id(m.container);
Swiff.CallBacks[this.instance]={};var e=m.params,g=m.vars,f=m.callBacks;var h=$extend({height:m.height,width:m.width},m.properties);var k=this;for(var d in f){Swiff.CallBacks[this.instance][d]=(function(n){return function(){return n.apply(k.object,arguments);
};})(f[d]);g[d]="Swiff.CallBacks."+this.instance+"."+d;}e.flashVars=Hash.toQueryString(g);if(Browser.Engine.trident){h.classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
e.movie=l;}else{h.type="application/x-shockwave-flash";h.data=l;}var j='<object id="'+b+'"';for(var i in h){j+=" "+i+'="'+h[i]+'"';}j+=">";for(var c in e){if(e[c]){j+='<param name="'+c+'" value="'+e[c]+'" />';
}}j+="</object>";this.object=((a)?a.empty():new Element("div")).set("html",j).firstChild;},replaces:function(a){a=document.id(a,true);a.parentNode.replaceChild(this.toElement(),a);
return this;},inject:function(a){document.id(a,true).appendChild(this.toElement());return this;},remote:function(){return Swiff.remote.apply(Swiff,[this.toElement()].extend(arguments));
}});Swiff.CallBacks={};Swiff.remote=function(obj,fn){var rs=obj.CallFunction('<invoke name="'+fn+'" returntype="javascript">'+__flash__argumentsToXML(arguments,2)+"</invoke>");
return eval(rs);};var Fx=new Class({Implements:[Chain,Events,Options],options:{fps:50,unit:false,duration:500,link:"ignore"},initialize:function(a){this.subject=this.subject||this;
this.setOptions(a);this.options.duration=Fx.Durations[this.options.duration]||this.options.duration.toInt();var b=this.options.wait;if(b===false){this.options.link="cancel";
}},getTransition:function(){return function(a){return -(Math.cos(Math.PI*a)-1)/2;};},step:function(){var a=$time();if(a<this.time+this.options.duration){var b=this.transition((a-this.time)/this.options.duration);
this.set(this.compute(this.from,this.to,b));}else{this.set(this.compute(this.from,this.to,1));this.complete();}},set:function(a){return a;},compute:function(c,b,a){return Fx.compute(c,b,a);
},check:function(){if(!this.timer){return true;}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(this.caller.bind(this,arguments));
return false;}return false;},start:function(b,a){if(!this.check(b,a)){return this;}this.from=b;this.to=a;this.time=0;this.transition=this.getTransition();
this.startTimer();this.onStart();return this;},complete:function(){if(this.stopTimer()){this.onComplete();}return this;},cancel:function(){if(this.stopTimer()){this.onCancel();
}return this;},onStart:function(){this.fireEvent("start",this.subject);},onComplete:function(){this.fireEvent("complete",this.subject);if(!this.callChain()){this.fireEvent("chainComplete",this.subject);
}},onCancel:function(){this.fireEvent("cancel",this.subject).clearChain();},pause:function(){this.stopTimer();return this;},resume:function(){this.startTimer();
return this;},stopTimer:function(){if(!this.timer){return false;}this.time=$time()-this.time;this.timer=$clear(this.timer);return true;},startTimer:function(){if(this.timer){return false;
}this.time=$time()-this.time;this.timer=this.step.periodical(Math.round(1000/this.options.fps),this);return true;}});Fx.compute=function(c,b,a){return(b-c)*a+c;
};Fx.Durations={"short":250,normal:500,"long":1000};Fx.CSS=new Class({Extends:Fx,prepare:function(d,e,b){b=$splat(b);var c=b[1];if(!$chk(c)){b[1]=b[0];
b[0]=d.getStyle(e);}var a=b.map(this.parse);return{from:a[0],to:a[1]};},parse:function(a){a=$lambda(a)();a=(typeof a=="string")?a.split(" "):$splat(a);
return a.map(function(c){c=String(c);var b=false;Fx.CSS.Parsers.each(function(f,e){if(b){return;}var d=f.parse(c);if($chk(d)){b={value:d,parser:f};}});
b=b||{value:c,parser:Fx.CSS.Parsers.String};return b;});},compute:function(d,c,b){var a=[];(Math.min(d.length,c.length)).times(function(e){a.push({value:d[e].parser.compute(d[e].value,c[e].value,b),parser:d[e].parser});
});a.$family={name:"fx:css:value"};return a;},serve:function(c,b){if($type(c)!="fx:css:value"){c=this.parse(c);}var a=[];c.each(function(d){a=a.concat(d.parser.serve(d.value,b));
});return a;},render:function(a,d,c,b){a.setStyle(d,this.serve(c,b));},search:function(a){if(Fx.CSS.Cache[a]){return Fx.CSS.Cache[a];}var b={};Array.each(document.styleSheets,function(e,d){var c=e.href;
if(c&&c.contains("://")&&!c.contains(document.domain)){return;}var f=e.rules||e.cssRules;Array.each(f,function(j,g){if(!j.style){return;}var h=(j.selectorText)?j.selectorText.replace(/^\w+/,function(i){return i.toLowerCase();
}):null;if(!h||!h.test("^"+a+"$")){return;}Element.Styles.each(function(k,i){if(!j.style[i]||Element.ShortStyles[i]){return;}k=String(j.style[i]);b[i]=(k.test(/^rgb/))?k.rgbToHex():k;
});});});return Fx.CSS.Cache[a]=b;}});Fx.CSS.Cache={};Fx.CSS.Parsers=new Hash({Color:{parse:function(a){if(a.match(/^#[0-9a-f]{3,6}$/i)){return a.hexToRgb(true);
}return((a=a.match(/(\d+),\s*(\d+),\s*(\d+)/)))?[a[1],a[2],a[3]]:false;},compute:function(c,b,a){return c.map(function(e,d){return Math.round(Fx.compute(c[d],b[d],a));
});},serve:function(a){return a.map(Number);}},Number:{parse:parseFloat,compute:Fx.compute,serve:function(b,a){return(a)?b+a:b;}},String:{parse:$lambda(false),compute:$arguments(1),serve:$arguments(0)}});
Fx.Tween=new Class({Extends:Fx.CSS,initialize:function(b,a){this.element=this.subject=document.id(b);this.parent(a);},set:function(b,a){if(arguments.length==1){a=b;
b=this.property||this.options.property;}this.render(this.element,b,a,this.options.unit);return this;},start:function(c,e,d){if(!this.check(c,e,d)){return this;
}var b=Array.flatten(arguments);this.property=this.options.property||b.shift();var a=this.prepare(this.element,this.property,b);return this.parent(a.from,a.to);
}});Element.Properties.tween={set:function(a){var b=this.retrieve("tween");if(b){b.cancel();}return this.eliminate("tween").store("tween:options",$extend({link:"cancel"},a));
},get:function(a){if(a||!this.retrieve("tween")){if(a||!this.retrieve("tween:options")){this.set("tween",a);}this.store("tween",new Fx.Tween(this,this.retrieve("tween:options")));
}return this.retrieve("tween");}};Element.implement({tween:function(a,c,b){this.get("tween").start(arguments);return this;},fade:function(c){var e=this.get("tween"),d="opacity",a;
c=$pick(c,"toggle");switch(c){case"in":e.start(d,1);break;case"out":e.start(d,0);break;case"show":e.set(d,1);break;case"hide":e.set(d,0);break;case"toggle":var b=this.retrieve("fade:flag",this.get("opacity")==1);
e.start(d,(b)?0:1);this.store("fade:flag",!b);a=true;break;default:e.start(d,arguments);}if(!a){this.eliminate("fade:flag");}return this;},highlight:function(c,a){if(!a){a=this.retrieve("highlight:original",this.getStyle("background-color"));
a=(a=="transparent")?"#fff":a;}var b=this.get("tween");b.start("background-color",c||"#ffff88",a).chain(function(){this.setStyle("background-color",this.retrieve("highlight:original"));
b.callChain();}.bind(this));return this;}});Fx.Morph=new Class({Extends:Fx.CSS,initialize:function(b,a){this.element=this.subject=document.id(b);this.parent(a);
},set:function(a){if(typeof a=="string"){a=this.search(a);}for(var b in a){this.render(this.element,b,a[b],this.options.unit);}return this;},compute:function(e,d,c){var a={};
for(var b in e){a[b]=this.parent(e[b],d[b],c);}return a;},start:function(b){if(!this.check(b)){return this;}if(typeof b=="string"){b=this.search(b);}var e={},d={};
for(var c in b){var a=this.prepare(this.element,c,b[c]);e[c]=a.from;d[c]=a.to;}return this.parent(e,d);}});Element.Properties.morph={set:function(a){var b=this.retrieve("morph");
if(b){b.cancel();}return this.eliminate("morph").store("morph:options",$extend({link:"cancel"},a));},get:function(a){if(a||!this.retrieve("morph")){if(a||!this.retrieve("morph:options")){this.set("morph",a);
}this.store("morph",new Fx.Morph(this,this.retrieve("morph:options")));}return this.retrieve("morph");}};Element.implement({morph:function(a){this.get("morph").start(a);
return this;}});Fx.implement({getTransition:function(){var a=this.options.transition||Fx.Transitions.Sine.easeInOut;if(typeof a=="string"){var b=a.split(":");
a=Fx.Transitions;a=a[b[0]]||a[b[0].capitalize()];if(b[1]){a=a["ease"+b[1].capitalize()+(b[2]?b[2].capitalize():"")];}}return a;}});Fx.Transition=function(b,a){a=$splat(a);
return $extend(b,{easeIn:function(c){return b(c,a);},easeOut:function(c){return 1-b(1-c,a);},easeInOut:function(c){return(c<=0.5)?b(2*c,a)/2:(2-b(2*(1-c),a))/2;
}});};Fx.Transitions=new Hash({linear:$arguments(0)});Fx.Transitions.extend=function(a){for(var b in a){Fx.Transitions[b]=new Fx.Transition(a[b]);}};Fx.Transitions.extend({Pow:function(b,a){return Math.pow(b,a[0]||6);
},Expo:function(a){return Math.pow(2,8*(a-1));},Circ:function(a){return 1-Math.sin(Math.acos(a));},Sine:function(a){return 1-Math.sin((1-a)*Math.PI/2);
},Back:function(b,a){a=a[0]||1.618;return Math.pow(b,2)*((a+1)*b-a);},Bounce:function(f){var e;for(var d=0,c=1;1;d+=c,c/=2){if(f>=(7-4*d)/11){e=c*c-Math.pow((11-6*d-11*f)/4,2);
break;}}return e;},Elastic:function(b,a){return Math.pow(2,10*--b)*Math.cos(20*b*Math.PI*(a[0]||1)/3);}});["Quad","Cubic","Quart","Quint"].each(function(b,a){Fx.Transitions[b]=new Fx.Transition(function(c){return Math.pow(c,[a+2]);
});});var Request=new Class({Implements:[Chain,Events,Options],options:{url:"",data:"",headers:{"X-Requested-With":"XMLHttpRequest",Accept:"text/javascript, text/html, application/xml, text/xml, */*"},async:true,format:false,method:"post",link:"ignore",isSuccess:null,emulation:true,urlEncoded:true,encoding:"utf-8",evalScripts:false,evalResponse:false,noCache:false},initialize:function(a){this.xhr=new Browser.Request();
this.setOptions(a);this.options.isSuccess=this.options.isSuccess||this.isSuccess;this.headers=new Hash(this.options.headers);},onStateChange:function(){if(this.xhr.readyState!=4||!this.running){return;
}this.running=false;this.status=0;$try(function(){this.status=this.xhr.status;}.bind(this));this.xhr.onreadystatechange=$empty;if(this.options.isSuccess.call(this,this.status)){this.response={text:this.xhr.responseText,xml:this.xhr.responseXML};
this.success(this.response.text,this.response.xml);}else{this.response={text:null,xml:null};this.failure();}},isSuccess:function(){return((this.status>=200)&&(this.status<300));
},processScripts:function(a){if(this.options.evalResponse||(/(ecma|java)script/).test(this.getHeader("Content-type"))){return $exec(a);}return a.stripScripts(this.options.evalScripts);
},success:function(b,a){this.onSuccess(this.processScripts(b),a);},onSuccess:function(){this.fireEvent("complete",arguments).fireEvent("success",arguments).callChain();
},failure:function(){this.onFailure();},onFailure:function(){this.fireEvent("complete").fireEvent("failure",this.xhr);},setHeader:function(a,b){this.headers.set(a,b);
return this;},getHeader:function(a){return $try(function(){return this.xhr.getResponseHeader(a);}.bind(this));},check:function(){if(!this.running){return true;
}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(this.caller.bind(this,arguments));return false;}return false;},send:function(k){if(!this.check(k)){return this;
}this.running=true;var i=$type(k);if(i=="string"||i=="element"){k={data:k};}var d=this.options;k=$extend({data:d.data,url:d.url,method:d.method},k);var g=k.data,b=String(k.url),a=k.method.toLowerCase();
switch($type(g)){case"element":g=document.id(g).toQueryString();break;case"object":case"hash":g=Hash.toQueryString(g);}if(this.options.format){var j="format="+this.options.format;
g=(g)?j+"&"+g:j;}if(this.options.emulation&&!["get","post"].contains(a)){var h="_method="+a;g=(g)?h+"&"+g:h;a="post";}if(this.options.urlEncoded&&a=="post"){var c=(this.options.encoding)?"; charset="+this.options.encoding:"";
this.headers.set("Content-type","application/x-www-form-urlencoded"+c);}if(this.options.noCache){var f="noCache="+new Date().getTime();g=(g)?f+"&"+g:f;
}var e=b.lastIndexOf("/");if(e>-1&&(e=b.indexOf("#"))>-1){b=b.substr(0,e);}if(g&&a=="get"){b=b+(b.contains("?")?"&":"?")+g;g=null;}this.xhr.open(a.toUpperCase(),b,this.options.async);
this.xhr.onreadystatechange=this.onStateChange.bind(this);this.headers.each(function(m,l){try{this.xhr.setRequestHeader(l,m);}catch(n){this.fireEvent("exception",[l,m]);
}},this);this.fireEvent("request");this.xhr.send(g);if(!this.options.async){this.onStateChange();}return this;},cancel:function(){if(!this.running){return this;
}this.running=false;this.xhr.abort();this.xhr.onreadystatechange=$empty;this.xhr=new Browser.Request();this.fireEvent("cancel");return this;}});(function(){var a={};
["get","post","put","delete","GET","POST","PUT","DELETE"].each(function(b){a[b]=function(){var c=Array.link(arguments,{url:String.type,data:$defined});
return this.send($extend(c,{method:b}));};});Request.implement(a);})();Element.Properties.send={set:function(a){var b=this.retrieve("send");if(b){b.cancel();
}return this.eliminate("send").store("send:options",$extend({data:this,link:"cancel",method:this.get("method")||"post",url:this.get("action")},a));},get:function(a){if(a||!this.retrieve("send")){if(a||!this.retrieve("send:options")){this.set("send",a);
}this.store("send",new Request(this.retrieve("send:options")));}return this.retrieve("send");}};Element.implement({send:function(a){var b=this.get("send");
b.send({data:this,url:a||b.options.url});return this;}});Request.HTML=new Class({Extends:Request,options:{update:false,append:false,evalScripts:true,filter:false},processHTML:function(c){var b=c.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
c=(b)?b[1]:c;var a=new Element("div");return $try(function(){var d="<root>"+c+"</root>",g;if(Browser.Engine.trident){g=new ActiveXObject("Microsoft.XMLDOM");
g.async=false;g.loadXML(d);}else{g=new DOMParser().parseFromString(d,"text/xml");}d=g.getElementsByTagName("root")[0];if(!d){return null;}for(var f=0,e=d.childNodes.length;
f<e;f++){var h=Element.clone(d.childNodes[f],true,true);if(h){a.grab(h);}}return a;})||a.set("html",c);},success:function(d){var c=this.options,b=this.response;
b.html=d.stripScripts(function(e){b.javascript=e;});var a=this.processHTML(b.html);b.tree=a.childNodes;b.elements=a.getElements("*");if(c.filter){b.tree=b.elements.filter(c.filter);
}if(c.update){document.id(c.update).empty().set("html",b.html);}else{if(c.append){document.id(c.append).adopt(a.getChildren());}}if(c.evalScripts){$exec(b.javascript);
}this.onSuccess(b.tree,b.elements,b.html,b.javascript);}});Element.Properties.load={set:function(a){var b=this.retrieve("load");if(b){b.cancel();}return this.eliminate("load").store("load:options",$extend({data:this,link:"cancel",update:this,method:"get"},a));
},get:function(a){if(a||!this.retrieve("load")){if(a||!this.retrieve("load:options")){this.set("load",a);}this.store("load",new Request.HTML(this.retrieve("load:options")));
}return this.retrieve("load");}};Element.implement({load:function(){this.get("load").send(Array.link(arguments,{data:Object.type,url:String.type}));return this;
}});Request.JSON=new Class({Extends:Request,options:{secure:true},initialize:function(a){this.parent(a);this.headers.extend({Accept:"application/json","X-Request":"JSON"});
},success:function(a){this.response.json=JSON.decode(a,this.options.secure);this.onSuccess(this.response.json,a);}});

//MooTools More, <http://mootools.net/more>. Copyright (c) 2006-2009 Aaron Newton <http://clientcide.com/>, Valerio Proietti <http://mad4milk.net> & the MooTools team <http://mootools.net/developers>, MIT Style License.

MooTools.More={version:"1.2.4.2",build:"bd5a93c0913cce25917c48cbdacde568e15e02ef"};(function(){var c=this;var b=function(){if(c.console&&console.log){try{console.log.apply(console,arguments);
}catch(d){console.log(Array.slice(arguments));}}else{Log.logged.push(arguments);}return this;};var a=function(){this.logged.push(arguments);return this;
};this.Log=new Class({logged:[],log:a,resetLog:function(){this.logged.empty();return this;},enableLog:function(){this.log=b;this.logged.each(function(d){this.log.apply(this,d);
},this);return this.resetLog();},disableLog:function(){this.log=a;return this;}});Log.extend(new Log).enableLog();Log.logger=function(){return this.log.apply(this,arguments);
};})();Element.implement({measure:function(e){var g=function(h){return !!(!h||h.offsetHeight||h.offsetWidth);};if(g(this)){return e.apply(this);}var d=this.getParent(),f=[],b=[];
while(!g(d)&&d!=document.body){b.push(d.expose());d=d.getParent();}var c=this.expose();var a=e.apply(this);c();b.each(function(h){h();});return a;},expose:function(){if(this.getStyle("display")!="none"){return $empty;
}var a=this.style.cssText;this.setStyles({display:"block",position:"absolute",visibility:"hidden"});return function(){this.style.cssText=a;}.bind(this);
},getDimensions:function(a){a=$merge({computeSize:false},a);var f={};var d=function(g,e){return(e.computeSize)?g.getComputedSize(e):g.getSize();};var b=this.getParent("body");
if(b&&this.getStyle("display")=="none"){f=this.measure(function(){return d(this,a);});}else{if(b){try{f=d(this,a);}catch(c){}}else{f={x:0,y:0};}}return $chk(f.x)?$extend(f,{width:f.x,height:f.y}):$extend(f,{x:f.width,y:f.height});
},getComputedSize:function(a){a=$merge({styles:["padding","border"],plains:{height:["top","bottom"],width:["left","right"]},mode:"both"},a);var c={width:0,height:0};
switch(a.mode){case"vertical":delete c.width;delete a.plains.width;break;case"horizontal":delete c.height;delete a.plains.height;break;}var b=[];$each(a.plains,function(g,f){g.each(function(h){a.styles.each(function(i){b.push((i=="border")?i+"-"+h+"-width":i+"-"+h);
});});});var e={};b.each(function(f){e[f]=this.getComputedStyle(f);},this);var d=[];$each(a.plains,function(g,f){var h=f.capitalize();c["total"+h]=c["computed"+h]=0;
g.each(function(i){c["computed"+i.capitalize()]=0;b.each(function(k,j){if(k.test(i)){e[k]=e[k].toInt()||0;c["total"+h]=c["total"+h]+e[k];c["computed"+i.capitalize()]=c["computed"+i.capitalize()]+e[k];
}if(k.test(i)&&f!=k&&(k.test("border")||k.test("padding"))&&!d.contains(k)){d.push(k);c["computed"+h]=c["computed"+h]-e[k];}});});});["Width","Height"].each(function(g){var f=g.toLowerCase();
if(!$chk(c[f])){return;}c[f]=c[f]+this["offset"+g]+c["computed"+g];c["total"+g]=c[f]+c["total"+g];delete c["computed"+g];},this);return $extend(e,c);}});
Element.implement({isDisplayed:function(){return this.getStyle("display")!="none";},isVisible:function(){var a=this.offsetWidth,b=this.offsetHeight;return(a==0&&b==0)?false:(a>0&&b>0)?true:this.isDisplayed();
},toggle:function(){return this[this.isDisplayed()?"hide":"show"]();},hide:function(){var b;try{if((b=this.getStyle("display"))=="none"){b=null;}}catch(a){}return this.store("originalDisplay",b||"block").setStyle("display","none");
},show:function(a){return this.setStyle("display",a||this.retrieve("originalDisplay")||"block");},swapClass:function(a,b){return this.removeClass(a).addClass(b);
}});Fx.Reveal=new Class({Extends:Fx.Morph,options:{link:"cancel",styles:["padding","border","margin"],transitionOpacity:!Browser.Engine.trident4,mode:"vertical",display:"block",hideInputs:Browser.Engine.trident?"select, input, textarea, object, embed":false},dissolve:function(){try{if(!this.hiding&&!this.showing){if(this.element.getStyle("display")!="none"){this.hiding=true;
this.showing=false;this.hidden=true;this.cssText=this.element.style.cssText;var d=this.element.getComputedSize({styles:this.options.styles,mode:this.options.mode});
this.element.setStyle("display","block");if(this.options.transitionOpacity){d.opacity=1;}var b={};$each(d,function(f,e){b[e]=[f,0];},this);this.element.setStyle("overflow","hidden");
var a=this.options.hideInputs?this.element.getElements(this.options.hideInputs):null;this.$chain.unshift(function(){if(this.hidden){this.hiding=false;$each(d,function(f,e){d[e]=f;
},this);this.element.style.cssText=this.cssText;this.element.setStyle("display","none");if(a){a.setStyle("visibility","visible");}}this.fireEvent("hide",this.element);
this.callChain();}.bind(this));if(a){a.setStyle("visibility","hidden");}this.start(b);}else{this.callChain.delay(10,this);this.fireEvent("complete",this.element);
this.fireEvent("hide",this.element);}}else{if(this.options.link=="chain"){this.chain(this.dissolve.bind(this));}else{if(this.options.link=="cancel"&&!this.hiding){this.cancel();
this.dissolve();}}}}catch(c){this.hiding=false;this.element.setStyle("display","none");this.callChain.delay(10,this);this.fireEvent("complete",this.element);
this.fireEvent("hide",this.element);}return this;},reveal:function(){try{if(!this.showing&&!this.hiding){if(this.element.getStyle("display")=="none"||this.element.getStyle("visiblity")=="hidden"||this.element.getStyle("opacity")==0){this.showing=true;
this.hiding=this.hidden=false;var d;this.cssText=this.element.style.cssText;this.element.measure(function(){d=this.element.getComputedSize({styles:this.options.styles,mode:this.options.mode});
}.bind(this));$each(d,function(f,e){d[e]=f;});if($chk(this.options.heightOverride)){d.height=this.options.heightOverride.toInt();}if($chk(this.options.widthOverride)){d.width=this.options.widthOverride.toInt();
}if(this.options.transitionOpacity){this.element.setStyle("opacity",0);d.opacity=1;}var b={height:0,display:this.options.display};$each(d,function(f,e){b[e]=0;
});this.element.setStyles($merge(b,{overflow:"hidden"}));var a=this.options.hideInputs?this.element.getElements(this.options.hideInputs):null;if(a){a.setStyle("visibility","hidden");
}this.start(d);this.$chain.unshift(function(){this.element.style.cssText=this.cssText;this.element.setStyle("display",this.options.display);if(!this.hidden){this.showing=false;
}if(a){a.setStyle("visibility","visible");}this.callChain();this.fireEvent("show",this.element);}.bind(this));}else{this.callChain();this.fireEvent("complete",this.element);
this.fireEvent("show",this.element);}}else{if(this.options.link=="chain"){this.chain(this.reveal.bind(this));}else{if(this.options.link=="cancel"&&!this.showing){this.cancel();
this.reveal();}}}}catch(c){this.element.setStyles({display:this.options.display,visiblity:"visible",opacity:1});this.showing=false;this.callChain.delay(10,this);
this.fireEvent("complete",this.element);this.fireEvent("show",this.element);}return this;},toggle:function(){if(this.element.getStyle("display")=="none"||this.element.getStyle("visiblity")=="hidden"||this.element.getStyle("opacity")==0){this.reveal();
}else{this.dissolve();}return this;},cancel:function(){this.parent.apply(this,arguments);this.element.style.cssText=this.cssText;this.hidding=false;this.showing=false;
}});Element.Properties.reveal={set:function(a){var b=this.retrieve("reveal");if(b){b.cancel();}return this.eliminate("reveal").store("reveal:options",a);
},get:function(a){if(a||!this.retrieve("reveal")){if(a||!this.retrieve("reveal:options")){this.set("reveal",a);}this.store("reveal",new Fx.Reveal(this,this.retrieve("reveal:options")));
}return this.retrieve("reveal");}};Element.Properties.dissolve=Element.Properties.reveal;Element.implement({reveal:function(a){this.get("reveal",a).reveal();
return this;},dissolve:function(a){this.get("reveal",a).dissolve();return this;},nix:function(){var a=Array.link(arguments,{destroy:Boolean.type,options:Object.type});
this.get("reveal",a.options).dissolve().chain(function(){this[a.destroy?"destroy":"dispose"]();}.bind(this));return this;},wink:function(){var b=Array.link(arguments,{duration:Number.type,options:Object.type});
var a=this.get("reveal",b.options);a.reveal().chain(function(){(function(){a.dissolve();}).delay(b.duration||2000);});}});var Drag=new Class({Implements:[Events,Options],options:{snap:6,unit:"px",grid:false,style:true,limit:false,handle:false,invert:false,preventDefault:false,stopPropagation:false,modifiers:{x:"left",y:"top"}},initialize:function(){var b=Array.link(arguments,{options:Object.type,element:$defined});
this.element=document.id(b.element);this.document=this.element.getDocument();this.setOptions(b.options||{});var a=$type(this.options.handle);this.handles=((a=="array"||a=="collection")?$$(this.options.handle):document.id(this.options.handle))||this.element;
this.mouse={now:{},pos:{}};this.value={start:{},now:{}};this.selection=(Browser.Engine.trident)?"selectstart":"mousedown";this.bound={start:this.start.bind(this),check:this.check.bind(this),drag:this.drag.bind(this),stop:this.stop.bind(this),cancel:this.cancel.bind(this),eventStop:$lambda(false)};
this.attach();},attach:function(){this.handles.addEvent("mousedown",this.bound.start);return this;},detach:function(){this.handles.removeEvent("mousedown",this.bound.start);
return this;},start:function(c){if(c.rightClick){return;}if(this.options.preventDefault){c.preventDefault();}if(this.options.stopPropagation){c.stopPropagation();
}this.mouse.start=c.page;this.fireEvent("beforeStart",this.element);var a=this.options.limit;this.limit={x:[],y:[]};for(var d in this.options.modifiers){if(!this.options.modifiers[d]){continue;
}if(this.options.style){this.value.now[d]=this.element.getStyle(this.options.modifiers[d]).toInt();}else{this.value.now[d]=this.element[this.options.modifiers[d]];
}if(this.options.invert){this.value.now[d]*=-1;}this.mouse.pos[d]=c.page[d]-this.value.now[d];if(a&&a[d]){for(var b=2;b--;b){if($chk(a[d][b])){this.limit[d][b]=$lambda(a[d][b])();
}}}}if($type(this.options.grid)=="number"){this.options.grid={x:this.options.grid,y:this.options.grid};}this.document.addEvents({mousemove:this.bound.check,mouseup:this.bound.cancel});
this.document.addEvent(this.selection,this.bound.eventStop);},check:function(a){if(this.options.preventDefault){a.preventDefault();}var b=Math.round(Math.sqrt(Math.pow(a.page.x-this.mouse.start.x,2)+Math.pow(a.page.y-this.mouse.start.y,2)));
if(b>this.options.snap){this.cancel();this.document.addEvents({mousemove:this.bound.drag,mouseup:this.bound.stop});this.fireEvent("start",[this.element,a]).fireEvent("snap",this.element);
}},drag:function(a){if(this.options.preventDefault){a.preventDefault();}this.mouse.now=a.page;for(var b in this.options.modifiers){if(!this.options.modifiers[b]){continue;
}this.value.now[b]=this.mouse.now[b]-this.mouse.pos[b];if(this.options.invert){this.value.now[b]*=-1;}if(this.options.limit&&this.limit[b]){if($chk(this.limit[b][1])&&(this.value.now[b]>this.limit[b][1])){this.value.now[b]=this.limit[b][1];
}else{if($chk(this.limit[b][0])&&(this.value.now[b]<this.limit[b][0])){this.value.now[b]=this.limit[b][0];}}}if(this.options.grid[b]){this.value.now[b]-=((this.value.now[b]-(this.limit[b][0]||0))%this.options.grid[b]);
}if(this.options.style){this.element.setStyle(this.options.modifiers[b],this.value.now[b]+this.options.unit);}else{this.element[this.options.modifiers[b]]=this.value.now[b];
}}this.fireEvent("drag",[this.element,a]);},cancel:function(a){this.document.removeEvent("mousemove",this.bound.check);this.document.removeEvent("mouseup",this.bound.cancel);
if(a){this.document.removeEvent(this.selection,this.bound.eventStop);this.fireEvent("cancel",this.element);}},stop:function(a){this.document.removeEvent(this.selection,this.bound.eventStop);
this.document.removeEvent("mousemove",this.bound.drag);this.document.removeEvent("mouseup",this.bound.stop);if(a){this.fireEvent("complete",[this.element,a]);
}}});Element.implement({makeResizable:function(a){var b=new Drag(this,$merge({modifiers:{x:"width",y:"height"}},a));this.store("resizer",b);return b.addEvent("drag",function(){this.fireEvent("resize",b);
}.bind(this));}});Drag.Move=new Class({Extends:Drag,options:{droppables:[],container:false,precalculate:false,includeMargins:true,checkDroppables:true},initialize:function(b,a){this.parent(b,a);
b=this.element;this.droppables=$$(this.options.droppables);this.container=document.id(this.options.container);if(this.container&&$type(this.container)!="element"){this.container=document.id(this.container.getDocument().body);
}var c=b.getStyles("left","right","position");if(c.left=="auto"||c.top=="auto"){b.setPosition(b.getPosition(b.getOffsetParent()));}if(c.position=="static"){b.setStyle("position","absolute");
}this.addEvent("start",this.checkDroppables,true);this.overed=null;},start:function(a){if(this.container){this.options.limit=this.calculateLimit();}if(this.options.precalculate){this.positions=this.droppables.map(function(b){return b.getCoordinates();
});}this.parent(a);},calculateLimit:function(){var d=this.element.getOffsetParent(),g=this.container.getCoordinates(d),f={},c={},b={},i={},k={};["top","right","bottom","left"].each(function(o){f[o]=this.container.getStyle("border-"+o).toInt();
b[o]=this.element.getStyle("border-"+o).toInt();c[o]=this.element.getStyle("margin-"+o).toInt();i[o]=this.container.getStyle("margin-"+o).toInt();k[o]=d.getStyle("padding-"+o).toInt();
},this);var e=this.element.offsetWidth+c.left+c.right,n=this.element.offsetHeight+c.top+c.bottom,h=0,j=0,m=g.right-f.right-e,a=g.bottom-f.bottom-n;if(this.options.includeMargins){h+=c.left;
j+=c.top;}else{m+=c.right;a+=c.bottom;}if(this.element.getStyle("position")=="relative"){var l=this.element.getCoordinates(d);l.left-=this.element.getStyle("left").toInt();
l.top-=this.element.getStyle("top").toInt();h+=f.left-l.left;j+=f.top-l.top;m+=c.left-l.left;a+=c.top-l.top;if(this.container!=d){h+=i.left+k.left;j+=(Browser.Engine.trident4?0:i.top)+k.top;
}}else{h-=c.left;j-=c.top;if(this.container==d){m-=f.left;a-=f.top;}else{h+=g.left+f.left;j+=g.top+f.top;}}return{x:[h,m],y:[j,a]};},checkAgainst:function(c,b){c=(this.positions)?this.positions[b]:c.getCoordinates();
var a=this.mouse.now;return(a.x>c.left&&a.x<c.right&&a.y<c.bottom&&a.y>c.top);},checkDroppables:function(){var a=this.droppables.filter(this.checkAgainst,this).getLast();
if(this.overed!=a){if(this.overed){this.fireEvent("leave",[this.element,this.overed]);}if(a){this.fireEvent("enter",[this.element,a]);}this.overed=a;}},drag:function(a){this.parent(a);
if(this.options.checkDroppables&&this.droppables.length){this.checkDroppables();}},stop:function(a){this.checkDroppables();this.fireEvent("drop",[this.element,this.overed,a]);
this.overed=null;return this.parent(a);}});Element.implement({makeDraggable:function(a){var b=new Drag.Move(this,a);this.store("dragger",b);return b;}});

/*

This file contains javascript wrappers for common html elements
which allows for easy element specific manipulation.

It is based on the prototype javascript library

Each element in this library can exist in one of two states.  Either it
represents an object actually in the document, or it represents an object
that doesn't yet exist in the document.  The second case is indended for 
creating an element in memory prior to writing it to the document.




*/

//----------------------------------------------------------------------
// This is the base object that handles the basic operations common
// to all HTML elements
//----------------------------------------------------------------------
function element_base(){
  this.element_name  = null;
  this.element_attrs = null;
  this.my_element = null; // this is the element as returned by 
                          // prototype's $() operator
  
  //
  //Connects this element up to an existing select element
  //
  this.bind = function(element){
    this.my_element = $(element);
  }
  //
  //Creates an element as a child to the given element
  //
  this.createAt = function(elem){
    var targetElem = this.normalizeElem(elem);
    this.my_element = new Element(this.element_name,this.element_attrs);
    targetElem.my_element.insert(this.my_element);
    this.addContent();    
  }
  //
  //Creates an element after (as a sibling of) the given element
  //
  this.createAfter = function(elem){
    var targetElem = this.normalizeElem(elem);
    this.my_element = new Element(this.element_name,this.element_attrs);
    targetElem.my_element.insert({after:this.my_element});
    this.addContent();    
  }
  //
  //This method should be overridden by subclasses.  After an element is created, this 
  //method is called to fill out any content.  The overriden method should depend on 
  //this.my_element being initialized with the element to initialize
  //
  this.addContent = function(){}
  
  this.setFocus = function(){
    my_element.focus();  
  }
  
  //
  //an element being passed in could be one of several types.
  //it could be an element_base derived type, or it could be
  //the id of an element.  This method takes the various types
  //and converts it to a element_base related object
  //
  this.normalizeElem = function(elem){
    //alert(typeof elem);
    if ( typeof elem == "object") {
       return elem;
    } else {
       //assume it's an id
       var new_elem = new element_base();
       new_elem.bind(elem);
       return new_elem;  
    }
    
  }
  
  this.escapeHTML = function (str) {                                       
    return str.replace(/&/g,'&amp;').replace(/>/g,'&gt;').replace(/</g,'&lt;').replace(/"/g,'&quot;');
  }
  

}
//----------------------------------------------------------------------
// checkbox
//----------------------------------------------------------------------
function Checkbox(){

  this.check = function(){
    this.my_element.checked = true;
  }
  this.uncheck = function(){
    this.my_element.checked = false;
  }
  this.toggle = function(){
  }
  this.isChecked = function(){
    return this.my_element.checked;
  }

}
Checkbox.prototype = new element_base;

//----------------------------------------------------------------------
// text element
//----------------------------------------------------------------------
function Text(){
  this.element_name = "input";
  this.element_attrs = {"type":"text"}; 
  this.value = null;  //value can be stored here temporarily until the 
                      //element is actually created
  
  this.getValue = function(){return this.my_element.value;};
  this.setValue = function(v){
    if (this.my_element!=null){
       this.my_element.value = v;
    } else {
       this.value = v;  
    } 
  }
  this.addContent = function(){
      this.setValue(this.value);
  }
}
Text.prototype = new element_base;
//----------------------------------------------------------------------
// Select element
//----------------------------------------------------------------------
function Select(){
  this.element_name = "select";
  var optiongroups
  
  this.addOption = function(text,value){
    this.my_element.insert("<option value='"+value+"'>"+this.escapeHTML(text)+"</option>");
  }
  this.addOptionGroup = function(text){
    this.my_element.insert("<optgroup label='"+text+"'/>");
  }
  this.addOptionToGroup = function(text,value,groupname){
    var optgroups = this.my_element.select("optgroup");
    var found = false;
    for (var i=0; i<optgroups.length; i++){
        if (optgroups[i].label==groupname){
           var opt = document.createElement("option");
           opt.value = value;
           opt.appendChild(document.createTextNode(text));
           optgroups[i].appendChild(opt);
           found = true;
        }
    }
    if (!found) return false;
    return true;
  }
  this.getSelectedText  = function(){
    return  this.my_element.options[this.my_element.selectedIndex].text;  //returns the text that the user sees
  };
  this.getSelectedValue = function(){
    return this.my_element.options[this.my_element.selectedIndex].value; //returns the value attribute
  };
  this.scrollToTop = function(){
    this.my_element.selectedIndex=0;
  }
  this.selectByName  = function(name){
    for (var i=0; i<this.my_element.options.length; i++){
        if (this.my_element.options[i].text == name){
           this.my_element.selectedIndex = i;
        }
    }  
  }
  this.selectByValue  = function(value){
    for (var i=0; i<this.my_element.options.length; i++){
        if (this.my_element.options[i].value == value){
           this.my_element.selectedIndex = i;
        }
    }  
  }
  this.sort = function(){
    var o = new Array();
  
    if (this.my_element.options==null) { return; }
  
    for (var i=0; i<this.my_element.options.length; i++) {
        o[o.length] = new Option( this.my_element.options[i].text, this.my_element.options[i].value, 
        this.my_element.options[i].defaultSelected,        
        this.my_element.options[i].selected) ;
    }
    if (o.length==0) { return; }
    o = o.sort( function(a,b) { 
                  if ((a.text.toLowerCase()+"") < (b.text.toLowerCase()+"")) { return -1; }
                  if ((a.text.toLowerCase()+"") > (b.text.toLowerCase()+"")) { return 1; }
                  return 0;
                  } 
               );
  
    for (var i=0; i<o.length; i++) {
        this.my_element.options[i] = new Option(o[i].text, o[i].value, o[i].defaultSelected, o[i].selected);
    }

  }
  
  
  // Gets the number of selectable items in the list (option groups 
  // are visible in the list but are not selectable and so are 
  // not counted.
  this.count = function(){
    return this.my_element.length;
  }
}
Select.prototype = new element_base;

function OptionGroup(){

}



//----------------------------------------------------------------------
// table element
//----------------------------------------------------------------------
function Table(){
  this.element_name = "table";
  this.deleteContents = function(){
    if (this.my_element==null){
       alert("Table.deleteContents is not implemented for the case where the Table object is not bound to an actual table element");  
       return;
    }
    var elementarray = this.my_element.down('tbody').childElements();
    for (var i=0; i<elementarray.length; i++){
        elementarray[i].remove();
    }
  }
}
Table.prototype = new element_base;
//----------------------------------------------------------------------
// div element
//----------------------------------------------------------------------
function Div(){
  this.element_name = "div";
  this.setHTML = function(html){
    this.my_element.innerHTML = html;
  }
  this.appendHTML = function(html){
    this.my_element.innerHTML = this.my_element.innerHTML+html;
  }

}
Div.prototype = new element_base;


//----------------------------------------------------------------------
// RadioButtonGroup
// radio buttons cannot be handled in the same way as other 
// controls because a radio button is not a single control.
//----------------------------------------------------------------------
function RadioButtonGroup(){
  var rblist = null;

  this.bind = function(group_name){
    rblist = document.getElementsByName(group_name);
  }
  this.getSelectedValue = function(){
    for (var i=0; i<rblist.length; i++){
        if (rblist[i].checked){
           return rblist[i].value;
        }
    }    
    return null;
  }
  this.getSelectedText = function(){
    for (var i=0; i<rblist.length; i++){
        if (rblist[i].checked){
           return rblist[i].nextSibling.wholeText;
        }
    }
    return null;
  }
  this.setSelected = function(value){
    alert('Radio.setSelected not implemented');
  }

}
//-------------------------------------------------------------------
//  cookie.js - a client side persistance framework
//              backed by cookies
//
//
//
//
//-------------------------------------------------------------------
//Client-side cookie manipulation
function createCookie(name,value,days)
{
	if (days)
	{
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name)
{
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++)
	{
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

function eraseCookie(name)
{
	createCookie(name,"",-1);
}

//-------------------------------------------------------------------
//Client-side storage
function ClientSideStorage(storageName){
  var storage = null;
  var error_string = "";
  var name = storageName;

  storage = new Object();
  //some javascript libraries add extra properties to objects.  We need to remove
  //them all from the storage object
  for (var i in storage){
      delete storage[i];
  }
  
  try { //You might not be able to trust the values in the cookes so watch for exceptions
      parse(readCookie(name));
  } catch (errstring){
      error_string = errstring;
  }
  //-------------------------------------------------------
  // clear
  // clears the value from a cookie in memory but does
  // not alter the cookie on disk.  To change the cookie
  // on disk you must save after clearing.
  //-------------------------------------------------------
  this.clear = function(){
    storage = new Object();
    //some javascript libraries add extra properties to objects.  We need to remove
    //them all from the storage object
    for (var i in storage){
        delete storage[i];
    }
  }
  //-------------------------------------------------------
  // contains
  //-------------------------------------------------------
  this.contains = function(name){
    if (name in storage){
       return true;
    } else { //it might be an array
       return  name+"*" in storage;
    }
  }
  //-------------------------------------------------------
  // remove
  //-------------------------------------------------------
  this.remove = function(){
    eraseCookie(name);
  }
  //-------------------------------------------------------
  // put
  //-------------------------------------------------------
  this.put = function(name,value){
    storage[name]=value;
  }
  //-------------------------------------------------------
  // get
  //-------------------------------------------------------
  this.get = function(name){
    return storage[name];
  }
  //-------------------------------------------------------
  // get default
  //-------------------------------------------------------
  this.getDefault = function(name,def){
    if (storage[name]==undefined){
       return def;
    }
    return storage[name];
  }
  //-------------------------------------------------------
  // putArray
  //
  // We add an asterix to the name of the array so that we
  // know it's an array. JavaScript doesn't provide a
  // reliable way of recognizing arrays
  //-------------------------------------------------------
  this.putArray = function(name,array){
    storage[name+"*"]=array;
  }
  //-------------------------------------------------------
  // getArray
  //-------------------------------------------------------
  this.getArray = function(name){
    return storage[name+"*"];
  }

  //-------------------------------------------------------
  // save
  //-------------------------------------------------------
  this.save = function(){
    var result = "";
    for (var i in storage){
        var value = storage[i];
        if (i.indexOf("*")==-1){ //Then save a single value
           //alert("value "+value+" encoded: "+encode(value));
           result = result + "~" + i + "~=" + ig_cookie_encode(value);
        } else { //then save an array of values

           result = result + "~" + i;
           if (value.length==0){
              result = result + "~0"; //special indicator for empty arrays
           } else {
             for (var i=0; i<value.length; i++){
                 result += "~*" + ig_cookie_encode(value[i]);
             }
           }
        }
    }
    createCookie(name,result,1000);
  }
  //tildes become double tildes
  function ig_cookie_encode(mystring){
    var encoded = "";
    var parts = String(mystring).split("~"); //split on tildes
    //rebuild replacing the tildes with 2 tildes
    var delim = "";
    for (var i=0; i<parts.length; i++){
        encoded += delim + parts[i];
        delim = "~~";
    }
    return encoded;
  }
  //double tildes become single tildes
  function ig_cookie_decode(mystring){
    var result = "";
    var parts = String(mystring).split("~~"); //split on double tildes
    var delim = "";
    for (var i=0; i<parts.length; i++){ //reassemble with single tildes
        result += delim + parts[i];
        delim = "~";
    }
    return result;
  }
  
  // String format is a repetition of this pattern "~ name ~= value" that is
  // each name value pair starts with a single tilde.  Names are separated from
  // values by a tilde-equals pair.  Tildes that existed in the value strings
  // are replaced by double tildes.
  //
  // So the algorithm is to first break up the string into pairs acording to the
  // single tildes.  Then break the pairs into names and values using the ~=.
  // Then replace any double tildes in the value with single tildes.
  //
  function parse(string){
    var pairs = breakAtSingleTildes(string);
    for (var i=0; i<pairs.length; i++){
        //first determine if this is an array or a singular value
        //the character following the first tilde makes the determination
        //"=" means single "*" means array
        var index = pairs[i].indexOf("~");
        var name = pairs[i].substr(0,index);
        if (pairs[i].charAt(index+1)=="="){     //handle single value
           var value = pairs[i].substr(index+2);
           storage[name] = ig_cookie_decode(value);

        } else if (pairs[i].charAt(index+1)=="*"){ //handles array
           var valuestring = pairs[i].substr(index+2);
           var values = new Array();
           var array_index=0;
           var value_index=0;
           while ((value_index = valuestring.indexOf("~*",value_index)) > -1){   //values are separated by a "~*" so we need to find one
                 //if (value_index==0 || valuestring.charAt(value_index-1)!="~"){   //not preceaded by a tilde
                 if (value_index==0 || preceededByEvenNumberOfTildes(valuestring,value_index)){   //not preceaded by a tilde
                    //we found a value end
                    var value = valuestring.substr(0,value_index);
                    values[array_index++] = ig_cookie_decode(value);
                    valuestring = valuestring.substr(value_index+2);
                    value_index=0;
                 } else { //its a false seperator.  skip it
                   value_index++;
                 }
           }
           values[array_index++]=ig_cookie_decode(valuestring);
           storage[name]=values;
        } else if (pairs[i].charAt(index+1)=="0"){ //handles empty array
           storage[name]= new Array();
        } else {
          throw "error parsing value.  Expeced ~=, ~* or ~0 to separate name from value";
        }

    }

  }

  function preceededByEvenNumberOfTildes(string, index){
    var count=0;
    var back_count = index-1;
    if (index==0){
       return true;
    }
    while (back_count > -1 && string.charAt(back_count--)=="~"){
          count++;
    }
    return ((count%2)==0);
  }

  // Breaks a string up at single tildes and discards the tildes.
  // returns the pieces as an array
  function breakAtSingleTildes(string){
    var results = new Array();
    var remainder = string;
    var results_index = 0;

    if (string==null){
       return results;
    }

    while (true){

          if (remainder.length==0){ //then we're done
             return results;        //return what we have
          }

          if (remainder.charAt(0)!="~"){
             throw "Badly formed storage string.  missing a tilde separator";
          }
          remainder = remainder.substr(1); //remove the initial tilde

          //find the next tilde not followed by an equals or another tilde
          index = remainder.indexOf("~");
          //This one should be followed by an equals
          var nextchar = remainder.charAt(index+1);
          if (nextchar!= "=" && nextchar!="*" && nextchar!="0"){
             throw "Badly formed storage string.  missing an equals, or asterix value separator"
          }
          while (true){
                //Now we're in the value portion.  Keep searching until
                //you find a single tilde
                index = remainder.indexOf("~",index+1);
                if (index==-1){ //we're at the end of the string and we're done
                   results[results_index++] = remainder;
                   return results;
                }
                //if The index is at the end of the string, we have a problem
                if (index+1 == remainder.length) {
                   throw "Badly formed storage string.  missing an equals value separator";
                }
                //if the tilde is not followed by another tilde
                //we've found the end of this pair
                if (remainder.charAt(index+1)=="~"){
                   index++; //skip the 2nd tilde
                } else if (remainder.charAt(index+1)=="*"){
                   index++; //skip the asterix
                } else {
                   results[results_index++] = remainder.substr(0,index);
                   remainder = remainder.substr(index);
                   break;
                }
          }
    }

  }


  this.test =  function(){

    alert("ig_cookie_decode: "+ig_cookie_decode("~~one~~two~~"));


  }

  return this;
}
function getXMLDoc(xmldata){
  try { //Internet Explorer
      xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
      xmlDoc.async="false";
      xmlDoc.loadXML(xmldata);
  }
  catch(e){
      try { //Firefox, Mozilla, Opera, etc.
          parser=new DOMParser();
          xmlDoc=parser.parseFromString(xmldata,"text/xml");
      } 
      catch(e){
          alert(e.message);
          return;
      }
  } 
  return xmlDoc;
}

/*

    This presents simplified interface to XML
    Text is handled differently than sub elements
    Children are just elements and not text nodes
    Text made up of whitespace is ignored

*/

function XMLDoc(){
  
  var xmldoc = null;

  this.setXML = function(xmlstr){
    try { //Internet Explorer
      xmldoc=new ActiveXObject("Microsoft.XMLDOM");
      xmldoc.async="false";
      xmldoc.loadXML(xmlstr);
    }
    catch(e){
      try { //Firefox, Mozilla, Opera, etc.
          parser=new DOMParser();
          xmldoc=parser.parseFromString(xmlstr,"text/xml");
      } 
      catch(e){
          alert(e.message);
          return;
      }
    }
  }

  this.getRoot = function(){
    return new XMLElement(xmldoc.documentElement);
  }

}

function XMLElement(node){
  
  var thisnode = node;
  var childArray = new Array();
  var mytext = "";
  
  //////////////////////////////////////////////////////////////////////////////
  this.getName = function(){
    return thisnode.nodeName;
  }
  //////////////////////////////////////////////////////////////////////////////
  this.hasAttribute = function(attrName){
    return !(thisnode.attributes.getNamedItem(attrName)==null);
  }
  //////////////////////////////////////////////////////////////////////////////
  this.getAttribute = function(attrName){
    var attrs = thisnode.attributes;
    if (!this.hasAttribute(attrName)) return null;
    return attrs.getNamedItem(attrName).nodeValue
  }
  //////////////////////////////////////////////////////////////////////////////
  this.hasChildren = function(){
    return (childArray.length>0);
  }
  //////////////////////////////////////////////////////////////////////////////
  this.getChildren = function(){
    var retarr = new Array();
    for (var i=0; i<childArray.length; i++){
        retarr.push(new XMLElement(childArray[i]));
    }
    return retarr;
  }
  //////////////////////////////////////////////////////////////////////////////
  // Get a list of child elements of a given element name
  //////////////////////////////////////////////////////////////////////////////
  this.getChildrenByName = function(name){
    var retarr = new Array();
    for (var i=0; i<childArray.length; i++){
        if (childArray[i].nodeName == name){
           retarr.push(new XMLElement(childArray[i]));
        }
    }
    return retarr;
  }
  //////////////////////////////////////////////////////////////////////////////
  // Get a child element by name.  This is a convenience method for situations
  // where you are expecting only a single returned element.  It's convenient 
  // because you don't have to dereference an array when you only have a single
  // return value.
  //
  // An exception will be thrown if there are more than one match;
  //
  //////////////////////////////////////////////////////////////////////////////
  this.getChildByName = function(name){
    var arr = this.getChildrenByName(name);
    if (arr.length>1){
       throw { name: "XML Format Error", message: "getChildByName found more than one element for: "+name};
    }
    if (arr.length==0) return null;
    return arr[0];
  }
  //////////////////////////////////////////////////////////////////////////////
  this.hasText = function(){
    return (mytext.length>0);
  }
  //////////////////////////////////////////////////////////////////////////////
  this.getText = function(){
    return mytext;
  }
  
  //parse the node
  for (var i=0; i<thisnode.childNodes.length; i++){
      parseNode(thisnode.childNodes.item(i));
  }
  //trim the text;
  mytext = mytext.replace(/^\s+|\s+$/g,"");

  function parseNode(node){
    switch (node.nodeType){
      case 1:
           childArray.push(node);
           break;
      case 3:
           mytext = mytext+node.nodeValue+" ";
           break;
      default:
           alert("Unknown node type "+node.nodeType+" in XMLElement.parseNode");
    }
  }
  
  
}


/*

*/
function Guider(){

  var xmldoc;
  var icon         = null;
  var logo         = null;
  var introText    = null;
  var contactEmail = null;
  var contactName  = null;
  var cssFile      = null;
  //This is the array of nodes by node id
  var nodearray = new Object();

  this.setXML = function(xmlstr){
    xmldoc = new XMLDoc();
    xmldoc.setXML(xmlstr);
    //build map of nodes by id
    var root  = xmldoc.getRoot();
    var noderoot = root.getChildByName("nodes");
    var nodes = noderoot.getChildrenByName("node");
    for (var i=0; i<nodes.length; i++){
        var node = nodes[i];
        var id = node.getAttribute("id");
        nodearray[id]=node;
    }
    //get the guider header stuff if available
    var options = root.getChildByName('portable-options');
    if (options != null){
       var icon_node         = options.getChildByName('icon');
       var logo_node         = options.getChildByName('logo');
       var introText_node    = options.getChildByName('intro-text');
       var contactEmail_node = options.getChildByName('contact-email');
       var contactName_node  = options.getChildByName('contact-name');
       var cssFile_node      = options.getChildByName('css-file');
       
       if (icon_node!=null)         icon         = icon_node.getChildByName('url').getText();
       if (logo_node!=null)         logo         = logo_node.getChildByName('url').getText();
       if (introText_node!=null)    introText    = introText_node.getText();
       if (contactEmail_node!=null) contactEmail = contactEmail_node.getText();
       if (contactName_node!=null)  contactName  = contactName_node.getText();
       if (cssFile_node!=null)      cssFile      = cssFile_node.getText();
    }
  }
  this.getIcon = function(){
    return icon;
  }
  this.getLogo = function(){
    return logo;
  }
  this.getIntroText = function(){
    return introText;
  }
  this.getCssFile = function(){
    return cssFile;
  }
  this.getContactEmail = function(){
    return contactEmail;
  }
  this.hasContactName = function(){
    return (contactName!=null);
  }
  this.getContactName = function(){
    return contactName;
  }
  this.getTitle = function(){
    var rootNodeElement = xmldoc.getRoot().getChildByName("name");
    return rootNodeElement.getText();
  }
  this.getRootQuestion = function(){
    var rootNodeElement = xmldoc.getRoot().getChildByName("root-node");
    var rootid = rootNodeElement.getText();
    var node = nodearray[rootid];
    var rootQ = new Question(node);
    rootQ.setGuider(this);
    return rootQ;
  }
  this.getNode = function(id){
    var node = nodearray[id];
    var desttype = node.getAttribute('type');
    var dest = null;
    switch (desttype){
      case "Question":
           dest = new Question(node);
           break;
      case "GoogleSearch":
           dest = new Results(node);
           break;
      case "ExternalLink":
           dest = new Results(node);
           break;
      case "SolutionPage":
           dest = new Results(node);
           break;
      default:
           alert("Unknown destination type of '"+desttype+"' in Answer.getDestination");
           break;
    }
    dest.setGuider(this);
    return dest;
  }
  //----------------------------------------------------------------------------
  // This method gets an external link node with the given destination URL
  //----------------------------------------------------------------------------
  this.getNodeByDestination = function(desturl){
    for (var i in nodearray){
        var node = nodearray[i];
        if (node.getAttribute('type')=="ExternalLink"){
           var result = new Results(node);
           result.setGuider(this);
           if (result.getURL()==desturl){
              return node;
           }
        }
    }
    return null;
  }
  //----------------------------------------------------------------------------
  // This method gets the parent of a given node
  //----------------------------------------------------------------------------
  this.getParent = function(childnode){
    var target = childnode.getAttribute('id');
    for (var i in nodearray){
        var node = nodearray[i];
        if (node.getAttribute('type')=="Question"){ //all parent nodes are Questions
           var question = new Question(node);
           question.setGuider(this);
           var answers = question.getAnswers();
           for (var j=0; j<answers.length; j++){
               var destnode = answers[j].getDestination();
               if (destnode.getID()==target){
                  return question;
               }
           }
        }
    }
    return null;
  }
  this.hasHeader = function(){
    return ( (icon!=null) || (logo!=null) || (introText!=null) );
  }

}

//Takes an XMLElement representing the node from the guider xml
function Question(node){

  var thisnode = node;
  var myguider = null;

  this.getText = function(){
    var qtnode = thisnode.getChildByName("question-text");
    return qtnode.getText().replace(/\[.*?:(.*?)\]/g,"$1"); //remove definitions which are not supported in portable guiders
  }
  this.getAnswers = function(){
    var answersnode = thisnode.getChildByName("answers");
    var answers = answersnode.getChildrenByName("answer");
    var retarr = new Array();
    for (var i=0; i<answers.length; i++){
        var a = new Answer(answers[i]);
        a.setGuider(myguider);
        retarr.push(a);
    }
    return retarr;
  }
  this.getID = function(){
    return thisnode.getAttribute('id');
  }
  this.hasExplanation = function(){
    return (thisnode.getChildByName("explanation-text")!=null);
  }
  this.getExplanation = function(){
    var exnode = thisnode.getChildByName("explanation-text");
    return exnode.getText();
  }
  this.getGuider = function(){
    return myguider;
  }
  this.isQuestion     = function(){return true;}
  this.isResult       = function(){return false;}
  this.isGoogleSearch = function(){return false;}
  this.isExternalLink = function(){return false;}
  this.isRoot     = function(){
    if (myguider==null){
       alert("question object has no link to the guider.");
       return false;
    }
    if (this.getID()==myguider.getRootQuestion().getID()){
       return true;
    }
    return false;
  }
  this.setGuider  = function(guider){myguider = guider;};
  //parse the XML node

}

function Answer(node){
  this.SUB_NODE      = 1;
  this.GOOGLE_SEARCH = 2;
  this.EXTERNAL_LINK = 3;

  var thisnode = node;
  var myguider = null;

  this.getDestination = function(){
    var dest = null;
    var linkselem = thisnode.getChildByName('links');
    if (linkselem!=null){
       var linkelem = linkselem.getChildByName('link');
       if (linkelem != null){ //Then it's an internal link
          var nodeid = linkelem.getAttribute('subsequent-node-id');
          dest = myguider.getNode(nodeid);
       } else { //is it a link to an external guider
          linkelem = linkselem.getChildByName('external-link');
          if (linkelem != null){ //Then it's an external guider
             var linkid = linkelem.getAttribute('guider');
             dest = new ExternalGuider(linkid);
          }
       }
    }
    if (dest!=null){
       dest.setGuider(myguider);
    }
    return dest;
  }

  this.getText = function(){
    var atnode = thisnode.getChildByName("answer-text");
    return atnode.getText().replace(/\[.*?:(.*?)\]/g,"$1"); //remove definitions which are not supported in portable guiders
  }
  this.hasExplanation = function(){
    return (thisnode.getChildByName("explanation-text")!=null);
  }
  this.getExplanation = function(){
    var exnode = thisnode.getChildByName("explanation-text");
    return exnode.getText();
  }
  this.hasImage = function(){
    return (thisnode.getChildByName("image")!=null);
  }
  this.getImage = function(){
    return thisnode.getChildByName("image").getChildByName("url").getText();
  }
  this.setGuider  = function(guider){myguider = guider;};
}

function Results(node){

  var thisnode = node;
  var myguider = null;

  function htmldecode(str){
    var out = str;
    out = out.replace( /\&amp;/g, '&' );
    out = out.replace( /\&lt;/g, '<' );
    out = out.replace( /\&gt;/g, '>' );
    out = out.replace( /\&quot;/g, '"' );
    out = out.replace( /\&copy;/g, '©' );
    out = out.replace( /\&reg;/g, '®' );
    out = out.replace( /\&laquo;/g, '«' );
    out = out.replace( /\&raqou;/g, '»' );
    out = out.replace( /\&apos;/g, "'" );
    return out;
  }

  this.getID = function(){
    return thisnode.getAttribute('id');
  }
  this.getURL = function(){
    var type  = thisnode.getAttribute('type');
    var query = null;
    switch (type){
      case "GoogleSearch":
           var query = thisnode.getChildByName('query').getText();
           query = "http://www.google.com/search?hl=en&q="+query.replace(/\s/g,"+");
           break;
      case "ExternalLink":
           var query = thisnode.getChildByName('query').getText();
           break;
    }
    return query;
  }
  this.getContent = function(){
    return htmldecode(thisnode.getChildByName('content').getText());
  }
  this.isQuestion      = function(){return false;}
  this.isResult        = function(){return true;}
  this.isGoogleSearch  = function(){return (thisnode.getAttribute('type')=='GoogleSearch')}
  this.isExternalLink  = function(){return (thisnode.getAttribute('type')=='ExternalLink')}
  this.isSolutionPage  = function(){return (thisnode.getAttribute('type')=='SolutionPage')}
  this.isGuider        = function(){return false;}
  this.setGuider  = function(guider){myguider = guider;};
}

function ExternalGuider(gid){
  var myguider = null;
  var destgid  = gid;
  this.getExternalGID  = function(){return destgid;}
  this.isQuestion      = function(){return false;}
  this.isResult        = function(){return true;}
  this.isGoogleSearch  = function(){return false;}
  this.isExternalLink  = function(){return false;}
  this.isSolutionPage  = function(){return false;}
  this.isGuider        = function(){return true;}
  this.setGuider  = function(guider){myguider = guider;};

}
var the_portable_guider_map = {};
var ig_options = {
  localCSS:    false, //true - don't set the css file because the css is set locally
  startAtRoot: false, //true - ignore history and start at root
  trackUsers:  true   //true - pings are sent back to track users
};
function portable_guider_callback(xml,uid,gid){
  var storage = new ClientSideStorage("portableguideruser");
  var userid = uid;
  if (storage.contains('userid')){
     userid = storage.get('userid');
  } else {
     storage.put('userid',userid);
     storage.save();
  }
  the_portable_guider_map[gid].setUserId(userid);
  the_portable_guider_map[gid].setXML(gid,xml);
}
function portable_guider_showWhatsThis(evt){
  if (!evt) evt = window.event;
  var target = (evt.target)?evt.target:(evt.srcElement)?evt.srcElement:null;
  //find the ancestor with class portable-guider-answer
  var row = target;
  while (row.parentNode){
        row = row.parentNode;
        if (row.className == "portable-guider-answer"){
           break;
        }
  }
  if (row.className != "portable-guider-answer"){
     //we can't find the what's this text
     return;
  }
  //now find the child with class name "portable-guider-whats-this-text"
  var textelem = null;
  for (var i=0; i<row.childNodes.length; i++){
      if (row.childNodes[i].className == "portable-guider-whats-this-text"){
         textelem = row.childNodes[i];
         break;
      }
  }
  if (textelem==null){
     //we can't find the what's this text
     return;     
  }
  textelem.style.display = (textelem.style.display != 'none' ? 'none' : '' );
  if (evt.stopPropagation) evt.stopPropagation();
  evt.cancelBubble = true;
  return false;
}
function showQuestionWhatsThis(){
  $('portable-guider-question-whats-this-text').toggle();
}
function PortableGuider(app,gid,key,viewer,options){

  var theStack  = new PortableGuider.StateStack(gid);
  var theCxn    = new PortableGuider.Connection(app,key,this);
  this.theViewer = viewer;
  this.theViewer.setContext(this);
  this.theViewer.setStack(theStack);
  this.theViewer.setConnection(theCxn);
  
  var theRootGID    = gid;
  var theApp = app;
  
  the_portable_guider_map[theRootGID] = this;
  

  this.options = ig_options;
  if (typeof options != 'undefined'){
     for (attr in options) { this.options[attr] = options[attr]; }
  }
  
  if (ig_options.trackUsers){
  } 

  this.hideViewer = function(){
    if (this.theViewer!=null){ 
       this.theViewer.hide();
    }
  }
  
  this.setXML = function(gid,xml){

    var guider = new Guider();
    guider.setXML(xml);
    theStack.pushGuider(gid,guider);
    this.theViewer.render()
  }
  this.setUserId = function(uid){
    this.theViewer.setUserId(uid);
  }
  this.getVersion = function(){return "0.03";}
  this.getApp     = function(){return app;}
  

  

//  
//  this.redisplay = function(){
//    $(thedivid).show();
//    render();
//  }

  theCxn.requestXML(theStack.theState.getGID());

}

////////////////////////////////////////////////////////////////////////////////
// Class: PortableGuider.Connection
////////////////////////////////////////////////////////////////////////////////
PortableGuider.Connection = function(app,key,pg_context){
  var theApp      = app;
  var theKey      = key;
  var theContext  = pg_context;
  var pingCounter = 0;
  
  this.requestXML = function(gid){
    var script = document.createElement("script");
    script.setAttribute("type", "text/javascript");
    script.setAttribute("charset", "utf-8");
    script.setAttribute("src", theApp+"/api/0.01/"+gid+"?callback=portable_guider_callback&noCacheIE="+new Date().getTime());
    document.getElementsByTagName("head").item(0).appendChild(script);
    the_portable_guider_map[gid] = theContext;
  }
  
  this.ping = function(op,gid,qid,uid){
    var script = document.createElement("script");
    script.setAttribute("type", "text/javascript");
    script.setAttribute("charset", "utf-8");
    script.setAttribute("src", theApp+"/api/0.01/ping/?apikey="+theKey+"&uid="+uid+"&operation="+op+"&gslug="+gid+"&qslug="+qid+"&count="+pingCounter+"&noCacheIE="+new Date().getTime());
    pingCounter++;
    document.getElementsByTagName("head").item(0).appendChild(script);
  }
  
  this.requestCSS = function(cssfile){
    var linkelem = document.getElementById('portable_guider_css');
    if (linkelem==null){ //then we need to build a new one
       linkelem=document.createElement("link")
       linkelem.setAttribute("id", "portable_guider_css")
       linkelem.setAttribute("rel", "stylesheet")
       linkelem.setAttribute("type", "text/css")
       linkelem.setAttribute("href", theApp+cssfile);
       document.getElementsByTagName("head")[0].appendChild(linkelem);
    } else { // then we have an existing element
       linkelem.setAttribute("href", theApp+cssfile);
    }
  }
  this.sendContactInfo = function(gid,userid,email,msg){
    var script = document.createElement("script");
    script.setAttribute("type", "text/javascript");
    script.setAttribute("charset", "utf-8");
    script.setAttribute("src", theApp+"/api/0.01/contact/?apikey="+theKey+"&uid="+userid+"&gid="+gid+"&name="+escape(name)+"&email="+email+"&msg="+escape(msg)+"&noCacheIE="+new Date().getTime());
    document.getElementsByTagName("head").item(0).appendChild(script);  
  }
}
////////////////////////////////////////////////////////////////////////////////
// Class: PortableGuider.Viewer
////////////////////////////////////////////////////////////////////////////////

PortableGuider.Viewer = function(gid){
  var theBaseGID    = gid;
  var theCurrentGID = gid;
  var theStack      = null;
  var theCxn        = null;
  var thecanvasdiv  = null;
  var theUserId     = null;
  var theContext    = null;
  var isDisplayed   = false;
  var theCanvasID   = "portable-guider-canvas";
  var thediv        = null;  //The div of the canvas into which the body of the guider is written

  //builds the portable guider frame and canvas then inserts into the document
  //use this method instead of setCanvasDiv if you are willing to accept the 
  //default position and behavior of the 
  this.buildFrame = function(){
    //remove existing frame if any
    var div = document.getElementById("portable-guider-frame");
    if (div != null){
       while (div.childNodes.length>0){
             var child = div.childNodes[0];
             div.removeChild(child);
       }
       //var parentNode = prevDiv.parentNode;
       //parentNode.removeChild(prevDiv);
    } else {
       div = document.createElement("div");
       div.id = "portable-guider-frame";
       //div.style.display = "none";
       div.style.position = "fixed";
       div.style.top  = "50px";
       div.style.left = "50px";
    }
    div.innerHTML  = "<a href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].hideViewer();' title='Close the guider'><span id='portable-guider-frame-close' >close</span></a>"+
                     "<div id='"+theCanvasID+"'></div>";
    var body_elem  = document.getElementsByTagName("body").item(0);
    body_elem.insertBefore(div,body_elem.firstChild);
    thediv = new Div();
    thediv.bind(theCanvasID);
  }
  
  this.setCanvasDivId = function(divid){
    thediv = new Div();
    thediv.bind(divid);
  }

  
  this.displayInitMsg = function(){
    var div = document.createElement("div");
    div.style.width = "170px";
    div.style.backgroundColor = "white";
    div.style.border = "1px solid black";
    div.style.padding = "10px";
    div.innerHTML = "Initializing Guider";
    thediv.my_element.appendChild(div);
    this.display();
  }
  this.display = function(){
    if (isDisplayed) return;
    if (typeof(ig_show_guider)=='function'){
       ig_show_guider('portable-guider-frame');
    } else {
       new Fx.Reveal($('portable-guider-frame'),{onShow:function(){$('portable-guider-frame').makeDraggable({stopPropagation:true});}}).reveal();
    }
    isDisplayed = true;
  }
  this.hide = function(){
    if (!isDisplayed) return;
    var autolaunch = new ClientSideStorage("autolaunch");
    autolaunch.clear();
    autolaunch.save();

    if (typeof(ig_hide_guider)=='function'){
       ig_hide_guider('portable-guider-frame');
    } else {
       new Fx.Reveal($('portable-guider-frame')).dissolve();
    }
    isDisplayed = false;
  }
  this.setConnection = function(cxn){
    theCxn = cxn;
  }
  this.setContext = function(context){
    theContext = context;
  }
  this.setStack = function(stack){
    theStack = stack;
    //this.build(); //reset the div
    //this.render();
    //this.display();
  }

  this.setState = function(state){
    alert('Viewer.setState() not implemented');
  }
  this.setUserId = function(uid){
    theUserId = uid;
  }
//  //----------------------------------------------------------------------------
//  // Tells the portable guider to ignore any exisiting cookies and just start 
//  // at the top of the guider tree.
//  //----------------------------------------------------------------------------
//  this.resetHistory = function(){
//    idstack = new Array();
//    currentid = "";
//    storage.clear();
//    storage.save();
//  }
  this.goToRoot = function(){
    question = theStack.theState.getGuider().getRootQuestion();
    theStack.theState.pushID(question.getID());
    renderQuestion(question);
  }
  this.goBack = function(){
    if (theStack.theState.hasPreviousID()){
       //Then we can stay in the existing guider
       var currentid = theStack.theState.popID();
       var node = theStack.theState.getGuider().getNode(currentid);
       if (!node.isQuestion()){ alert("PortableGuider.renderQuestion received node which is not a question"); }
       renderQuestion(node);    
    } else if (theStack.hasPreviousGuider()){
       //Then we need to go to a previous guider
       theStack.pop();
       //send ping about guider change
       theCxn.ping("guiderchange",theCurrentGID,theStack.theState.getGID(),theUserId);
       if (theStack.theState.getGuider()==null){
          //Then we need to request the XML and wait for it.
          theCxn.requestXML(theStack.theState.getGID());
       } else {
          //The state has the guider it needs
          var guider = theStack.theState.getGuider();
          theCurrentGID = theStack.theState.getGID();
          theCxn.requestCSS(guider.getCssFile());
          var currentid = theStack.theState.getCurrentID();
          var node = theStack.theState.getGuider().getNode(currentid);
          if (!node.isQuestion()){ alert("PortableGuider.renderQuestion received node which is not a question"); }
          renderQuestion(node); 
       }
       theCurrentGID = theStack.theState.getGID();
    }
    theStack.saveState();
  }
  this.handleAnswer =  function(qid,answer_index){
    var guider = theStack.theState.getGuider();
    var question = guider.getNode(qid);
    var answers = question.getAnswers();
    if (answer_index >= answers.length){
       alert('answer index out of bounds in handleAnswer');
    }
    var answer = answers[answer_index];

    theCxn.ping('answerclick',theCurrentGID,encodeURI(answer.getText()),theUserId);
    if (answer.getDestination().isQuestion()){
       this.next(answer.getDestination().getID());
    } else if (answer.getDestination().isExternalLink()){
       window.location = answer.getDestination().getURL();
    } else if (answer.getDestination().isSolutionPage()){
       theStack.theState.pushID(-1);
       renderSolutionPage(answer.getDestination());
    } else if (answer.getDestination().isGoogleSearch()){
       window.open(answer.getDestination().getURL(),"Google","width=1000,height=600,resizable,scrollbars=yes");
    } else { //it's an external guider link
      this.nextGuider(answer.getDestination().getExternalGID());
    }
  }
  this.next = function(id){
    var guider = theStack.theState.getGuider()

    var node = guider.getNode(id);
    if (!node.isQuestion()){ alert("PortableGuider.renderQuestion received node which is not a question"); }

    theStack.theState.pushID(id);

    renderQuestion(node);
    
    theStack.saveState();
  }
  this.nextGuider = function(gid){
    //Show interstitial
    renderLoadingMessage();
    //make call for new guider definition.
    theCxn.requestXML(gid);
    
    theCxn.ping("guiderchange",theCurrentGID,gid,theUserId);
    theCurrentGID = gid;
  }
  this.showContactForm = function(){
    var elem = document.getElementById('portable-guider-contact-link');
    elem.style.display='none';
    var elem = document.getElementById('portable-guider-contact-form');
    elem.style.display='';
  }
  this.sendContactInfo = function(){
    var elem = document.getElementById('portable-guider-contact-form');
    elem.style.display='none';
    var elem = document.getElementById('portable-guider-contact-link');
    elem.style.display='';
    var name  =  document.getElementById('portable-guider-contact-name').value;
    var email =  document.getElementById('portable-guider-contact-email').value;
    var msg   =  document.getElementById('portable-guider-contact-message').value;

    theCxn.sendContactInfo(theBaseGID,theUserId,email,msg);
    
  }
  this.hideContactInfo = function(){
    var elem = document.getElementById('portable-guider-contact-form');
    elem.style.display='none';
    var elem = document.getElementById('portable-guider-contact-link');
    elem.style.display='';
  }
  
  this.render = function(){
    var question = null;
    var guider = theStack.theState.getGuider();
    theCurrentGID = theStack.theState.getGID();
    if (theContext.options.localCSS == false && guider.getCssFile() != null){
       theCxn.requestCSS(guider.getCssFile());
    }
    title = guider.getTitle();
    question = theStack.theState.getInitialQuestion();
    try {
        renderQuestion(question);
    } catch (e){
        renderError(e);
    }
    this.display();
  }
  //////////////////////////////////////////////////////////////////////////////
  // Private methods
  //////////////////////////////////////////////////////////////////////////////
  function renderQuestion(node){

    theCxn.ping('pageview',theCurrentGID,node.getID(),theUserId);
    
    var guider = theStack.theState.getGuider();
    var html = "";
    if (theStack.previousAvailable()){
       html += "<a href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.goBack();' title='Return to the previous question'><span id='portable-guider-enabled-back-Button'>&lt;Back</span></a>";
    } else {
       html += "<span id='portable-guider-disabled-back-Button'>&nbsp;</span>";
    }
    if (node.isRoot()){
       html += "<span id='portable-guider-disabled-root-Button'>&nbsp;</span>";      
    } else {
       html += "<a href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.goToRoot();' title='Return to the root of this guider'><span id='portable-guider-enabled-root-Button'>^top</span></a>";
    }
    html += "<div id='portable-guider-canvas-content'>";
    html += "<div id='portable-guider-title'>"+theStack.theState.getGuider().getTitle()+"</div>";
    // render the header if necessary
    if (node.getGuider().hasHeader()){
       html += "<div id='portable-guider-header'>";
       var icon      = node.getGuider().getIcon();
       var logo      = node.getGuider().getLogo();
       var introText = node.getGuider().getIntroText();

       if (icon!=null){
          html += "<img id='portable-guider-company-logo' src='"+icon+"' alt='company logo' />";
       }
       if (logo!=null){
          html += "<img id='portable-guider-logo' src='"+logo+"' alt='guider logo' />";
       }
       if (introText!=null){
          html += "<p>"+introText+"</p>";
       }

       html += "</div>";
    }
    html += "<div id='portable-guider-body'>";
    html += "<h4 class='portable-guider-question'>"+node.getText()+"</h4>";
    if (node.hasExplanation()){
       html += "<a href='javascript:void(0)' class='portable-guider-whats-this-button' onClick='showQuestionWhatsThis();' >What's this</a>";
       html += "<div id='portable-guider-question-whats-this-text' class='portable-guider-whats-this-text' style='display: none;' >"+node.getExplanation()+"</div>";   
    }
    html += "<div id='portable-guider-answers'>";
    var answers = node.getAnswers(); 
    for (var i=0; i<answers.length; i++){
        var destination = answers[i].getDestination();
        if (destination==null){
           html += "<div class='portable-guider-answer' >"+answers[i].getText();
           if (answers[i].hasImage()){
              html += "<img class='portable-guider-answer-illustration' src='"+answers[i].getImage()+"' alt='answer illustration' />";
           }
           if (answers[i].hasExplanation()){
              html += "<span class='portable-guider-whats-this-button'>What's This</span>";
           }
           if (answers[i].hasExplanation()){
              html +=  "<div id='portable-guider-whats-this-text-"+i+"' class='portable-guider-whats-this-text' style='display: none;'>"+answers[i].getExplanation()+"</div>";
           }
           html += "</div>";
        } else {
          if (destination.isQuestion()){
             html += "<div class='portable-guider-answer'>";
             if (answers[i].hasImage()){
                html += "<a class='portable-guider-answer-image-link' href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.handleAnswer(\""+node.getID()+"\","+i+")' ><img class='portable-guider-answer-illustration' src='"+answers[i].getImage()+"' /></a>";
             }
             html += "<a class='portable-guider-answer-link' href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.handleAnswer(\""+node.getID()+"\","+i+")' ><span class='portable-guider-destination-icon-narrow'>narrow</span>" + answers[i].getText();
             if (answers[i].hasExplanation()){
                html += "<span class='portable-guider-whats-this-button'>What's this</span>";
             }
             html +=  "</a>";
             if (answers[i].hasExplanation()){
                html +=  "<div id='portable-guider-whats-this-text-"+i+"' class='portable-guider-whats-this-text' style='display: none;'>"+answers[i].getExplanation()+"</div>";
             }
             html += "</div>";
             
          } else if (destination.isExternalLink()){
             html += "<div class='portable-guider-answer'>";
             if (answers[i].hasImage()){
                html += "<a class='portable-guider-answer-image-link' href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.handleAnswer(\""+node.getID()+"\","+i+")'><img class='portable-guider-answer-illustration' src='"+answers[i].getImage()+"' /></a>";
             }
             html += "<a class='portable-guider-answer-link' href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.handleAnswer(\""+node.getID()+"\","+i+")'>" + "<span class='portable-guider-destination-icon-link'>website</span>" + answers[i].getText();
             if (answers[i].hasExplanation()){
                html += "<span class='portable-guider-whats-this-button'>What's this</span>";
             }
             html +=  "</a>";
             if (answers[i].hasExplanation()){
                html +=  "<div id='portable-guider-whats-this-text-"+i+"' class='portable-guider-whats-this-text' style='display: none;'>"+answers[i].getExplanation()+"</div>";
             }
             html += "</div>";
          } else if (destination.isSolutionPage()){
             html += "<div class='portable-guider-answer'>";
             if (answers[i].hasImage()){
                html += "<a class='portable-guider-answer-image-link' href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.handleAnswer(\""+node.getID()+"\","+i+")'><img class='portable-guider-answer-illustration' src='"+answers[i].getImage()+"' /></a>";
             }
             html += "<a class='portable-guider-answer-link' href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.handleAnswer(\""+node.getID()+"\","+i+")'>" + "<span class='portable-guider-destination-icon-solution'>solution</span>" + answers[i].getText();
             if (answers[i].hasExplanation()){
                html += "<span class='portable-guider-whats-this-button'>What's this</span>";
             }
             html +=  "</a>";
             if (answers[i].hasExplanation()){
                html +=  "<div id='portable-guider-whats-this-text-"+i+"' class='portable-guider-whats-this-text' style='display: none;'>"+answers[i].getExplanation()+"</div>";
             }
             html += "</div>";            
          } else if (destination.isGoogleSearch()){
             html += "<div class='portable-guider-answer'>";
             if (answers[i].hasImage()){
                html += "<a class='portable-guider-answer-image-link' href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.handleAnswer(\""+node.getID()+"\","+i+")'><img class='portable-guider-answer-illustration' src='"+answers[i].getImage()+"' /></a>";
             }
             html += "<a class='portable-guider-answer-link' href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.handleAnswer(\""+node.getID()+"\","+i+")'><span class='portable-guider-destination-icon-google'>website</span>" + answers[i].getText();
             if (answers[i].hasExplanation()){
                html += "<span class='portable-guider-whats-this-button'>What's this</span>";
             }
             html +=  "</a>";
             if (answers[i].hasExplanation()){
                html +=  "<div id='portable-guider-whats-this-text-"+i+"' class='portable-guider-whats-this-text' style='display: none;'>"+answers[i].getExplanation()+"</div>";
             }
             html += "</div>";
          } else { //it's a link to an external guider
             html += "<div class='portable-guider-answer'>";
             if (answers[i].hasImage()){
                html += "<a class='portable-guider-answer-image-link' href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.handleAnswer(\""+node.getID()+"\","+i+")'><img class='portable-guider-answer-illustration' src='"+answers[i].getImage()+"' /></a>";
             }
             html += "<a class='portable-guider-answer-link' href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.handleAnswer(\""+node.getID()+"\","+i+")'><span class='portable-guider-destination-icon-guider'>guider</span>" + answers[i].getText();
             if (answers[i].hasExplanation()){
                html += "<span class='portable-guider-whats-this-button'>What's this</span>";
             }
             html +=  "</a>";
             if (answers[i].hasExplanation()){
                html +=  "<div id='portable-guider-whats-this-text-"+i+"' class='portable-guider-whats-this-text' style='display: none;'>"+answers[i].getExplanation()+"</div>";
             }
             html += "</div>";
          }
        }
    }
    html += "</div>"; //close portable-guider-body
    html += "</div>";
    html += "</div>";
    html += "<div id='portable-guider-footer'>";
    if (guider.getContactEmail()!=null){
        html += "<div id='portable-guider-contact-form' style='display: none'>";
        html += "<a id='portable-guider-contact-form-close' href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.hideContactInfo();'>X</a>";
        html += "<span>Your name:</span>";    
        html += "<input id='portable-guider-contact-name' type='text'><br />";
        html += "<span>Your email:</span>";    
        html += "<input id='portable-guider-contact-email' type='text'><br />";    
        html += "<span>Message:</span>";    
        html += "<input id='portable-guider-contact-message' type='text'>";    
        html += "<input type='button' value='send' onClick='the_portable_guider_map[\""+theBaseGID+"\"].theViewer.sendContactInfo();'>";    
        html += "</div>";
        html += "<div id='portable-guider-contact-link'>";
        if (guider.hasContactName()){
           html += "<a href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.showContactForm();'>Contact "+guider.getContactName()+"</a>";
        } else {   
           html += "<a href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.showContactForm();'>Contact me now</a>";
        }
        html += "</div>"
    }
    html += "<div id='portable-guider-pg-logo'><a href='http://www.iguiders.com' ><img id='portable-guider-home-link' src='http://www.iguiders.com/pg/latest/img/portable.png' /></a></div>";
    html += "</div>";
    
    thediv.setHTML(html);
    //attach the whats this handlers
    var icons = $$('#portable-guider-answers .portable-guider-whats-this-button');
    for (var i=0; i<icons.length; i++){
        icons[i].onclick = portable_guider_showWhatsThis;
    }
  }
  function renderLoadingMessage(e){
    var div = document.getElementById('portable-guider-canvas-content');
    div.innerHTML = "<div id='portable-guider-loading-message'><span id='portable-guider-loading-message-text'>Loading Next Guider</span><img src='"+theContext.getApp()+"/pg/"+theContext.getVersion()+"/img/progress.gif'/></div>";
  }
  function renderError(e){
    var html = "<a href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].hideViewer();' title='Close the guider' style='float: right'><div id='portable-guider-frame-close' >X</div></a>";
    html += "<div id='portable-guider-error-display'>";
    html += "An error has occurred: "+e.name + ", " + e.message;
    html += "</div>";
    thediv.setHTML(html);  
  }
  function renderSolutionPage(node){
    var html = "";
    html += "<a href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.goBack();' title='Return to the previous question'><span id='portable-guider-enabled-back-Button'>&lt;Back</span></a>";
    html += "<a href='javascript:the_portable_guider_map[\""+theBaseGID+"\"].theViewer.goToRoot();' title='Return to the root of this guider'><span id='portable-guider-enabled-root-Button'>^top</span></a>";
    html += "<div id='portable-guider-canvas-content'>";
     html += "<div id='portable-guider-title'>"+theStack.theState.getGuider().getTitle()+"</div>";
    html += node.getContent();

    html += "</div>";
    thediv.setHTML(html);
  }

}
////////////////////////////////////////////////////////////////////////////////
// Class: PortableGuider.State
////////////////////////////////////////////////////////////////////////////////

PortableGuider.State = function(){
  var theGuider = null;
  var theGID = null;
  
  var idstack = new Array();
  var theCurrentID = null;
  
  
  this.setGuider = function(guider){
    theGuider = guider;
    if (theCurrentID==null){
       this.pushID(theGuider.getRootQuestion().getID());
    }
  }
  this.getGuider = function(){return theGuider;}
  this.setIDs    = function(ids){
    idstack = ids;
    theCurrentID = idstack[idstack.length-1];
  }
  this.getIDs    = function(){return idstack;}
  this.setGID    = function(gid){theGID = gid;}
  this.getGID    = function(){return theGID;}
  
  
  /*
    Behavior of the pushID/popID methods.
    
    They don't really work like a stack.  When you push an ID, it becomes the 
    the current ID (as returned from getCurrentID()).  If you popID you don't 
    get that ID back.  The previous ID becomes the current ID 
    and it's that previous ID that's returned.
  
  */
  this.pushID    = function(id){
    theCurrentID=id;
    idstack.push(theCurrentID);
  }
  this.popID     = function(){
    if (idstack.length<2) return null;
    idstack.length--;
    theCurrentID =idstack[idstack.length-1];
    return theCurrentID;
  }
  this.hasPreviousID = function(){
    return idstack.length>1;
  }
  //setCurrentID is meant for initialization.  Normally you should use pushID 
  //because it moves IDs onto the stack
  //this.setCurrentID = function(id){
  //  theCurrentID = id;
  //}
  this.getCurrentID = function(){
    return theCurrentID;
  }
  //The initial question is either the root of the current guider or it's the last
  //page we were on when accoring to the cookies.  We will use the cookie value if
  //there is one, and it's for the current guider.  Otherwise it's just the root 
  //of this guider.
  this.getInitialQuestion = function(){

    if (theGuider==null){alert('State.getInitialPage called before setting the guider');}
    
    //Determine what the initial node should be.  There are three possiblilties
    //  1. if there's a node that leads to the current URL - use that as the starting node.  otherwise
    //  2. if there is a cookie with the previous location, use that.  Otherwise
    //  3. Use the root node.

    var destnode = theGuider.getNodeByDestination(""+window.location);
    var id = (theCurrentID!=null?theCurrentID:"");
    var question = null;
     
    if (destnode!=null){ 
       question = theGuider.getParent(destnode);
    } else if (id!="") { 
       question = theGuider.getNode(id);
    } else {
       question = theGuider.getRootQuestion();      
    }
    return question;
  }

}

////////////////////////////////////////////////////////////////////////////////
// Class: PortableGuider.StateStack
////////////////////////////////////////////////////////////////////////////////
PortableGuider.StateStack = function(basegid){
  
  var theBaseGID = basegid;
  var theStack = Array();
  var storage = new ClientSideStorage("portableguiderhistory");
  var that = this;
  
  this.theState = null; //this is the state at the top of the stack 
  
  this.push = function(state){
    theStack.push(state);
    this.theState = state;
  }  
  this.pop = function(){
    theStack.length--;
    this.theState = theStack[theStack.length-1];
    return this.theState;
  }
  this.hasPreviousGuider = function(){
    return theStack.length>0;
  }
  /*
    A guider could be pushed to the stack under two circumstances.
    1 - we are going forward to a new guider
    2 - We are going backwards to a guider we didn't have the 
        definition for yet.
    
    So, when a guider is received we check the top of the stack.  
    If the top state is for the same guider we just assign the new 
    guider to that state.  Otherwise, we create a brand new state. 
        
  */
  this.pushGuider = function(gid,guider){
    if (theStack.length>0 && this.theState.getGID()==gid){
       this.theState.setGuider(guider);
    } else {
       var newState = new PortableGuider.State();
       newState.setGuider(guider);
       newState.setGID(gid);
       this.push(newState);
    }
    this.saveState();
  }
  /*
    Indicates if there is a previous location to go back to.
  */
  this.previousAvailable = function(){
    if (theStack.length>1) return true;
    if (this.theState.hasPreviousID()) return true;
    return false;
  }
  this.saveState = function(){
    var guiderstack = Array();
    var idstack     = Array();
    for (var i=0; i<theStack.length; i++){
        guiderstack.push(theStack[i].getGID());
        var thisIDStack = theStack[i].getIDs();
        for (var j=0; j<thisIDStack.length; j++){
            idstack.push(""+i+":"+thisIDStack[j]); //prefix each id with the guider stack number
        }
    }
    storage.put("basegid",theBaseGID);
    //storage.put("currentid",theStack[theStack.length-1].getCurrentID());
    storage.putArray("guiderstack",guiderstack);
    storage.putArray("idstack",idstack);
    storage.save();
  }
  this.alertState = function(){
    var str = "Length: "+theStack.length+"\n";
    for (var i=0; i<theStack.length; i++){
        if (theStack[i].getGuider()!=null){
           str += theStack[i].getGuider().getTitle()+"\n";
        } else {
           str += "no guider.  GID: "+theStack[i].getGID()+"\n";
        }
    }
    alert(str);
  }
  
  //Try to rebuild the stack from cookies.  Return true if possible, 
  //false otherwise
  this.rebuildFromCookies = function(){
    //if the cookie does not exist, there's nothing to rebuild
    var idstack = Array();
    var guiderstack = Array();

    if (!storage.contains("basegid")){
       return false;
    }
    //cookie has data.  See if it's useful.  If the given gid, the base gid
    //is the save as the basegid in the cookie we should be able to use it.
    if (storage.get("basegid")!=theBaseGID){
       return false;
    }
    //OK, the cookie is for this guider.  We should be able to load up the 
    //stack
    if (storage.contains("idstack")){
       idstack = storage.getArray("idstack");  
    } else return false;
    if (storage.contains("guiderstack")){
       guiderstack = storage.getArray("guiderstack");  
    } else return false;
    
    for (var i=0; i<guiderstack.length; i++){
        var state = new PortableGuider.State();
        state.setGID(guiderstack[i]);
        var ids = Array();
        for (var j=0; j<idstack.length; j++){
            if (idstack[j].substr(0,2)==(""+i+":")){
               //if the id is prefixed by this gid index
               ids.push(idstack[j].substr(2));
            }
        }
        state.setIDs(ids);
        this.push(state);
    }
    //if (storage.contains("currentid")){
    //   this.theState.setCurrentID(storage.get("currentid"));
    //}
    return true;
  }


  //Try to reconstitute the state from cookies
  if (!this.rebuildFromCookies()){
     //we were unable to rebuild from cookies so initialize normally
     var state = new PortableGuider.State();
     state.setGID(theBaseGID);
     this.push(state);
  }
  
  //this.alertState();



}

//provides the public interface to igpg.js
function ig_launch_guider(app,gid,apikey,options){
      var viewer = new PortableGuider.Viewer(gid);
      //viewer.displayInitMsg();
      viewer.buildFrame();
      viewer.display();
      var pg = new PortableGuider(app,gid,apikey,viewer,options);
}

