/*
 * jQuery 1.2.6 - New Wave Javascript
 *
 * Copyright (c) 2008 John Resig (jquery.com)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * $Date: 2008/05/26 $
 * $Rev: 5685 $
 */
(function(){var _jQuery=window.jQuery,_$=window.$;var jQuery=window.jQuery=window.$=function(selector,context){return new jQuery.fn.init(selector,context);};var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,isSimple=/^.[^:#\[\.]*$/,undefined;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem){if(elem.id!=match[3])return jQuery().find(selector);return jQuery(elem);}selector=[];}}else
return jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(jQuery.makeArray(selector));},jquery:"1.2.6",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;return jQuery.inArray(elem&&elem.jquery?elem[0]:elem,this);},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value===undefined)return this[0]&&jQuery[type||"attr"](this[0],name);else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else
return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else
selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return this.pushStack(jQuery.unique(jQuery.merge(this.get(),typeof selector=='string'?jQuery(selector):jQuery.makeArray(selector))));},is:function(selector){return!!selector&&jQuery.multiFilter(selector,this).length>0;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i<max;i++){var option=options[i];if(option.selected){value=jQuery.browser.msie&&!option.attributes.value.specified?option.text:option.value;if(one)return value;values.push(value);}}return values;}else
return(this[0].value||"").replace(/\r/g,"");}return undefined;}if(value.constructor==Number)value+='';return this.each(function(){if(this.nodeType!=1)return;if(value.constructor==Array&&/radio|checkbox/.test(this.type))this.checked=(jQuery.inArray(this.value,value)>=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=jQuery.makeArray(value);jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else
this.value=value;});},html:function(value){return value==undefined?(this[0]?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value===undefined){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data===undefined&&this.length)data=jQuery.data(this[0],key);return data===undefined&&parts[1]?this.data(parts[0]):data;}else
return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script"))scripts=scripts.add(elem);else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.fn.init.prototype=jQuery.fn;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else
jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}function now(){return+new Date;}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==i){target=this;--i;}for(;i<length;i++)if((options=arguments[i])!=null)for(var name in options){var src=target[name],copy=options[name];if(target===copy)continue;if(deep&&copy&&typeof copy=="object"&&!copy.nodeType)target[name]=jQuery.extend(deep,src||(copy.length!=null?[]:{}),copy);else if(copy!==undefined)target[name]=copy;}return target;};var expando="jQuery"+now(),uuid=0,windowData={},exclude=/z-?index|font-?weight|opacity|zoom|line-?height/i,defaultView=document.defaultView||{};jQuery.extend({noConflict:function(deep){window.$=_$;if(deep)window.jQuery=_jQuery;return jQuery;},isFunction:function(fn){return!!fn&&typeof fn!="string"&&!fn.nodeName&&fn.constructor!=Array&&/^[\s[]?function/.test(fn+"");},isXMLDoc:function(elem){return elem.documentElement&&!elem.body||elem.tagName&&elem.ownerDocument&&!elem.ownerDocument.body;},globalEval:function(data){data=jQuery.trim(data);if(data){var head=document.getElementsByTagName("head")[0]||document.documentElement,script=document.createElement("script");script.type="text/javascript";if(jQuery.browser.msie)script.text=data;else
script.appendChild(document.createTextNode(data));head.insertBefore(script,head.firstChild);head.removeChild(script);}},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toUpperCase()==name.toUpperCase();},cache:{},data:function(elem,name,data){elem=elem==window?windowData:elem;var id=elem[expando];if(!id)id=elem[expando]=++uuid;if(name&&!jQuery.cache[id])jQuery.cache[id]={};if(data!==undefined)jQuery.cache[id][name]=data;return name?jQuery.cache[id][name]:id;},removeData:function(elem,name){elem=elem==window?windowData:elem;var id=elem[expando];if(name){if(jQuery.cache[id]){delete jQuery.cache[id][name];name="";for(name in jQuery.cache[id])break;if(!name)jQuery.removeData(elem);}}else{try{delete elem[expando];}catch(e){if(elem.removeAttribute)elem.removeAttribute(expando);}delete jQuery.cache[id];}},each:function(object,callback,args){var name,i=0,length=object.length;if(args){if(length==undefined){for(name in object)if(callback.apply(object[name],args)===false)break;}else
for(;i<length;)if(callback.apply(object[i++],args)===false)break;}else{if(length==undefined){for(name in object)if(callback.call(object[name],name,object[name])===false)break;}else
for(var value=object[0];i<length&&callback.call(value,i,value)!==false;value=object[++i]){}}return object;},prop:function(elem,value,type,i,name){if(jQuery.isFunction(value))value=value.call(elem,i);return value&&value.constructor==Number&&type=="curCSS"&&!exclude.test(name)?value+"px":value;},className:{add:function(elem,classNames){jQuery.each((classNames||"").split(/\s+/),function(i,className){if(elem.nodeType==1&&!jQuery.className.has(elem.className,className))elem.className+=(elem.className?" ":"")+className;});},remove:function(elem,classNames){if(elem.nodeType==1)elem.className=classNames!=undefined?jQuery.grep(elem.className.split(/\s+/),function(className){return!jQuery.className.has(classNames,className);}).join(" "):"";},has:function(elem,className){return jQuery.inArray(className,(elem.className||elem).toString().split(/\s+/))>-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else
jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret,style=elem.style;function color(elem){if(!jQuery.browser.safari)return false;var ret=defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=style.outline;style.outline="0 solid black";style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&style&&style[name])ret=style[name];else if(defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var computedStyle=defaultView.getComputedStyle(elem,null);if(computedStyle&&!color(elem))ret=computedStyle.getPropertyValue(name);else{var swap=[],stack=[],a=elem,i=0;for(;a&&color(a);a=a.parentNode)stack.unshift(a);for(;i<stack.length;i++)if(color(stack[i])){swap[i]=stack[i].style.display;stack[i].style.display="block";}ret=name=="display"&&swap[stack.length-1]!=null?"none":(computedStyle&&computedStyle.getPropertyValue(name))||"";for(i=0;i<swap.length;i++)if(swap[i]!=null)stack[i].style.display=swap[i];}if(name=="opacity"&&ret=="")ret="1";}else if(elem.currentStyle){var camelCase=name.replace(/\-(\w)/g,function(all,letter){return letter.toUpperCase();});ret=elem.currentStyle[name]||elem.currentStyle[camelCase];if(!/^\d+(px)?$/i.test(ret)&&/^\d/.test(ret)){var left=style.left,rsLeft=elem.runtimeStyle.left;elem.runtimeStyle.left=elem.currentStyle.left;style.left=ret||0;ret=style.pixelLeft+"px";style.left=left;elem.runtimeStyle.left=rsLeft;}}return ret;},clean:function(elems,context){var ret=[];context=context||document;if(typeof context.createElement=='undefined')context=context.ownerDocument||context[0]&&context[0].ownerDocument||document;jQuery.each(elems,function(i,elem){if(!elem)return;if(elem.constructor==Number)elem+='';if(typeof elem=="string"){elem=elem.replace(/(<(\w+)[^>]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+"></"+tag+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!tags.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!tags.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!tags.indexOf("<td")||!tags.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!tags.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||jQuery.browser.msie&&[1,"div<div>","</div>"]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf("<table")&&tags.indexOf("<tbody")<0?div.firstChild&&div.firstChild.childNodes:wrap[1]=="<table>"&&tags.indexOf("<tbody")<0?div.childNodes:[];for(var j=tbody.length-1;j>=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else
ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var notxml=!jQuery.isXMLDoc(elem),set=value!==undefined,msie=jQuery.browser.msie;name=notxml&&jQuery.props[name]||name;if(elem.tagName){var special=/href|src|style/.test(name);if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(name in elem&&notxml&&!special){if(set){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem[name]=value;}if(jQuery.nodeName(elem,"form")&&elem.getAttributeNode(name))return elem.getAttributeNode(name).nodeValue;return elem[name];}if(msie&&notxml&&name=="style")return jQuery.attr(elem.style,"cssText",value);if(set)elem.setAttribute(name,""+value);var attr=msie&&notxml&&special?elem.getAttribute(name,2):elem.getAttribute(name);return attr===null?undefined:attr;}if(msie&&name=="opacity"){if(set){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(value)+''=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100)+'':"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(set)elem[name]=value;return elem[name];},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(array!=null){var i=array.length;if(i==null||array.split||array.setInterval||array.call)ret[0]=array;else
while(i)ret[--i]=array[i];}return ret;},inArray:function(elem,array){for(var i=0,length=array.length;i<length;i++)if(array[i]===elem)return i;return-1;},merge:function(first,second){var i=0,elem,pos=first.length;if(jQuery.browser.msie){while(elem=second[i++])if(elem.nodeType!=8)first[pos++]=elem;}else
while(elem=second[i++])first[pos++]=elem;return first;},unique:function(array){var ret=[],done={};try{for(var i=0,length=array.length;i<length;i++){var id=jQuery.data(array[i]);if(!done[id]){done[id]=true;ret.push(array[i]);}}}catch(e){ret=array;}return ret;},grep:function(elems,callback,inv){var ret=[];for(var i=0,length=elems.length;i<length;i++)if(!inv!=!callback(elems[i],i))ret.push(elems[i]);return ret;},map:function(elems,callback){var ret=[];for(var i=0,length=elems.length;i<length;i++){var value=callback(elems[i],i);if(value!=null)ret[ret.length]=value;}return ret.concat.apply([],ret);}});var userAgent=navigator.userAgent.toLowerCase();jQuery.browser={version:(userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1],safari:/webkit/.test(userAgent),opera:/opera/.test(userAgent),msie:/msie/.test(userAgent)&&!/opera/.test(userAgent),mozilla:/mozilla/.test(userAgent)&&!/(compatible|webkit)/.test(userAgent)};var styleFloat=jQuery.browser.msie?"styleFloat":"cssFloat";jQuery.extend({boxModel:!jQuery.browser.msie||document.compatMode=="CSS1Compat",props:{"for":"htmlFor","class":"className","float":styleFloat,cssFloat:styleFloat,styleFloat:styleFloat,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing"}});jQuery.each({parent:function(elem){return elem.parentNode;},parents:function(elem){return jQuery.dir(elem,"parentNode");},next:function(elem){return jQuery.nth(elem,2,"nextSibling");},prev:function(elem){return jQuery.nth(elem,2,"previousSibling");},nextAll:function(elem){return jQuery.dir(elem,"nextSibling");},prevAll:function(elem){return jQuery.dir(elem,"previousSibling");},siblings:function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},children:function(elem){return jQuery.sibling(elem.firstChild);},contents:function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}},function(name,fn){jQuery.fn[name]=function(selector){var ret=jQuery.map(this,fn);if(selector&&typeof selector=="string")ret=jQuery.multiFilter(selector,ret);return this.pushStack(jQuery.unique(ret));};});jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(){var args=arguments;return this.each(function(){for(var i=0,length=args.length;i<length;i++)jQuery(args[i])[original](this);});};});jQuery.each({removeAttr:function(name){jQuery.attr(this,name,"");if(this.nodeType==1)this.removeAttribute(name);},addClass:function(classNames){jQuery.className.add(this,classNames);},removeClass:function(classNames){jQuery.className.remove(this,classNames);},toggleClass:function(classNames){jQuery.className[jQuery.className.has(this,classNames)?"remove":"add"](this,classNames);},remove:function(selector){if(!selector||jQuery.filter(selector,[this]).r.length){jQuery("*",this).add(this).each(function(){jQuery.event.remove(this);jQuery.removeData(this);});if(this.parentNode)this.parentNode.removeChild(this);}},empty:function(){jQuery(">*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});function num(elem,prop){return elem[0]&&parseInt(jQuery.curCSS(elem[0],prop,true),10)||0;}var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return i<m[3]-0;},gt:function(a,i,m){return i>m[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false,re=quickChild,m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j<rl;j++){var n=m=="~"||m=="+"?ret[j].nextSibling:ret[j].firstChild;for(;n;n=n.nextSibling)if(n.nodeType==1){var id=jQuery.data(n);if(m=="~"&&merge[id])break;if(!nodeName||n.nodeName.toUpperCase()==nodeName){if(m=="~")merge[id]=true;r.push(n);}if(m=="+")break;}}ret=r;t=jQuery.trim(t.replace(re,""));foundToken=true;}}if(t&&!foundToken){if(!t.indexOf(",")){if(context==ret[0])ret.shift();done=jQuery.merge(done,ret);r=ret=[context];t=" "+t.substr(1,t.length);}else{var re2=quickID;var m=re2.exec(t);if(m){m=[0,m[2],m[3],m[1]];}else{re2=quickClass;m=re2.exec(t);}m[2]=m[2].replace(/\\/g,"");var elem=ret[ret.length-1];if(m[1]=="#"&&elem&&elem.getElementById&&!jQuery.isXMLDoc(elem)){var oid=elem.getElementById(m[2]);if((jQuery.browser.msie||jQuery.browser.opera)&&oid&&typeof oid.id=="string"&&oid.id!=m[2])oid=jQuery('[@id="'+m[2]+'"]',elem)[0];ret=r=oid&&(!m[3]||jQuery.nodeName(oid,m[3]))?[oid]:[];}else{for(var i=0;ret[i];i++){var tag=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];if(tag=="*"&&ret[i].nodeName.toLowerCase()=="object")tag="param";r=jQuery.merge(r,ret[i].getElementsByTagName(tag));}if(m[1]==".")r=jQuery.classFilter(r,m[2]);if(m[1]=="#"){var tmp=[];for(var i=0;r[i];i++)if(r[i].getAttribute("id")==m[2]){tmp=[r[i]];break;}r=tmp;}ret=r;}t=t.replace(re2,"");}}if(t){var val=jQuery.filter(t,r);ret=r=val.r;t=jQuery.trim(val.t);}}if(t)ret=[];if(ret&&context==ret[0])ret.shift();done=jQuery.merge(done,ret);return done;},classFilter:function(r,m,not){m=" "+m+" ";var tmp=[];for(var i=0;r[i];i++){var pass=(" "+r[i].className+" ").indexOf(m)>=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i<rl;i++){var a=r[i],z=a[jQuery.props[m[2]]||m[2]];if(z==null||/href|src|selected/.test(m[2]))z=jQuery.attr(a,m[2])||'';if((type==""&&!!z||type=="="&&z==m[5]||type=="!="&&z!=m[5]||type=="^="&&z&&!z.indexOf(m[5])||type=="$="&&z.substr(z.length-m[5].length)==m[5]||(type=="*="||type=="~=")&&z.indexOf(m[5])>=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i<rl;i++){var node=r[i],parentNode=node.parentNode,id=jQuery.data(parentNode);if(!merge[id]){var c=1;for(var n=parentNode.firstChild;n;n=n.nextSibling)if(n.nodeType==1)n.nodeIndex=c++;merge[id]=true;}var add=false;if(first==0){if(node.nodeIndex==last)add=true;}else if((node.nodeIndex-last)%first==0&&(node.nodeIndex-last)/first>=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[],cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&n!=elem)r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=this.proxy(fn,function(){return fn.apply(this,arguments);});handler.data=data;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){if(typeof jQuery!="undefined"&&!jQuery.event.triggered)return jQuery.event.handle.apply(arguments.callee.elem,arguments);});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else
for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event){data.unshift({type:type,target:elem,preventDefault:function(){},stopPropagation:function(){},timeStamp:now()});data[0][expando]=true;}data[0].type=type;if(exclusive)data[0].exclusive=true;var handle=jQuery.data(elem,"handle");if(handle)val=handle.apply(elem,data);if((!fn||(jQuery.nodeName(elem,'a')&&type=="click"))&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val,ret,namespace,all,handlers;event=arguments[0]=jQuery.event.fix(event||window.event);namespace=event.type.split(".");event.type=namespace[0];namespace=namespace[1];all=!namespace&&!event.exclusive;handlers=(jQuery.data(this,"events")||{})[event.type];for(var j in handlers){var handler=handlers[j];if(all||handler.type==namespace){event.handler=handler;event.data=handler.data;ret=handler.apply(this,arguments);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}return val;},fix:function(event){if(event[expando]==true)return event;var originalEvent=event;event={originalEvent:originalEvent};var props="altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target timeStamp toElement type view wheelDelta which".split(" ");for(var i=props.length;i;i--)event[props[i]]=originalEvent[props[i]];event[expando]=true;event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};event.timeStamp=event.timeStamp||now();if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=event.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},proxy:function(fn,proxy){proxy.guid=fn.guid=fn.guid||proxy.guid||this.guid++;return proxy;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){var one=jQuery.event.proxy(fn||data,function(event){jQuery(this).unbind(event,one);return(fn||data).apply(this,arguments);});return this.each(function(){jQuery.event.add(this,type,one,fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){return this[0]&&jQuery.event.trigger(type,data,this[0],false,fn);},toggle:function(fn){var args=arguments,i=1;while(i<args.length)jQuery.event.proxy(fn,args[i++]);return this.click(jQuery.event.proxy(fn,function(event){this.lastToggle=(this.lastToggle||0)%i;event.preventDefault();return args[this.lastToggle++].apply(this,arguments)||false;}));},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)fn.call(document,jQuery);else
jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.call(document);});jQuery.readyList=null;}jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}jQuery.ready();})();if(jQuery.browser.opera)document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i<document.styleSheets.length;i++)if(document.styleSheets[i].disabled){setTimeout(arguments.callee,0);return;}jQuery.ready();},false);if(jQuery.browser.safari){var numStyles;(function(){if(jQuery.isReady)return;if(document.readyState!="loaded"&&document.readyState!="complete"){setTimeout(arguments.callee,0);return;}if(numStyles===undefined)numStyles=jQuery("style, link[rel=stylesheet]").length;if(document.styleSheets.length!=numStyles){setTimeout(arguments.callee,0);return;}jQuery.ready();})();}jQuery.event.add(window,"load",jQuery.ready);}jQuery.each(("blur,focus,load,resize,scroll,unload,click,dblclick,"+"mousedown,mouseup,mousemove,mouseover,mouseout,change,select,"+"submit,keydown,keypress,keyup,error").split(","),function(i,name){jQuery.fn[name]=function(fn){return fn?this.bind(name,fn):this.trigger(name);};});var withinElement=function(event,elem){var parent=event.relatedTarget;while(parent&&parent!=elem)try{parent=parent.parentNode;}catch(error){parent=elem;}return parent==elem;};jQuery(window).bind("unload",function(){jQuery("*").add(document).unbind();});jQuery.fn.extend({_load:jQuery.fn.load,load:function(url,params,callback){if(typeof url!='string')return this._load(url);var off=url.indexOf(" ");if(off>=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("<div/>").append(res.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=now();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{url:location.href,global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));var jsonp,jsre=/=\?(&|$)/g,status,data,type=s.type.toUpperCase();if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(type=="GET"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&type=="GET"){var ts=now();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&type=="GET"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");var remote=/^(?:\w+:)?\/\/([^\/?#]+)/;if(s.dataType=="script"&&type=="GET"&&remote.test(s.url)&&remote.exec(s.url)[1]!=location.host){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xhr=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();if(s.username)xhr.open(type,s.url,s.async,s.username,s.password);else
xhr.open(type,s.url,s.async);try{if(s.data)xhr.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xhr.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");xhr.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend&&s.beforeSend(xhr,s)===false){s.global&&jQuery.active--;xhr.abort();return false;}if(s.global)jQuery.event.trigger("ajaxSend",[xhr,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xhr&&(xhr.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xhr)&&"error"||s.ifModified&&jQuery.httpNotModified(xhr,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xhr,s.dataType,s.dataFilter);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xhr.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else
jQuery.handleError(s,xhr,status);complete();if(s.async)xhr=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xhr){xhr.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xhr.send(s.data);}catch(e){jQuery.handleError(s,xhr,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xhr,s]);}function complete(){if(s.complete)s.complete(xhr,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xhr,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xhr;},handleError:function(s,xhr,status,e){if(s.error)s.error(xhr,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xhr,s,e]);},active:0,httpSuccess:function(xhr){try{return!xhr.status&&location.protocol=="file:"||(xhr.status>=200&&xhr.status<300)||xhr.status==304||xhr.status==1223||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpNotModified:function(xhr,url){try{var xhrRes=xhr.getResponseHeader("Last-Modified");return xhr.status==304||xhrRes==jQuery.lastModified[url]||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpData:function(xhr,type,filter){var ct=xhr.getResponseHeader("content-type"),xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0,data=xml?xhr.responseXML:xhr.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(filter)data=filter(data,type);if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else
for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else
s.push(encodeURIComponent(j)+"="+encodeURIComponent(jQuery.isFunction(a[j])?a[j]():a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle.apply(this,arguments):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall),p,hidden=jQuery(this).is(":hidden"),self=this;for(p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return opt.complete.call(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else
e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.call(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(elem){type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",jQuery.makeArray(array));}return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].call(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:jQuery.fx.speeds[opt.duration])||jQuery.fx.speeds.def;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.call(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.call(this.elem,this.now,this);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=now();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;i<timers.length;i++)if(!timers[i]())timers.splice(i--,1);if(!timers.length){clearInterval(jQuery.timerId);jQuery.timerId=null;}},13);}},show:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.show=true;this.custom(0,this.cur());if(this.prop=="width"||this.prop=="height")this.elem.style[this.prop]="1px";jQuery(this.elem).show();},hide:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0);},step:function(gotoEnd){var t=now();if(gotoEnd||t>this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done)this.options.complete.call(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.extend(jQuery.fx,{speeds:{slow:600,fast:200,def:400},step:{scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}}});jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),css=jQuery.curCSS,fixed=css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||css(offsetChild,"position")=="absolute"))||(mozilla&&css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l,10)||0;top+=parseInt(t,10)||0;}return results;};jQuery.fn.extend({position:function(){var left=0,top=0,results;if(this[0]){var offsetParent=this.offsetParent(),offset=this.offset(),parentOffset=/^body|html$/i.test(offsetParent[0].tagName)?{top:0,left:0}:offsetParent.offset();offset.top-=num(this,'marginTop');offset.left-=num(this,'marginLeft');parentOffset.top+=num(offsetParent,'borderTopWidth');parentOffset.left+=num(offsetParent,'borderLeftWidth');results={top:offset.top-parentOffset.top,left:offset.left-parentOffset.left};}return results;},offsetParent:function(){var offsetParent=this[0].offsetParent;while(offsetParent&&(!/^body|html$/i.test(offsetParent.tagName)&&jQuery.css(offsetParent,'position')=='static'))offsetParent=offsetParent.offsetParent;return jQuery(offsetParent);}});jQuery.each(['Left','Top'],function(i,name){var method='scroll'+name;jQuery.fn[method]=function(val){if(!this[0])return;return val!=undefined?this.each(function(){this==window||this==document?window.scrollTo(!i?val:jQuery(window).scrollLeft(),i?val:jQuery(window).scrollTop()):this[method]=val;}):this[0]==window||this[0]==document?self[i?'pageYOffset':'pageXOffset']||jQuery.boxModel&&document.documentElement[method]||document.body[method]:this[0][method];};});jQuery.each(["Height","Width"],function(i,name){var tl=i?"Left":"Top",br=i?"Right":"Bottom";jQuery.fn["inner"+name]=function(){return this[name.toLowerCase()]()+num(this,"padding"+tl)+num(this,"padding"+br);};jQuery.fn["outer"+name]=function(margin){return this["inner"+name]()+num(this,"border"+tl+"Width")+num(this,"border"+br+"Width")+(margin?num(this,"margin"+tl)+num(this,"margin"+br):0);};});})();/**
 * jQuery.Preload
 * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com
 * Dual licensed under MIT and GPL.
 * Date: 3/12/2008
 *
 * @projectDescription Multifunctional preloader
 * @author Ariel Flesler
 * @version 1.0.7
 *
 * @id jQuery.preload
 * @param {String, jQuery, Array< String, <a>, <link>, <img> >} original Collection of sources to preload
 * @param {Object} settings Hash of settings.
 *
 * @id jQuery.fn.preload
 * @param {Object} settings Hash of settings.
 * @return {jQuery} Returns the same jQuery object, for chaining.
 *
 * @example Link Mode:
 *	$.preload( '#images a' );
 *
 * @example Rollover Mode:
 *	$.preload( '#images img', {
 *		find:/\.(gif|jpg)/,
 *		replace:'_over.$1'
 *	});
 *
 * @example Src Mode:
 *	$.preload( [ 'red', 'blue', 'yellow' ], {
 *		base:'images/colors/',
 *		ext:'.jpg'
 *	});
 *
 * @example Placeholder Mode:
 *	$.preload( '#images img', {
 *		placeholder:'placeholder.jpg',
 *		notFound:'notfound.jpg'
 *	});
 *
 * @example Placeholder+Rollover Mode(High res):
 *	$.preload( '#images img', {
 *		placeholder:true,
 *		find:/\.(gif|jpg)/,
 *		replace:'_high.$1'
 *	});
 */
(function($) {

    var $preload = $.preload;
    $preload = function(original, settings) {
        if (original.split)//selector
        {
            original = $(original);
        }

        settings = $.extend({}, $preload.defaults, settings);
        var sources = $.map(original, function(source) {
            if (!source) {
                return; //skip
            }
            if (source.split)//URL Mode
            {
                return settings.base + source + settings.ext;
            }
            var url = source.src || source.href; //save the original source
            if (typeof settings.placeholder == 'string' && source.src)//Placeholder Mode, if it's an image, set it.
            {
                source.src = settings.placeholder;
            }
            if (url && settings.find)//Rollover mode
            {
                url = url.replace(settings.find, settings.replace);
            }
            return url || null; //skip if empty string
        });

        var data = {
            loaded: 0, //how many were loaded successfully
            failed: 0, //how many urls failed
            next: 0, //which one's the next image to load (index)
            done: 0, //how many urls were tried
            //found:false,//whether the last one was successful
            total: sources.length//how many images are being preloaded overall
        };

        if (!data.total)//nothing to preload
        {
            return finish();
        }

        var imgs = '<img/>', //ensure one
			thres = settings.threshold; //save a copy

        while (--thres > 0)//it could be oddly negative
        {
            imgs += '<img/>';
        }
        imgs = $(imgs).load(handler).error(handler).bind('abort', handler).each(fetch);

        function handler(e) {
            data.found = e.type == 'load';
            data.image = this.src;
            var orig = data.original;
            orig = original[this.index];
            data[data.found ? 'loaded' : 'failed']++;
            data.done++;
            if (settings.placeholder && orig.src)//special case when on placeholder mode
            {
                orig.src = data.found ? data.image : settings.notFound || orig.src;
            }
            if (settings.onComplete) {
                settings.onComplete(data);
            }
            if (data.done < data.total)//let's continue
            {
                fetch(0, this);
            }
            else {//we are finished
                if (imgs.unbind)//sometimes IE gets here before finishing line 84
                {
                    imgs.unbind('load').unbind('error').unbind('abort'); //cleanup
                }
                imgs = null;
                finish();
            }
        };
        function fetch(i, img, retry) {
            if ($.browser.msie && data.next && data.next % $preload.gap == 0 && !retry) {//IE problem, can't preload more than 15
                setTimeout(function() { fetch(i, img, true); }, 0);
                return false;
            }
            if (data.next == data.total) {
                return false; //no more to fetch
            }
            img.index = data.next; //save it, we'll need it.
            img.src = sources[data.next++];
            if (settings.onRequest) {
                data.image = img.src;
                data.original = original[data.next - 1];
                settings.onRequest(data);
            }
        };
        function finish() {
            if (settings.onFinish) {
                settings.onFinish(data);
            }
        };
    };

    // each time we load this amount and it's IE, we must rest for a while, make it lower if you get stack overflow.
    $preload.gap = 14;

    $preload.defaults = {
        threshold: 2, //how many images to load simultaneously
        base: '', //URL mode: a base url can be specified, it is prepended to all string urls
        ext: '', //URL mode:same as base, but it's appended after the original url.
        replace: ''//Rollover mode: replacement (can be left empty)
        /*
        find:null,//Rollover mode: a string or regex for the replacement
        notFound:''//Placeholder Mode: Optional url of an image to use when the original wasn't found
        placeholder:'',//Placeholder Mode: url of an image to set while loading
        onRequest:function( data ){ ... },//callback called every time a new url is requested
        onComplete:function( data ){ ... },//callback called every time a response is received(successful or not)
        onFinish:function( data ){ ... }//callback called after all the images were loaded(or failed)
        */
    };

    $.fn.preload = function(settings) {
        $preload(this, settings);
        return this;
    };

})(jQuery);/*
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 *
 * Uses the built in easing capabilities added In jQuery 1.1
 * to offer multiple easing options
 *
 * TERMS OF USE - jQuery Easing
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2008 George McGinley Smith
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this list of 
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list 
 * of conditions and the following disclaimer in the documentation and/or other materials 
 * provided with the distribution.
 * 
 * Neither the name of the author nor the names of contributors may be used to endorse 
 * or promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE. 
 *
*/

// t: current time, b: begInnIng value, c: change In value, d: duration
jQuery.easing['jswing'] = jQuery.easing['swing'];

jQuery.extend( jQuery.easing,
{
	def: 'easeOutQuad',
	swing: function (x, t, b, c, d) {
		//alert(jQuery.easing.default);
		return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
	},
	easeInQuad: function (x, t, b, c, d) {
		return c*(t/=d)*t + b;
	},
	easeOutQuad: function (x, t, b, c, d) {
		return -c *(t/=d)*(t-2) + b;
	},
	easeInOutQuad: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	easeInCubic: function (x, t, b, c, d) {
		return c*(t/=d)*t*t + b;
	},
	easeOutCubic: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	},
	easeInOutCubic: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	},
	easeInQuart: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t + b;
	},
	easeOutQuart: function (x, t, b, c, d) {
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	easeInOutQuart: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	},
	easeInQuint: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t*t + b;
	},
	easeOutQuint: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	easeInOutQuint: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	},
	easeInSine: function (x, t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	easeOutSine: function (x, t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},
	easeInOutSine: function (x, t, b, c, d) {
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	easeInExpo: function (x, t, b, c, d) {
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},
	easeOutExpo: function (x, t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	easeInOutExpo: function (x, t, b, c, d) {
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	},
	easeInCirc: function (x, t, b, c, d) {
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},
	easeOutCirc: function (x, t, b, c, d) {
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},
	easeInOutCirc: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	},
	easeInElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	},
	easeOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},
	//Copy of easeOutElastic as it was a little too bouncy!
	easeOutElasticTVI: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		// Changed variable is the -14 in this line vv
		return a*Math.pow(2,-14*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},
	easeInOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
	},
	easeInBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	easeOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},
	easeInOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158; 
		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	},
	easeInBounce: function (x, t, b, c, d) {
		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
	},
	easeOutBounce: function (x, t, b, c, d) {
		if ((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
	},
	easeInOutBounce: function (x, t, b, c, d) {
		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
	}
});

/*
 *
 * TERMS OF USE - EASING EQUATIONS
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2001 Robert Penner
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this list of 
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list 
 * of conditions and the following disclaimer in the documentation and/or other materials 
 * provided with the distribution.
 * 
 * Neither the name of the author nor the names of contributors may be used to endorse 
 * or promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE. 
 *
 *//**
 * jQuery.ScrollTo - Easy element scrolling using jQuery.
 * Copyright (c) 2007-2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 9/11/2008
 * @author Ariel Flesler
 * @version 1.4
 *
 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
 */
;(function(h){var m=h.scrollTo=function(b,c,g){h(window).scrollTo(b,c,g)};m.defaults={axis:'y',duration:1};m.window=function(b){return h(window).scrollable()};h.fn.scrollable=function(){return this.map(function(){var b=this.parentWindow||this.defaultView,c=this.nodeName=='#document'?b.frameElement||b:this,g=c.contentDocument||(c.contentWindow||c).document,i=c.setInterval;return c.nodeName=='IFRAME'||i&&h.browser.safari?g.body:i?g.documentElement:this})};h.fn.scrollTo=function(r,j,a){if(typeof j=='object'){a=j;j=0}if(typeof a=='function')a={onAfter:a};a=h.extend({},m.defaults,a);j=j||a.speed||a.duration;a.queue=a.queue&&a.axis.length>1;if(a.queue)j/=2;a.offset=n(a.offset);a.over=n(a.over);return this.scrollable().each(function(){var k=this,o=h(k),d=r,l,e={},p=o.is('html,body');switch(typeof d){case'number':case'string':if(/^([+-]=)?\d+(px)?$/.test(d)){d=n(d);break}d=h(d,this);case'object':if(d.is||d.style)l=(d=h(d)).offset()}h.each(a.axis.split(''),function(b,c){var g=c=='x'?'Left':'Top',i=g.toLowerCase(),f='scroll'+g,s=k[f],t=c=='x'?'Width':'Height',v=t.toLowerCase();if(l){e[f]=l[i]+(p?0:s-o.offset()[i]);if(a.margin){e[f]-=parseInt(d.css('margin'+g))||0;e[f]-=parseInt(d.css('border'+g+'Width'))||0}e[f]+=a.offset[i]||0;if(a.over[i])e[f]+=d[v]()*a.over[i]}else e[f]=d[i];if(/^\d+$/.test(e[f]))e[f]=e[f]<=0?0:Math.min(e[f],u(t));if(!b&&a.queue){if(s!=e[f])q(a.onAfterFirst);delete e[f]}});q(a.onAfter);function q(b){o.animate(e,j,a.easing,b&&function(){b.call(this,r,a)})};function u(b){var c='scroll'+b,g=k.ownerDocument;return p?Math.max(g.documentElement[c],g.body[c]):k[c]}}).end()};function n(b){return typeof b=='object'?b:{top:b,left:b}}})(jQuery);/**
 * jQuery.LocalScroll - Animated scrolling navigation, using anchors.
 * Copyright (c) 2007-2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 6/3/2008
 * @author Ariel Flesler
 * @version 1.2.6
 **/
;(function($){var g=location.href.replace(/#.*/,''),h=$.localScroll=function(a){$('body').localScroll(a)};h.defaults={duration:1e3,axis:'y',event:'click',stop:1};h.hash=function(a){a=$.extend({},h.defaults,a);a.hash=0;if(location.hash)setTimeout(function(){i(0,location,a)},0)};$.fn.localScroll=function(b){b=$.extend({},h.defaults,b);return(b.persistent||b.lazy)?this.bind(b.event,function(e){var a=$([e.target,e.target.parentNode]).filter(c)[0];a&&i(e,a,b)}):this.find('a,area').filter(c).bind(b.event,function(e){i(e,this,b)}).end().end();function c(){var a=this;return!!a.href&&!!a.hash&&a.href.replace(a.hash,'')==g&&(!b.filter||$(a).is(b.filter))}};function i(e,a,b){var c=a.hash.slice(1),d=document.getElementById(c)||document.getElementsByName(c)[0],f;if(d){e&&e.preventDefault();f=$(b.target||$.scrollTo.window());if(b.lock&&f.is(':animated')||b.onBefore&&b.onBefore.call(a,e,d,f)===!1)return;if(b.stop)f.queue('fx',[]).stop();f.scrollTo(d,b).trigger('notify.serialScroll',[d]);if(b.hash)f.queue(function(){location=a.hash;$(this).dequeue()})}}})(jQuery);/**
 * jQuery lightBox plugin
 * This jQuery plugin was inspired and based on Lightbox 2 by Lokesh Dhakar (http://www.huddletogether.com/projects/lightbox2/)
 * and adapted to me for use like a plugin from jQuery.
 * @name jquery-lightbox-0.5.js
 * @author Leandro Vieira Pinho - http://leandrovieira.com
 * @version 0.5
 * @date April 11, 2008
 * @category jQuery plugin
 * @copyright (c) 2008 Leandro Vieira Pinho (leandrovieira.com)
 * @license CC Attribution-No Derivative Works 2.5 Brazil - http://creativecommons.org/licenses/by-nd/2.5/br/deed.en_US
 * @example Visit http://leandrovieira.com/projects/jquery/lightbox/ for more informations about this jQuery plugin
 */

// Offering a Custom Alias suport - More info: http://docs.jquery.com/Plugins/Authoring#Custom_Alias
(function($) {
    /**
    * $ is an alias to jQuery object
    *
    */
    $.fn.lightBox = function(settings) {
        // Settings to configure the jQuery lightBox plugin how you like
        settings = jQuery.extend({
            // Configuration related to overlay
            overlayBgColor: '#e2e5e6', 	// (string) Background color to overlay; inform a hexadecimal value like: #RRGGBB. Where RR, GG, and BB are the hexadecimal values for the red, green, and blue values of the color.
            overlayOpacity: 0.86, 	// (integer) Opacity value to overlay; inform: 0.X. Where X are number from 0 to 9
            // Configuration related to navigation
            fixedNavigation: false, 	// (boolean) Boolean that informs if the navigation (next and prev button) will be fixed or not in the interface.
            // Configuration related to images
            imageLoading: '/i/lightbox-ajax-loader.gif', 	// (string) Path and the name of the loading icon
            imageBtnPrev: '/i/lightbox-btn-prev.gif', 		// (string) Path and the name of the prev button image
            imageBtnNext: '/i/lightbox-btn-next.gif', 		// (string) Path and the name of the next button image
            //imageBtnClose: '/i/lightbox-btn-close.gif', 	// (string) Path and the name of the close btn
            imageBlank: '/i/lightbox-blank.gif', 		// (string) Path and the name of a blank image (one pixel)
            // Configuration related to container image box
            containerBorderSize: 10, 		// (integer) If you adjust the padding in the CSS for the container, #lightbox-container-image-box, you will need to update this value
            containerResizeSpeed: 300, 	// (integer) Specify the resize duration of container image. These number are miliseconds. 400 is default.
            // Configuration related to texts in caption. For example: Image 2 of 8. You can alter either "Image" and "of" texts.
            txtImage: 'Image', // (string) Specify text "Image"
            txtOf: 'of', 	// (string) Specify text "of"
            // Configuration related to keyboard navigation
            keyToClose: 'c', 	// (string) (c = close) Letter to close the jQuery lightBox interface. Beyond this letter, the letter X and the SCAPE key is used to.
            keyToPrev: 'p', 	// (string) (p = previous) Letter to show the previous image
            keyToNext: 'n', 	// (string) (n = next) Letter to show the next image.
            // Don�t alter these variables in any way
            imageArray: [],
            activeImage: 0
        }, settings);
        // Caching the jQuery object with all elements matched
        var jQueryMatchedObj = this; // This, in this context, refer to jQuery object
        /**
        * Initializing the plugin calling the start function
        *
        * @return boolean false
        */
        function _initialize() {
            _start(this, jQueryMatchedObj); // This, in this context, refer to object (link) which the user have clicked
            return false; // Avoid the browser following the link
        }
        /**
        * Start the jQuery lightBox plugin
        *
        * @param object objClicked The object (link) whick the user have clicked
        * @param object jQueryMatchedObj The jQuery object with all elements matched
        */
        function _start(objClicked, jQueryMatchedObj) {
            // Hime some elements to avoid conflict with overlay in IE. These elements appear above the overlay.
            $('embed, object, select').css({ 'visibility': 'hidden' });
            // Call the function to create the markup structure; style some elements; assign events in some elements.
            _set_interface();
            // Unset total images in imageArray
            settings.imageArray.length = 0;
            // Unset image active information
            settings.activeImage = 0;
            // We have an image set? Or just an image? Let�s see it.
            if (jQueryMatchedObj.length == 1) {
                settings.imageArray.push(new Array(objClicked.getAttribute('href'), objClicked.getAttribute('title')));
            } else {
                // Add an Array (as many as we have), with href and title atributes, inside the Array that storage the images references		
                for (var i = 0; i < jQueryMatchedObj.length; i++) {
                    settings.imageArray.push(new Array(jQueryMatchedObj[i].getAttribute('href'), jQueryMatchedObj[i].getAttribute('title')));
                }
            }
            while (settings.imageArray[settings.activeImage][0] != objClicked.getAttribute('href')) {
                settings.activeImage++;
            }
            // Call the function that prepares image exibition
            _set_image_to_view();
        }
        /**
        * Create the jQuery lightBox plugin interface
        *
        * The HTML markup will be like that:
        <div id="jquery-overlay"></div>
        <div id="jquery-lightbox">
        <div id="lightbox-container-image-box">
        <div id="lightbox-container-image">
        <img src="../fotos/XX.jpg" id="lightbox-image">
        <div id="lightbox-nav">
        <a href="#" id="lightbox-nav-btnPrev"></a>
        <a href="#" id="lightbox-nav-btnNext"></a>
        </div>
        <div id="lightbox-loading">
        <a href="#" id="lightbox-loading-link">
        <img src="../images/lightbox-ico-loading.gif">
        </a>
        </div>
        </div>
        </div>
        <div id="lightbox-container-image-data-box">
        <div id="lightbox-container-image-data">
        <div id="lightbox-image-details">
        <span id="lightbox-image-details-caption"></span>
        <span id="lightbox-image-details-currentNumber"></span>
        </div>
        <div id="lightbox-secNav">
        <a href="#" id="lightbox-secNav-btnClose">
        <img src="../images/lightbox-btn-close.gif">
        </a>
        </div>
        </div>
        </div>
        </div>
        *
        */
        function _set_interface() {
            // Apply the HTML markup into body tag
            $('body').append('<div id="jquery-overlay"></div><div id="jquery-lightbox"><div id="lightbox-container-image-box"><div id="lightbox-container-image"><img id="lightbox-image"><div style="" id="lightbox-nav"><a href="#" id="lightbox-nav-btnPrev"></a><a href="#" id="lightbox-nav-btnNext"></a></div><div id="lightbox-loading"><a href="#" id="lightbox-loading-link"><img src="' + settings.imageLoading + '"></a></div></div></div><div id="lightbox-container-image-data-box"><div id="lightbox-container-image-data"><div id="lightbox-image-details"><span id="lightbox-image-details-caption"></span><span id="lightbox-image-details-currentNumber"></span></div><div id="lightbox-secNav"><a href="#" id="lightbox-secNav-btnClose"></a></div></div></div></div>');
            // Get page sizes
            var arrPageSizes = ___getPageSize();
            // Style overlay and show it
            $('#jquery-overlay').css({
                backgroundColor: settings.overlayBgColor,
                opacity: settings.overlayOpacity,
                width: arrPageSizes[0],
                height: arrPageSizes[1]
            }).fadeIn();
            // Get page scroll
            var arrPageScroll = ___getPageScroll();
            // Calculate top and left offset for the jquery-lightbox div object and show it
            $('#jquery-lightbox').css({
                top: arrPageScroll[1] + (arrPageSizes[3] / 10),
                left: arrPageScroll[0]
            }).show();
            // Assigning click events in elements to close overlay
            $('#jquery-overlay,#jquery-lightbox').click(function() {
                _finish();
            });
            // Assign the _finish function to lightbox-loading-link and lightbox-secNav-btnClose objects
            $('#lightbox-loading-link,#lightbox-secNav-btnClose').click(function() {
                _finish();
                return false;
            });
            // If window was resized, calculate the new overlay dimensions
            $(window).resize(function() {
                // Get page sizes
                var arrPageSizes = ___getPageSize();
                // Style overlay and show it
                $('#jquery-overlay').css({
                    width: arrPageSizes[0],
                    height: arrPageSizes[1]
                });
                // Get page scroll
                var arrPageScroll = ___getPageScroll();
                // Calculate top and left offset for the jquery-lightbox div object and show it
                $('#jquery-lightbox').css({
                    top: arrPageScroll[1] + (arrPageSizes[3] / 10),
                    left: arrPageScroll[0]
                });
            });
        }
        /**
        * Prepares image exibition; doing a image�s preloader to calculate it�s size
        *
        */
        function _set_image_to_view() { // show the loading
            // Show the loading
            $('#lightbox-loading').show();
            if (settings.fixedNavigation) {
                $('#lightbox-image,#lightbox-container-image-data-box,#lightbox-image-details-currentNumber').hide();
            } else {
                // Hide some elements
                $('#lightbox-image,#lightbox-nav,#lightbox-nav-btnPrev,#lightbox-nav-btnNext,#lightbox-container-image-data-box,#lightbox-image-details-currentNumber').hide();
            }
            // Image preload process
            var objImagePreloader = new Image();
            objImagePreloader.onload = function() {
                $('#lightbox-image').attr('src', settings.imageArray[settings.activeImage][0]);
                // Perfomance an effect in the image container resizing it
                _resize_container_image_box(objImagePreloader.width, objImagePreloader.height);
                //	clear onLoad, IE behaves irratically with animated gifs otherwise
                objImagePreloader.onload = function() { };
            };
            objImagePreloader.src = settings.imageArray[settings.activeImage][0];
        }
        /**
        * Perfomance an effect in the image container resizing it
        *
        * @param integer intImageWidth The image�s width that will be showed
        * @param integer intImageHeight The image�s height that will be showed
        */
        function _resize_container_image_box(intImageWidth, intImageHeight) {
            // Get current width and height
            var intCurrentWidth = $('#lightbox-container-image-box').width();
            var intCurrentHeight = $('#lightbox-container-image-box').height();
            // Get the width and height of the selected image plus the padding
            var intWidth = (intImageWidth + (settings.containerBorderSize * 2)); // Plus the image�s width and the left and right padding value
            var intHeight = (intImageHeight + (settings.containerBorderSize * 2)); // Plus the image�s height and the left and right padding value
            // Diferences
            var intDiffW = intCurrentWidth - intWidth;
            var intDiffH = intCurrentHeight - intHeight;
            // Perfomance the effect
            $('#lightbox-container-image-box').animate({ width: intWidth, height: intHeight }, settings.containerResizeSpeed, function() { _show_image(); });
            if ((intDiffW == 0) && (intDiffH == 0)) {
                if ($.browser.msie) {
                    ___pause(250);
                } else {
                    ___pause(100);
                }
            }
            $('#lightbox-container-image-data-box').css({ width: intImageWidth });
            $('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css({ height: intImageHeight + (settings.containerBorderSize * 2) });
        }
        /**
        * Show the prepared image
        *
        */
        function _show_image() {
            $('#lightbox-loading').hide();
            $('#lightbox-image').fadeIn(function() {
                _show_image_data();
                _set_navigation();
            });
            _preload_neighbor_images();
        }
        /**
        * Show the image information
        *
        */
        function _show_image_data() {
            $('#lightbox-container-image-data-box').slideDown('fast');
            $('#lightbox-container-image-box').css({ borderBottom: 'none' });
            $('#lightbox-image-details-caption').hide();
            if (settings.imageArray[settings.activeImage][1]) {
                $('#lightbox-image-details-caption').html(settings.imageArray[settings.activeImage][1]).show();
            }
            // If we have a image set, display 'Image X of X'
            if (settings.imageArray.length > 1) {
                $('#lightbox-image-details-currentNumber').html(settings.txtImage + ' ' + (settings.activeImage + 1) + ' ' + settings.txtOf + ' ' + settings.imageArray.length).show();
            }
        }
        /**
        * Display the button navigations
        *
        */
        function _set_navigation() {
            $('#lightbox-nav').show();

            // Instead to define this configuration in CSS file, we define here. And it�s need to IE. Just.
            $('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css({ 'background': 'transparent url(' + settings.imageBlank + ') no-repeat' });

            // Show the prev button, if not the first image in set
            if (settings.activeImage != 0) {
                if (settings.fixedNavigation) {
                    $('#lightbox-nav-btnPrev').css({ 'background': 'url(' + settings.imageBtnPrev + ') left 50% no-repeat' })
						.unbind()
						.bind('click', function() {
						    settings.activeImage = settings.activeImage - 1;
						    _set_image_to_view();
						    return false;
						});
                } else {
                    // Show the images button for Next buttons
                    $('#lightbox-nav-btnPrev').unbind().hover(function() {
                        $(this).css({ 'background': 'url(' + settings.imageBtnPrev + ') left 50% no-repeat' });
                    }, function() {
                        $(this).css({ 'background': 'transparent url(' + settings.imageBlank + ') no-repeat' });
                    }).show().bind('click', function() {
                        settings.activeImage = settings.activeImage - 1;
                        _set_image_to_view();
                        return false;
                    });
                }
            }

            // Show the next button, if not the last image in set
            if (settings.activeImage != (settings.imageArray.length - 1)) {
                if (settings.fixedNavigation) {
                    $('#lightbox-nav-btnNext').css({ 'background': 'url(' + settings.imageBtnNext + ') right 50% no-repeat' })
						.unbind()
						.bind('click', function() {
						    settings.activeImage = settings.activeImage + 1;
						    _set_image_to_view();
						    return false;
						});
                } else {
                    // Show the images button for Next buttons
                    $('#lightbox-nav-btnNext').unbind().hover(function() {
                        $(this).css({ 'background': 'url(' + settings.imageBtnNext + ') right 50% no-repeat' });
                    }, function() {
                        $(this).css({ 'background': 'transparent url(' + settings.imageBlank + ') no-repeat' });
                    }).show().bind('click', function() {
                        settings.activeImage = settings.activeImage + 1;
                        _set_image_to_view();
                        return false;
                    });
                }
            }
            // Enable keyboard navigation
            _enable_keyboard_navigation();
        }
        /**
        * Enable a support to keyboard navigation
        *
        */
        function _enable_keyboard_navigation() {
            $(document).keydown(function(objEvent) {
                _keyboard_action(objEvent);
            });
        }
        /**
        * Disable the support to keyboard navigation
        *
        */
        function _disable_keyboard_navigation() {
            $(document).unbind();
        }
        /**
        * Perform the keyboard actions
        *
        */
        function _keyboard_action(objEvent) {
            // To ie
            if (objEvent == null) {
                keycode = event.keyCode;
                escapeKey = 27;
                // To Mozilla
            } else {
                keycode = objEvent.keyCode;
                escapeKey = objEvent.DOM_VK_ESCAPE;
            }
            // Get the key in lower case form
            key = String.fromCharCode(keycode).toLowerCase();
            // Verify the keys to close the ligthBox
            if ((key == settings.keyToClose) || (key == 'x') || (keycode == escapeKey)) {
                _finish();
            }
            // Verify the key to show the previous image
            if ((key == settings.keyToPrev) || (keycode == 37)) {
                // If we�re not showing the first image, call the previous
                if (settings.activeImage != 0) {
                    settings.activeImage = settings.activeImage - 1;
                    _set_image_to_view();
                    _disable_keyboard_navigation();
                }
            }
            // Verify the key to show the next image
            if ((key == settings.keyToNext) || (keycode == 39)) {
                // If we�re not showing the last image, call the next
                if (settings.activeImage != (settings.imageArray.length - 1)) {
                    settings.activeImage = settings.activeImage + 1;
                    _set_image_to_view();
                    _disable_keyboard_navigation();
                }
            }
        }
        /**
        * Preload prev and next images being showed
        *
        */
        function _preload_neighbor_images() {
            if ((settings.imageArray.length - 1) > settings.activeImage) {
                objNext = new Image();
                objNext.src = settings.imageArray[settings.activeImage + 1][0];
            }
            if (settings.activeImage > 0) {
                objPrev = new Image();
                objPrev.src = settings.imageArray[settings.activeImage - 1][0];
            }
        }
        /**
        * Remove jQuery lightBox plugin HTML markup
        *
        */
        function _finish() {
            $('#jquery-lightbox').remove();
            $('#jquery-overlay').fadeOut(function() { $('#jquery-overlay').remove(); });
            // Show some elements to avoid conflict with overlay in IE. These elements appear above the overlay.
            $('embed, object, select').css({ 'visibility': 'visible' });
        }
        /**
        / THIRD FUNCTION
        * getPageSize() by quirksmode.com
        *
        * @return Array Return an array with page width, height and window width, height
        */
        function ___getPageSize() {
            var xScroll, yScroll;
            if (window.innerHeight && window.scrollMaxY) {
                xScroll = window.innerWidth + window.scrollMaxX;
                yScroll = window.innerHeight + window.scrollMaxY;
            } else if (document.body.scrollHeight > document.body.offsetHeight) { // all but Explorer Mac
                xScroll = document.body.scrollWidth;
                yScroll = document.body.scrollHeight;
            } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
                xScroll = document.body.offsetWidth;
                yScroll = document.body.offsetHeight;
            }
            var windowWidth, windowHeight;
            if (self.innerHeight) {	// all except Explorer
                if (document.documentElement.clientWidth) {
                    windowWidth = document.documentElement.clientWidth;
                } else {
                    windowWidth = self.innerWidth;
                }
                windowHeight = self.innerHeight;
            } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
                windowWidth = document.documentElement.clientWidth;
                windowHeight = document.documentElement.clientHeight;
            } else if (document.body) { // other Explorers
                windowWidth = document.body.clientWidth;
                windowHeight = document.body.clientHeight;
            }
            // for small pages with total height less then height of the viewport
            if (yScroll < windowHeight) {
                pageHeight = windowHeight;
            } else {
                pageHeight = yScroll;
            }
            // for small pages with total width less then width of the viewport
            if (xScroll < windowWidth) {
                pageWidth = xScroll;
            } else {
                pageWidth = windowWidth;
            }
            arrayPageSize = new Array(pageWidth, pageHeight, windowWidth, windowHeight);
            return arrayPageSize;
        }
        /**
        / THIRD FUNCTION
        * getPageScroll() by quirksmode.com
        *
        * @return Array Return an array with x,y page scroll values.
        */
        function ___getPageScroll() {
            var xScroll, yScroll;
            if (self.pageYOffset) {
                yScroll = self.pageYOffset;
                xScroll = self.pageXOffset;
            } else if (document.documentElement && document.documentElement.scrollTop) {	 // Explorer 6 Strict
                yScroll = document.documentElement.scrollTop;
                xScroll = document.documentElement.scrollLeft;
            } else if (document.body) {// all other Explorers
                yScroll = document.body.scrollTop;
                xScroll = document.body.scrollLeft;
            }
            arrayPageScroll = new Array(xScroll, yScroll);
            return arrayPageScroll;
        }
        /**
        * Stop the code execution from a escified time in milisecond
        *
        */
        function ___pause(ms) {
            var date = new Date();
            curDate = null;
            do { var curDate = new Date(); }
            while (curDate - date < ms);
        }
        // Return the jQuery object for chaining. The unbind method is used to avoid click conflict when the plugin is called more than once
        return this.unbind('click').click(_initialize);
    };
})(jQuery);   // Call and execute the function immediately passing the jQuery object
if(!this.JSON){JSON=function(){function f(n){return n<10?'0'+n:n;}Date.prototype.toJSON=function(key){return this.getUTCFullYear()+'-'+f(this.getUTCMonth()+1)+'-'+f(this.getUTCDate())+'T'+f(this.getUTCHours())+':'+f(this.getUTCMinutes())+':'+f(this.getUTCSeconds())+'Z';};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapeable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapeable.lastIndex=0;return escapeable.test(string)?'"'+string.replace(escapeable,function(a){var c=meta[a];if(typeof c==='string'){return c;}return'\\u'+('0000'+(+(a.charCodeAt(0))).toString(16)).slice(-4);})+'"':'"'+string+'"';}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);}if(typeof rep==='function'){value=rep.call(holder,key,value);}switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}gap+=indent;partial=[];if(typeof value.length==='number'&&!(value.propertyIsEnumerable('length'))){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||'null';}v=partial.length===0?'[]':gap?'[\n'+gap+partial.join(',\n'+gap)+'\n'+mind+']':'['+partial.join(',')+']';gap=mind;return v;}if(rep&&typeof rep==='object'){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==='string'){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}v=partial.length===0?'{}':gap?'{\n'+gap+partial.join(',\n'+gap)+'\n'+mind+'}':'{'+partial.join(',')+'}';gap=mind;return v;}}return{stringify:function(value,replacer,space){var i;gap='';indent='';if(typeof space==='number'){for(i=0;i<space;i+=1){indent+=' ';}}else if(typeof space==='string'){indent=space;}rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof replacer!=='object'||typeof replacer.length!=='number')){throw new Error('JSON.stringify');}return str('',{'':value});},parse:function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==='object'){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v;}else{delete value[k];}}}}return reviver.call(holder,key,value);}cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return'\\u'+('0000'+(+(a.charCodeAt(0))).toString(16)).slice(-4);});}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return typeof reviver==='function'?walk({'':j},''):j;}throw new SyntaxError('JSON.parse');}};}();}/**
 * TrimPath Template. Release 1.0.38.
 * Copyright (C) 2004, 2005 Metaha.
 * 
 * TrimPath Template is licensed under the GNU General Public License
 * and the Apache License, Version 2.0, as follows:
 *
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed WITHOUT ANY WARRANTY; without even the 
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var TrimPath;

// TODO: Debugging mode vs stop-on-error mode - runtime flag.
// TODO: Handle || (or) characters and backslashes.
// TODO: Add more modifiers.

(function() {               // Using a closure to keep global namespace clean.
    if (TrimPath == null) {
        TrimPath = {};
    }
    if (TrimPath.evalEx == null) {
        TrimPath.evalEx = function(src) { return eval(src); };
    }

    var UNDEFINED;
    if (Array.prototype.pop == null)  // IE 5.x fix from Igor Poteryaev.
    {
        Array.prototype.pop = function() {
            if (this.length === 0) { return UNDEFINED; }
            return this[--this.length];
        };
    }
    if (Array.prototype.push == null) // IE 5.x fix from Igor Poteryaev.
    {
        Array.prototype.push = function() {
            for (var i = 0; i < arguments.length; ++i) { this[this.length] = arguments[i]; }
            return this.length;
        };
    }

    TrimPath.parseTemplate = function(tmplContent, optTmplName, optEtc) {
        if (optEtc == null) {
            optEtc = TrimPath.parseTemplate_etc;
        }

        var funcSrc = parse(tmplContent, optTmplName, optEtc);
        var func = TrimPath.evalEx(funcSrc, optTmplName, 1);
        if (func != null) {
            return new optEtc.Template(optTmplName, tmplContent, funcSrc, func, optEtc);
        }

        return null;
    };

    try {
        String.prototype.process = function(context, optFlags) {
            var template = TrimPath.parseTemplate(this, null);
            if (template != null) {
                return template.process(context, optFlags);
            }
            return this;
        };
    } catch (e) { // Swallow exception, such as when String.prototype is sealed.
    }

    TrimPath.parseTemplate_etc = {};            // Exposed for extensibility.
    TrimPath.parseTemplate_etc.statementTag = "forelse|for|if|elseif|else|var|macro";
    TrimPath.parseTemplate_etc.statementDef = { // Lookup table for statement tags.
        "if": { delta: 1, prefix: "if (", suffix: ") {", paramMin: 1 },
        "else": { delta: 0, prefix: "} else {" },
        "elseif": { delta: 0, prefix: "} else if (", suffix: ") {", paramDefault: "true" },
        "/if": { delta: -1, prefix: "}" },
        "for": { delta: 1, paramMin: 3,
            prefixFunc: function(stmtParts, state, tmplName, etc) {
                if (stmtParts[2] != "in") {
                    throw new etc.ParseError(tmplName, state.line, "bad for loop statement: " + stmtParts.join(' '));
                }
                var iterVar = stmtParts[1];
                var listVar = "__LIST__" + iterVar;
                return ["var ", listVar, " = ", stmtParts[3], ";",
                // Fix from Ross Shaull for hash looping, make sure that we have an array of loop lengths to treat like a stack.
                             "var __LENGTH_STACK__;",
                             "if (typeof(__LENGTH_STACK__) == 'undefined' || !__LENGTH_STACK__.length) __LENGTH_STACK__ = new Array();",
                             "__LENGTH_STACK__[__LENGTH_STACK__.length] = 0;", // Push a new for-loop onto the stack of loop lengths.
                             "if ((", listVar, ") != null) { ",
                             "var ", iterVar, "_ct = 0;",       // iterVar_ct variable, added by B. Bittman     
                             "for (var ", iterVar, "_index in ", listVar, ") { ",
                             iterVar, "_ct++;",
                             "if (typeof(", listVar, "[", iterVar, "_index]) == 'function') {continue;}", // IE 5.x fix from Igor Poteryaev.
                             "__LENGTH_STACK__[__LENGTH_STACK__.length - 1]++;",
                             "var ", iterVar, " = ", listVar, "[", iterVar, "_index];"].join("");
            }
        },
        "forelse": { delta: 0, prefix: "} } if (__LENGTH_STACK__[__LENGTH_STACK__.length - 1] == 0) { if (", suffix: ") {", paramDefault: "true" },
        "/for": { delta: -1, prefix: "} }; delete __LENGTH_STACK__[__LENGTH_STACK__.length - 1];" }, // Remove the just-finished for-loop from the stack of loop lengths.
        "var": { delta: 0, prefix: "var ", suffix: ";" },
        "macro": { delta: 1,
            prefixFunc: function(stmtParts, state, tmplName, etc) {
                var macroName = stmtParts[1].split('(')[0];
                return ["var ", macroName, " = function",
                                   stmtParts.slice(1).join(' ').substring(macroName.length),
                                   "{ var _OUT_arr = []; var _OUT = { write: function(m) { if (m) _OUT_arr.push(m); } }; "].join('');
            }
        },
        "/macro": { delta: -1, prefix: " return _OUT_arr.join(''); };" }
    };
    TrimPath.parseTemplate_etc.modifierDef = {
        "eat": function(v) { return ""; },
        "escape": function(s) { return String(s).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); },
        "capitalize": function(s) { return String(s).toUpperCase(); },
        "default": function(s, d) { return s != null ? s : d; }
    };
    TrimPath.parseTemplate_etc.modifierDef.h = TrimPath.parseTemplate_etc.modifierDef.escape;

    TrimPath.parseTemplate_etc.Template = function(tmplName, tmplContent, funcSrc, func, etc) {
        this.process = function(context, flags) {
            if (context == null) {
                context = {};
            }
            if (context._MODIFIERS == null) {
                context._MODIFIERS = {};
            }
            if (context.defined == null) {
                context.defined = function(str) { return (context[str] != undefined); };
            }
            for (var k in etc.modifierDef) {
                if (context._MODIFIERS[k] == null) {
                    context._MODIFIERS[k] = etc.modifierDef[k];
                }
            }
            if (flags == null) {
                flags = {};
            }
            var resultArr = [];
            var resultOut = { write: function(m) { resultArr.push(m); } };
            try {
                func(resultOut, context, flags);
            } catch (e) {
                if (flags.throwExceptions == true) {
                    throw e;
                }
                var result = new String(resultArr.join("") + "[ERROR: " + e.toString() + (e.message ? '; ' + e.message : '') + "]");
                result["exception"] = e;
                return result;
            }
            return resultArr.join("");
        };
        this.name = tmplName;
        this.source = tmplContent;
        this.sourceFunc = funcSrc;
        this.toString = function() { return "TrimPath.Template [" + tmplName + "]"; };
    };
    TrimPath.parseTemplate_etc.ParseError = function(name, line, message) {
        this.name = name;
        this.line = line;
        this.message = message;
    };
    TrimPath.parseTemplate_etc.ParseError.prototype.toString = function() {
        return ("TrimPath template ParseError in " + this.name + ": line " + this.line + ", " + this.message);
    };

    var parse = function(body, tmplName, etc) {
        body = cleanWhiteSpace(body);
        var funcText = ["var TrimPath_Template_TEMP = function(_OUT, _CONTEXT, _FLAGS) { with (_CONTEXT) {"];
        var state = { stack: [], line: 1 };                              // TODO: Fix line number counting.
        var endStmtPrev = -1;
        while (endStmtPrev + 1 < body.length) {
            var begStmt = endStmtPrev;
            // Scan until we find some statement markup.
            begStmt = body.indexOf("{", begStmt + 1);
            while (begStmt >= 0) {
                var endStmt = body.indexOf('}', begStmt + 1);
                var stmt = body.substring(begStmt, endStmt);
                var blockrx = stmt.match(/^\{(cdata|minify|eval)/); // From B. Bittman, minify/eval/cdata implementation.
                if (blockrx) {
                    var blockType = blockrx[1];
                    var blockMarkerBeg = begStmt + blockType.length + 1;
                    var blockMarkerEnd = body.indexOf('}', blockMarkerBeg);
                    if (blockMarkerEnd >= 0) {
                        var blockMarker;
                        if (blockMarkerEnd - blockMarkerBeg <= 0) {
                            blockMarker = "{/" + blockType + "}";
                        } else {
                            blockMarker = body.substring(blockMarkerBeg + 1, blockMarkerEnd);
                        }

                        var blockEnd = body.indexOf(blockMarker, blockMarkerEnd + 1);
                        if (blockEnd >= 0) {
                            emitSectionText(body.substring(endStmtPrev + 1, begStmt), funcText);

                            var blockText = body.substring(blockMarkerEnd + 1, blockEnd);
                            if (blockType == 'cdata') {
                                emitText(blockText, funcText);
                            } else if (blockType == 'minify') {
                                emitText(scrubWhiteSpace(blockText), funcText);
                            } else if (blockType == 'eval') {
                                if (blockText != null && blockText.length > 0) // From B. Bittman, eval should not execute until process().
                                {
                                    funcText.push('_OUT.write( (function() { ' + blockText + ' })() );');
                                }
                            }
                            begStmt = endStmtPrev = blockEnd + blockMarker.length - 1;
                        }
                    }
                } else if (body.charAt(begStmt - 1) != '$' &&               // Not an expression or backslashed,
                           body.charAt(begStmt - 1) != '\\') {              // so check if it is a statement tag.
                    var offset = (body.charAt(begStmt + 1) == '/' ? 2 : 1); // Close tags offset of 2 skips '/'.
                    // 10 is larger than maximum statement tag length.
                    if (body.substring(begStmt + offset, begStmt + 10 + offset).search(TrimPath.parseTemplate_etc.statementTag) == 0) {
                        break;                                              // Found a match.
                    }
                }
                begStmt = body.indexOf("{", begStmt + 1);
            }
            if (begStmt < 0)                              // In "a{for}c", begStmt will be 1.
            {
                break;
            }
            var endStmt = body.indexOf("}", begStmt + 1); // In "a{for}c", endStmt will be 5.
            if (endStmt < 0) {
                break;
            }
            emitSectionText(body.substring(endStmtPrev + 1, begStmt), funcText);
            emitStatement(body.substring(begStmt, endStmt + 1), state, funcText, tmplName, etc);
            endStmtPrev = endStmt;
        }
        emitSectionText(body.substring(endStmtPrev + 1), funcText);
        if (state.stack.length != 0) {
            throw new etc.ParseError(tmplName, state.line, "unclosed, unmatched statement(s): " + state.stack.join(","));
        }
        funcText.push("}}; TrimPath_Template_TEMP");
        return funcText.join("");
    };

    var emitStatement = function(stmtStr, state, funcText, tmplName, etc) {
        var parts = stmtStr.slice(1, -1).split(' ');
        var stmt = etc.statementDef[parts[0]]; // Here, parts[0] == for/if/else/...
        if (stmt == null) {                    // Not a real statement.
            emitSectionText(stmtStr, funcText);
            return;
        }
        if (stmt.delta < 0) {
            if (state.stack.length <= 0) {
                throw new etc.ParseError(tmplName, state.line, "close tag does not match any previous statement: " + stmtStr);
            }
            state.stack.pop();
        }
        if (stmt.delta > 0) {
            state.stack.push(stmtStr);
        }

        if (stmt.paramMin != null &&
            stmt.paramMin >= parts.length) {
            throw new etc.ParseError(tmplName, state.line, "statement needs more parameters: " + stmtStr);
        }
        if (stmt.prefixFunc != null) {
            funcText.push(stmt.prefixFunc(parts, state, tmplName, etc));
        }
        else {
            funcText.push(stmt.prefix);
        }
        if (stmt.suffix != null) {
            if (parts.length <= 1) {
                if (stmt.paramDefault != null) {
                    funcText.push(stmt.paramDefault);
                }
            } else {
                for (var i = 1; i < parts.length; i++) {
                    if (i > 1) {
                        funcText.push(' ');
                        funcText.push(parts[i]);
                    }
                }
            }
            funcText.push(stmt.suffix);
        }
    };

    var emitSectionText = function(text, funcText) {
        if (text.length <= 0) {
            return;
        }
        var nlPrefix = 0;               // Index to first non-newline in prefix.
        var nlSuffix = text.length - 1; // Index to first non-space/tab in suffix.
        while (nlPrefix < text.length && (text.charAt(nlPrefix) == '\n')) {
            nlPrefix++;
        }
        while (nlSuffix >= 0 && (text.charAt(nlSuffix) == ' ' || text.charAt(nlSuffix) == '\t')) {
            nlSuffix--;
        }
        if (nlSuffix < nlPrefix) {
            nlSuffix = nlPrefix;
        }
        if (nlPrefix > 0) {
            funcText.push('if (_FLAGS.keepWhitespace == true) _OUT.write("');
            var s = text.substring(0, nlPrefix).replace('\n', '\\n'); // A macro IE fix from BJessen.
            if (s.charAt(s.length - 1) == '\n') {
                s = s.substring(0, s.length - 1);
            }
            funcText.push(s);
            funcText.push('");');
        }
        var lines = text.substring(nlPrefix, nlSuffix + 1).split('\n');
        for (var i = 0; i < lines.length; i++) {
            emitSectionTextLine(lines[i], funcText);
            if (i < lines.length - 1) {
                funcText.push('_OUT.write("\\n");\n');
            }
        }
        if (nlSuffix + 1 < text.length) {
            funcText.push('if (_FLAGS.keepWhitespace == true) _OUT.write("');
            var s = text.substring(nlSuffix + 1).replace('\n', '\\n');
            if (s.charAt(s.length - 1) == '\n') {
                s = s.substring(0, s.length - 1);
            }
            funcText.push(s);
            funcText.push('");');
        }
    };

    var emitSectionTextLine = function(line, funcText) {
        var endMarkPrev = '}';
        var endExprPrev = -1;
        while (endExprPrev + endMarkPrev.length < line.length) {
            var begMark = "${", endMark = "}";
            var begExpr = line.indexOf(begMark, endExprPrev + endMarkPrev.length); // In "a${b}c", begExpr == 1
            if (begExpr < 0) {
                break;
            }
            if (line.charAt(begExpr + 2) == '%') {
                begMark = "${%";
                endMark = "%}";
            }
            var endExpr = line.indexOf(endMark, begExpr + begMark.length);         // In "a${b}c", endExpr == 4;
            if (endExpr < 0) {
                break;
            }
            emitText(line.substring(endExprPrev + endMarkPrev.length, begExpr), funcText);
            // Example: exprs == 'firstName|default:"John Doe"|capitalize'.split('|')
            var exprArr = line.substring(begExpr + begMark.length, endExpr).replace(/\|\|/g, "#@@#").split('|');
            for (var k in exprArr) {
                if (exprArr[k].replace) // IE 5.x fix from Igor Poteryaev.
                {
                    exprArr[k] = exprArr[k].replace(/#@@#/g, '||');
                }
            }
            funcText.push('_OUT.write(');
            emitExpression(exprArr, exprArr.length - 1, funcText);
            funcText.push(');');
            endExprPrev = endExpr;
            endMarkPrev = endMark;
        }
        emitText(line.substring(endExprPrev + endMarkPrev.length), funcText);
    };

    var emitText = function(text, funcText) {
        if (text == null ||
            text.length <= 0) {
            return;
        }
        text = text.replace(/\\/g, '\\\\');
        text = text.replace(/\n/g, '\\n');
        text = text.replace(/"/g, '\\"');
        funcText.push('_OUT.write("');
        funcText.push(text);
        funcText.push('");');
    };

    var emitExpression = function(exprArr, index, funcText) {
        // Ex: foo|a:x|b:y1,y2|c:z1,z2 is emitted as c(b(a(foo,x),y1,y2),z1,z2)
        var expr = exprArr[index]; // Ex: exprArr == [firstName,capitalize,default:"John Doe"]
        if (index <= 0) {          // Ex: expr    == 'default:"John Doe"'
            funcText.push(expr);
            return;
        }
        var parts = expr.split(':');
        funcText.push('_MODIFIERS["');
        funcText.push(parts[0]); // The parts[0] is a modifier function name, like capitalize.
        funcText.push('"](');
        emitExpression(exprArr, index - 1, funcText);
        if (parts.length > 1) {
            funcText.push(',');
            funcText.push(parts[1]);
        }
        funcText.push(')');
    };

    var cleanWhiteSpace = function(result) {
        result = result.replace(/\t/g, "    ");
        result = result.replace(/\r\n/g, "\n");
        result = result.replace(/\r/g, "\n");
        result = result.replace(/^(\s*\S*(\s+\S+)*)\s*$/, '$1'); // Right trim by Igor Poteryaev.
        return result;
    };

    var scrubWhiteSpace = function(result) {
        result = result.replace(/^\s+/g, "");
        result = result.replace(/\s+$/g, "");
        result = result.replace(/\s+/g, " ");
        result = result.replace(/^(\s*\S*(\s+\S+)*)\s*$/, '$1'); // Right trim by Igor Poteryaev.
        return result;
    };

    // The DOM helper functions depend on DOM/DHTML, so they only work in a browser.
    // However, these are not considered core to the engine.
    //
    TrimPath.parseDOMTemplate = function(elementId, optDocument, optEtc) {
        if (optDocument == null) {
            optDocument = document;
        }
        var element = optDocument.getElementById(elementId);
        var content = element.value;     // Like textarea.value.
        if (content == null) {
            content = element.innerHTML; // Like textarea.innerHTML.
        }
        content = content.replace(/&lt;/g, "<").replace(/&gt;/g, ">");
        return TrimPath.parseTemplate(content, elementId, optEtc);
    };

    TrimPath.processDOMTemplate = function(elementId, context, optFlags, optDocument, optEtc) {
        return TrimPath.parseDOMTemplate(elementId, optDocument, optEtc).process(context, optFlags);
    };
})();
/*****************************************************************************
scalable Inman Flash Replacement (sIFR) version 3, revision 436.

Copyright 2006 – 2008 Mark Wubben, <http://novemberborn.net/>

Older versions:
* IFR by Shaun Inman
* sIFR 1.0 by Mike Davidson, Shaun Inman and Tomas Jogin
* sIFR 2.0 by Mike Davidson, Shaun Inman, Tomas Jogin and Mark Wubben

See also <http://novemberborn.net/sifr3> and <http://wiki.novemberborn.net/sifr3>.

This software is licensed and provided under the CC-GNU LGPL.
See <http://creativecommons.org/licenses/LGPL/2.1/>
*****************************************************************************/

var sIFR=new function(){var O=this;var E={ACTIVE:"sIFR-active",REPLACED:"sIFR-replaced",IGNORE:"sIFR-ignore",ALTERNATE:"sIFR-alternate",CLASS:"sIFR-class",LAYOUT:"sIFR-layout",FLASH:"sIFR-flash",FIX_FOCUS:"sIFR-fixfocus",DUMMY:"sIFR-dummy"};E.IGNORE_CLASSES=[E.REPLACED,E.IGNORE,E.ALTERNATE];this.MIN_FONT_SIZE=6;this.MAX_FONT_SIZE=126;this.FLASH_PADDING_BOTTOM=5;this.VERSION="436";this.isActive=false;this.isEnabled=true;this.fixHover=true;this.autoInitialize=true;this.setPrefetchCookie=true;this.cookiePath="/";this.domains=[];this.forceWidth=true;this.fitExactly=false;this.forceTextTransform=true;this.useDomLoaded=true;this.useStyleCheck=false;this.hasFlashClassSet=false;this.repaintOnResize=true;this.replacements=[];var L=0;var R=false;function Y(){}function D(c){function d(e){return e.toLocaleUpperCase()}this.normalize=function(e){return e.replace(/\n|\r|\xA0/g,D.SINGLE_WHITESPACE).replace(/\s+/g,D.SINGLE_WHITESPACE)};this.textTransform=function(e,f){switch(e){case"uppercase":return f.toLocaleUpperCase();case"lowercase":return f.toLocaleLowerCase();case"capitalize":return f.replace(/^\w|\s\w/g,d)}return f};this.toHexString=function(e){if(e.charAt(0)!="#"||e.length!=4&&e.length!=7){return e}e=e.substring(1);return"0x"+(e.length==3?e.replace(/(.)(.)(.)/,"$1$1$2$2$3$3"):e)};this.toJson=function(g,f){var e="";switch(typeof(g)){case"string":e='"'+f(g)+'"';break;case"number":case"boolean":e=g.toString();break;case"object":e=[];for(var h in g){if(g[h]==Object.prototype[h]){continue}e.push('"'+h+'":'+this.toJson(g[h]))}e="{"+e.join(",")+"}";break}return e};this.convertCssArg=function(e){if(!e){return{}}if(typeof(e)=="object"){if(e.constructor==Array){e=e.join("")}else{return e}}var l={};var m=e.split("}");for(var h=0;h<m.length;h++){var k=m[h].match(/([^\s{]+)\s*\{(.+)\s*;?\s*/);if(!k||k.length!=3){continue}if(!l[k[1]]){l[k[1]]={}}var g=k[2].split(";");for(var f=0;f<g.length;f++){var n=g[f].match(/\s*([^:\s]+)\s*\:\s*([^;]+)/);if(!n||n.length!=3){continue}l[k[1]][n[1]]=n[2].replace(/\s+$/,"")}}return l};this.extractFromCss=function(g,f,i,e){var h=null;if(g&&g[f]&&g[f][i]){h=g[f][i];if(e){delete g[f][i]}}return h};this.cssToString=function(f){var g=[];for(var e in f){var j=f[e];if(j==Object.prototype[e]){continue}g.push(e,"{");for(var i in j){if(j[i]==Object.prototype[i]){continue}var h=j[i];if(D.UNIT_REMOVAL_PROPERTIES[i]){h=parseInt(h,10)}g.push(i,":",h,";")}g.push("}")}return g.join("")};this.escape=function(e){return escape(e).replace(/\+/g,"%2B")};this.encodeVars=function(e){return e.join("&").replace(/%/g,"%25")};this.copyProperties=function(g,f){for(var e in g){if(f[e]===undefined){f[e]=g[e]}}return f};this.domain=function(){var f="";try{f=document.domain}catch(g){}return f};this.domainMatches=function(h,g){if(g=="*"||g==h){return true}var f=g.lastIndexOf("*");if(f>-1){g=g.substr(f+1);var e=h.lastIndexOf(g);if(e>-1&&(e+g.length)==h.length){return true}}return false};this.uriEncode=function(e){return encodeURI(decodeURIComponent(e))};this.delay=function(f,h,g){var e=Array.prototype.slice.call(arguments,3);setTimeout(function(){h.apply(g,e)},f)}}D.UNIT_REMOVAL_PROPERTIES={leading:true,"margin-left":true,"margin-right":true,"text-indent":true};D.SINGLE_WHITESPACE=" ";function U(e){var d=this;function c(g,j,h){var k=d.getStyleAsInt(g,j,e.ua.ie);if(k==0){k=g[h];for(var f=3;f<arguments.length;f++){k-=d.getStyleAsInt(g,arguments[f],true)}}return k}this.getBody=function(){return document.getElementsByTagName("body")[0]||null};this.querySelectorAll=function(f){return window.parseSelector(f)};this.addClass=function(f,g){if(g){g.className=((g.className||"")==""?"":g.className+" ")+f}};this.removeClass=function(f,g){if(g){g.className=g.className.replace(new RegExp("(^|\\s)"+f+"(\\s|$)"),"").replace(/^\s+|(\s)\s+/g,"$1")}};this.hasClass=function(f,g){return new RegExp("(^|\\s)"+f+"(\\s|$)").test(g.className)};this.hasOneOfClassses=function(h,g){for(var f=0;f<h.length;f++){if(this.hasClass(h[f],g)){return true}}return false};this.ancestorHasClass=function(g,f){g=g.parentNode;while(g&&g.nodeType==1){if(this.hasClass(f,g)){return true}g=g.parentNode}return false};this.create=function(f,g){var h=document.createElementNS?document.createElementNS(U.XHTML_NS,f):document.createElement(f);if(g){h.className=g}return h};this.getComputedStyle=function(h,i){var f;if(document.defaultView&&document.defaultView.getComputedStyle){var g=document.defaultView.getComputedStyle(h,null);f=g?g[i]:null}else{if(h.currentStyle){f=h.currentStyle[i]}}return f||""};this.getStyleAsInt=function(g,i,f){var h=this.getComputedStyle(g,i);if(f&&!/px$/.test(h)){return 0}return parseInt(h)||0};this.getWidthFromStyle=function(f){return c(f,"width","offsetWidth","paddingRight","paddingLeft","borderRightWidth","borderLeftWidth")};this.getHeightFromStyle=function(f){return c(f,"height","offsetHeight","paddingTop","paddingBottom","borderTopWidth","borderBottomWidth")};this.getDimensions=function(j){var h=j.offsetWidth;var f=j.offsetHeight;if(h==0||f==0){for(var g=0;g<j.childNodes.length;g++){var k=j.childNodes[g];if(k.nodeType!=1){continue}h=Math.max(h,k.offsetWidth);f=Math.max(f,k.offsetHeight)}}return{width:h,height:f}};this.getViewport=function(){return{width:window.innerWidth||document.documentElement.clientWidth||this.getBody().clientWidth,height:window.innerHeight||document.documentElement.clientHeight||this.getBody().clientHeight}};this.blurElement=function(g){try{g.blur();return}catch(h){}var f=this.create("input");f.style.width="0px";f.style.height="0px";g.parentNode.appendChild(f);f.focus();f.blur();f.parentNode.removeChild(f)}}U.XHTML_NS="http://www.w3.org/1999/xhtml";function H(r){var g=navigator.userAgent.toLowerCase();var q=(navigator.product||"").toLowerCase();var h=navigator.platform.toLowerCase();this.parseVersion=H.parseVersion;this.macintosh=/^mac/.test(h);this.windows=/^win/.test(h);this.linux=/^linux/.test(h);this.quicktime=false;this.opera=/opera/.test(g);this.konqueror=/konqueror/.test(g);this.ie=false/*@cc_on||true@*/;this.ieSupported=this.ie&&!/ppc|smartphone|iemobile|msie\s5\.5/.test(g)/*@cc_on&&@_jscript_version>=5.5@*/;this.ieWin=this.ie&&this.windows/*@cc_on&&@_jscript_version>=5.1@*/;this.windows=this.windows&&(!this.ie||this.ieWin);this.ieMac=this.ie&&this.macintosh/*@cc_on&&@_jscript_version<5.1@*/;this.macintosh=this.macintosh&&(!this.ie||this.ieMac);this.safari=/safari/.test(g);this.webkit=!this.konqueror&&/applewebkit/.test(g);this.khtml=this.webkit||this.konqueror;this.gecko=!this.khtml&&q=="gecko";this.ieVersion=this.ie&&/.*msie\s(\d\.\d)/.exec(g)?this.parseVersion(RegExp.$1):"0";this.operaVersion=this.opera&&/.*opera(\s|\/)(\d+\.\d+)/.exec(g)?this.parseVersion(RegExp.$2):"0";this.webkitVersion=this.webkit&&/.*applewebkit\/(\d+).*/.exec(g)?this.parseVersion(RegExp.$1):"0";this.geckoVersion=this.gecko&&/.*rv:\s*([^\)]+)\)\s+gecko/.exec(g)?this.parseVersion(RegExp.$1):"0";this.konquerorVersion=this.konqueror&&/.*konqueror\/([\d\.]+).*/.exec(g)?this.parseVersion(RegExp.$1):"0";this.flashVersion=0;if(this.ieWin){var l;var o=false;try{l=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7")}catch(m){try{l=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");this.flashVersion=this.parseVersion("6");l.AllowScriptAccess="always"}catch(m){o=this.flashVersion==this.parseVersion("6")}if(!o){try{l=new ActiveXObject("ShockwaveFlash.ShockwaveFlash")}catch(m){}}}if(!o&&l){this.flashVersion=this.parseVersion((l.GetVariable("$version")||"").replace(/^\D+(\d+)\D+(\d+)\D+(\d+).*/g,"$1.$2.$3"))}}else{if(navigator.plugins&&navigator.plugins["Shockwave Flash"]){var n=navigator.plugins["Shockwave Flash"].description.replace(/^.*\s+(\S+\s+\S+$)/,"$1");var p=n.replace(/^\D*(\d+\.\d+).*$/,"$1");if(/r/.test(n)){p+=n.replace(/^.*r(\d*).*$/,".$1")}else{if(/d/.test(n)){p+=".0"}}this.flashVersion=this.parseVersion(p);var j=false;for(var k=0,c=this.flashVersion>=H.MIN_FLASH_VERSION;c&&k<navigator.mimeTypes.length;k++){var f=navigator.mimeTypes[k];if(f.type!="application/x-shockwave-flash"){continue}if(f.enabledPlugin){j=true;if(f.enabledPlugin.description.toLowerCase().indexOf("quicktime")>-1){c=false;this.quicktime=true}}}if(this.quicktime||!j){this.flashVersion=this.parseVersion("0")}}}this.flash=this.flashVersion>=H.MIN_FLASH_VERSION;this.transparencySupport=this.macintosh||this.windows||this.linux&&(this.flashVersion>=this.parseVersion("10")&&(this.gecko&&this.geckoVersion>=this.parseVersion("1.9")||this.opera));this.computedStyleSupport=this.ie||!!document.defaultView.getComputedStyle;this.fixFocus=this.gecko&&this.windows;this.nativeDomLoaded=this.gecko||this.webkit&&this.webkitVersion>=this.parseVersion("525")||this.konqueror&&this.konquerorMajor>this.parseVersion("03")||this.opera;this.mustCheckStyle=this.khtml||this.opera;this.forcePageLoad=this.webkit&&this.webkitVersion<this.parseVersion("523");this.properDocument=typeof(document.location)=="object";this.supported=this.flash&&this.properDocument&&(!this.ie||this.ieSupported)&&this.computedStyleSupport&&(!this.opera||this.operaVersion>=this.parseVersion("9.61"))&&(!this.webkit||this.webkitVersion>=this.parseVersion("412"))&&(!this.gecko||this.geckoVersion>=this.parseVersion("1.8.0.12"))&&(!this.konqueror)}H.parseVersion=function(c){return c.replace(/(^|\D)(\d+)(?=\D|$)/g,function(f,e,g){f=e;for(var d=4-g.length;d>=0;d--){f+="0"}return f+g})};H.MIN_FLASH_VERSION=H.parseVersion("8");function F(c){this.fix=c.ua.ieWin&&window.location.hash!="";var d;this.cache=function(){d=document.title};function e(){document.title=d}this.restore=function(){if(this.fix){setTimeout(e,0)}}}function S(l){var e=null;function c(){try{if(l.ua.ie||document.readyState!="loaded"&&document.readyState!="complete"){document.documentElement.doScroll("left")}}catch(n){return setTimeout(c,10)}i()}function i(){if(l.useStyleCheck){h()}else{if(!l.ua.mustCheckStyle){d(null,true)}}}function h(){e=l.dom.create("div",E.DUMMY);l.dom.getBody().appendChild(e);m()}function m(){if(l.dom.getComputedStyle(e,"marginLeft")=="42px"){g()}else{setTimeout(m,10)}}function g(){if(e&&e.parentNode){e.parentNode.removeChild(e)}e=null;d(null,true)}function d(n,o){l.initialize(o);if(n&&n.type=="load"){if(document.removeEventListener){document.removeEventListener("DOMContentLoaded",d,false)}if(window.removeEventListener){window.removeEventListener("load",d,false)}}}function j(){l.prepareClearReferences();if(document.readyState=="interactive"){document.attachEvent("onstop",f);setTimeout(function(){document.detachEvent("onstop",f)},0)}}function f(){document.detachEvent("onstop",f);k()}function k(){l.clearReferences()}this.attach=function(){if(window.addEventListener){window.addEventListener("load",d,false)}else{window.attachEvent("onload",d)}if(!l.useDomLoaded||l.ua.forcePageLoad||l.ua.ie&&window.top!=window){return}if(l.ua.nativeDomLoaded){document.addEventListener("DOMContentLoaded",i,false)}else{if(l.ua.ie||l.ua.khtml){c()}}};this.attachUnload=function(){if(!l.ua.ie){return}window.attachEvent("onbeforeunload",j);window.attachEvent("onunload",k)}}var Q="sifrFetch";function N(c){var e=false;this.fetchMovies=function(f){if(c.setPrefetchCookie&&new RegExp(";?"+Q+"=true;?").test(document.cookie)){return}try{e=true;d(f)}catch(g){}if(c.setPrefetchCookie){document.cookie=Q+"=true;path="+c.cookiePath}};this.clear=function(){if(!e){return}try{var f=document.getElementsByTagName("script");for(var g=f.length-1;g>=0;g--){var h=f[g];if(h.type=="sifr/prefetch"){h.parentNode.removeChild(h)}}}catch(j){}};function d(f){for(var g=0;g<f.length;g++){document.write('<script defer type="sifr/prefetch" src="'+f[g].src+'"><\/script>')}}}function b(e){var g=e.ua.ie;var f=g&&e.ua.flashVersion<e.ua.parseVersion("9.0.115");var d={};var c={};this.fixFlash=f;this.register=function(h){if(!g){return}var i=h.getAttribute("id");this.cleanup(i,false);c[i]=h;delete d[i];if(f){window[i]=h}};this.reset=function(){if(!g){return false}for(var j=0;j<e.replacements.length;j++){var h=e.replacements[j];var k=c[h.id];if(!d[h.id]&&(!k.parentNode||k.parentNode.nodeType==11)){h.resetMovie();d[h.id]=true}}return true};this.cleanup=function(l,h){var i=c[l];if(!i){return}for(var k in i){if(typeof(i[k])=="function"){i[k]=null}}c[l]=null;if(f){window[l]=null}if(i.parentNode){if(h&&i.parentNode.nodeType==1){var j=document.createElement("div");j.style.width=i.offsetWidth+"px";j.style.height=i.offsetHeight+"px";i.parentNode.replaceChild(j,i)}else{i.parentNode.removeChild(i)}}};this.prepareClearReferences=function(){if(!f){return}__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){}};this.clearReferences=function(){if(f){var j=document.getElementsByTagName("object");for(var h=j.length-1;h>=0;h--){c[j[h].getAttribute("id")]=j[h]}}for(var k in c){if(Object.prototype[k]!=c[k]){this.cleanup(k,true)}}}}function K(d,g,f,c,e){this.sIFR=d;this.id=g;this.vars=f;this.movie=null;this.__forceWidth=c;this.__events=e;this.__resizing=0}K.prototype={getFlashElement:function(){return document.getElementById(this.id)},getAlternate:function(){return document.getElementById(this.id+"_alternate")},getAncestor:function(){var c=this.getFlashElement().parentNode;return !this.sIFR.dom.hasClass(E.FIX_FOCUS,c)?c:c.parentNode},available:function(){var c=this.getFlashElement();return c&&c.parentNode},call:function(c){var d=this.getFlashElement();if(!d[c]){return false}return Function.prototype.apply.call(d[c],d,Array.prototype.slice.call(arguments,1))},attempt:function(){if(!this.available()){return false}try{this.call.apply(this,arguments)}catch(c){if(this.sIFR.debug){throw c}return false}return true},updateVars:function(c,e){for(var d=0;d<this.vars.length;d++){if(this.vars[d].split("=")[0]==c){this.vars[d]=c+"="+e;break}}var f=this.sIFR.util.encodeVars(this.vars);this.movie.injectVars(this.getFlashElement(),f);this.movie.injectVars(this.movie.html,f)},storeSize:function(c,d){this.movie.setSize(c,d);this.updateVars(c,d)},fireEvent:function(c){if(this.available()&&this.__events[c]){this.sIFR.util.delay(0,this.__events[c],this,this)}},resizeFlashElement:function(c,d,e){if(!this.available()){return}this.__resizing++;var f=this.getFlashElement();f.setAttribute("height",c);this.getAncestor().style.minHeight="";this.updateVars("renderheight",c);this.storeSize("height",c);if(d!==null){f.setAttribute("width",d);this.movie.setSize("width",d)}if(this.__events.onReplacement){this.sIFR.util.delay(0,this.__events.onReplacement,this,this);delete this.__events.onReplacement}if(e){this.sIFR.util.delay(0,function(){this.attempt("scaleMovie");this.__resizing--},this)}else{this.__resizing--}},blurFlashElement:function(){if(this.available()){this.sIFR.dom.blurElement(this.getFlashElement())}},resetMovie:function(){this.sIFR.util.delay(0,this.movie.reset,this.movie,this.getFlashElement(),this.getAlternate())},resizeAfterScale:function(){if(this.available()&&this.__resizing==0){this.sIFR.util.delay(0,this.resize,this)}},resize:function(){if(!this.available()){return}this.__resizing++;var g=this.getFlashElement();var f=g.offsetWidth;if(f==0){return}var e=g.getAttribute("width");var l=g.getAttribute("height");var m=this.getAncestor();var o=this.sIFR.dom.getHeightFromStyle(m);g.style.width="1px";g.style.height="1px";m.style.minHeight=o+"px";var c=this.getAlternate().childNodes;var n=[];for(var k=0;k<c.length;k++){var h=c[k].cloneNode(true);n.push(h);m.appendChild(h)}var d=this.sIFR.dom.getWidthFromStyle(m);for(var k=0;k<n.length;k++){m.removeChild(n[k])}g.style.width=g.style.height=m.style.minHeight="";g.setAttribute("width",this.__forceWidth?d:e);g.setAttribute("height",l);if(sIFR.ua.ie){g.style.display="none";var j=g.offsetHeight;g.style.display=""}if(d!=f){if(this.__forceWidth){this.storeSize("width",d)}this.attempt("resize",d)}this.__resizing--},replaceText:function(g,j){var d=this.sIFR.util.escape(g);if(!this.attempt("replaceText",d)){return false}this.updateVars("content",d);var f=this.getAlternate();if(j){while(f.firstChild){f.removeChild(f.firstChild)}for(var c=0;c<j.length;c++){f.appendChild(j[c])}}else{try{f.innerHTML=g}catch(h){}}return true},changeCSS:function(c){c=this.sIFR.util.escape(this.sIFR.util.cssToString(this.sIFR.util.convertCssArg(c)));this.updateVars("css",c);return this.attempt("changeCSS",c)},remove:function(){if(this.movie&&this.available()){this.movie.remove(this.getFlashElement(),this.id)}}};var X=new function(){this.create=function(p,n,j,i,f,e,g,o,l,h,m){var k=p.ua.ie?d:c;return new k(p,n,j,i,f,e,g,o,["flashvars",l,"wmode",h,"bgcolor",m,"allowScriptAccess","always","quality","best"])};function c(s,q,l,h,f,e,g,r,n){var m=s.dom.create("object",E.FLASH);var p=["type","application/x-shockwave-flash","id",f,"name",f,"data",e,"width",g,"height",r];for(var o=0;o<p.length;o+=2){m.setAttribute(p[o],p[o+1])}var j=m;if(h){j=W.create("div",E.FIX_FOCUS);j.appendChild(m)}for(var o=0;o<n.length;o+=2){if(n[o]=="name"){continue}var k=W.create("param");k.setAttribute("name",n[o]);k.setAttribute("value",n[o+1]);m.appendChild(k)}l.style.minHeight=r+"px";while(l.firstChild){l.removeChild(l.firstChild)}l.appendChild(j);this.html=j.cloneNode(true)}c.prototype={reset:function(e,f){e.parentNode.replaceChild(this.html.cloneNode(true),e)},remove:function(e,f){e.parentNode.removeChild(e)},setSize:function(e,f){this.html.setAttribute(e,f)},injectVars:function(e,g){var h=e.getElementsByTagName("param");for(var f=0;f<h.length;f++){if(h[f].getAttribute("name")=="flashvars"){h[f].setAttribute("value",g);break}}}};function d(p,n,j,h,f,e,g,o,k){this.dom=p.dom;this.broken=n;this.html='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="'+f+'" width="'+g+'" height="'+o+'" class="'+E.FLASH+'"><param name="movie" value="'+e+'"></param></object>';var m="";for(var l=0;l<k.length;l+=2){m+='<param name="'+k[l]+'" value="'+k[l+1]+'"></param>'}this.html=this.html.replace(/(<\/object>)/,m+"$1");j.style.minHeight=o+"px";j.innerHTML=this.html;this.broken.register(j.firstChild)}d.prototype={reset:function(f,g){g=g.cloneNode(true);var e=f.parentNode;e.innerHTML=this.html;this.broken.register(e.firstChild);e.appendChild(g)},remove:function(e,f){this.broken.cleanup(f)},setSize:function(e,f){this.html=this.html.replace(e=="height"?/(height)="\d+"/:/(width)="\d+"/,'$1="'+f+'"')},injectVars:function(e,f){if(e!=this.html){return}this.html=this.html.replace(/(flashvars(=|\"\svalue=)\")[^\"]+/,"$1"+f)}}};this.errors=new Y(O);var A=this.util=new D(O);var W=this.dom=new U(O);var T=this.ua=new H(O);var G={fragmentIdentifier:new F(O),pageLoad:new S(O),prefetch:new N(O),brokenFlashIE:new b(O)};this.__resetBrokenMovies=G.brokenFlashIE.reset;var J={kwargs:[],replaceAll:function(d){for(var c=0;c<this.kwargs.length;c++){O.replace(this.kwargs[c])}if(!d){this.kwargs=[]}}};this.activate=function(){if(!T.supported||!this.isEnabled||this.isActive||!C()||a()){return}G.prefetch.fetchMovies(arguments);this.isActive=true;this.setFlashClass();G.fragmentIdentifier.cache();G.pageLoad.attachUnload();if(!this.autoInitialize){return}G.pageLoad.attach()};this.setFlashClass=function(){if(this.hasFlashClassSet){return}W.addClass(E.ACTIVE,W.getBody()||document.documentElement);this.hasFlashClassSet=true};this.removeFlashClass=function(){if(!this.hasFlashClassSet){return}W.removeClass(E.ACTIVE,W.getBody());W.removeClass(E.ACTIVE,document.documentElement);this.hasFlashClassSet=false};this.initialize=function(c){if(!this.isActive||!this.isEnabled){return}if(R){if(!c){J.replaceAll(false)}return}R=true;J.replaceAll(c);if(O.repaintOnResize){if(window.addEventListener){window.addEventListener("resize",Z,false)}else{window.attachEvent("onresize",Z)}}G.prefetch.clear()};this.replace=function(x,u){if(!T.supported){return}if(u){x=A.copyProperties(x,u)}if(!R){return J.kwargs.push(x)}if(this.onReplacementStart){this.onReplacementStart(x)}var AM=x.elements||W.querySelectorAll(x.selector);if(AM.length==0){return}var w=M(x.src);var AR=A.convertCssArg(x.css);var v=B(x.filters);var AN=x.forceSingleLine===true;var AS=x.preventWrap===true&&!AN;var q=AN||(x.fitExactly==null?this.fitExactly:x.fitExactly)===true;var AD=q||(x.forceWidth==null?this.forceWidth:x.forceWidth)===true;var s=x.ratios||[];var AE=x.pixelFont===true;var r=parseInt(x.tuneHeight)||0;var z=!!x.onRelease||!!x.onRollOver||!!x.onRollOut;if(q){A.extractFromCss(AR,".sIFR-root","text-align",true)}var t=A.extractFromCss(AR,".sIFR-root","font-size",true)||"0";var e=A.extractFromCss(AR,".sIFR-root","background-color",true)||"#FFFFFF";var o=A.extractFromCss(AR,".sIFR-root","kerning",true)||"";var AW=A.extractFromCss(AR,".sIFR-root","opacity",true)||"100";var k=A.extractFromCss(AR,".sIFR-root","cursor",true)||"default";var AP=parseInt(A.extractFromCss(AR,".sIFR-root","leading"))||0;var AJ=x.gridFitType||(A.extractFromCss(AR,".sIFR-root","text-align")=="right")?"subpixel":"pixel";var h=this.forceTextTransform===false?"none":A.extractFromCss(AR,".sIFR-root","text-transform",true)||"none";t=/^\d+(px)?$/.test(t)?parseInt(t):0;AW=parseFloat(AW)<1?100*parseFloat(AW):AW;var AC=x.modifyCss?"":A.cssToString(AR);var AG=x.wmode||"";if(!AG){if(x.transparent){AG="transparent"}else{if(x.opaque){AG="opaque"}}}if(AG=="transparent"){if(!T.transparencySupport){AG="opaque"}else{e="transparent"}}else{if(e=="transparent"){e="#FFFFFF"}}for(var AV=0;AV<AM.length;AV++){var AF=AM[AV];if(W.hasOneOfClassses(E.IGNORE_CLASSES,AF)||W.ancestorHasClass(AF,E.ALTERNATE)){continue}var AO=W.getDimensions(AF);var f=AO.height;var c=AO.width;var AA=W.getComputedStyle(AF,"display");if(!f||!c||!AA||AA=="none"){continue}c=W.getWidthFromStyle(AF);var n,AH;if(!t){var AL=I(AF);n=Math.min(this.MAX_FONT_SIZE,Math.max(this.MIN_FONT_SIZE,AL.fontSize));if(AE){n=Math.max(8,8*Math.round(n/8))}AH=AL.lines}else{n=t;AH=1}var d=W.create("span",E.ALTERNATE);var AX=AF.cloneNode(true);AF.parentNode.appendChild(AX);for(var AU=0,AT=AX.childNodes.length;AU<AT;AU++){var m=AX.childNodes[AU];if(!/^(style|script)$/i.test(m.nodeName)){d.appendChild(m.cloneNode(true))}}if(x.modifyContent){x.modifyContent(AX,x.selector)}if(x.modifyCss){AC=x.modifyCss(AR,AX,x.selector)}var p=P(AX,h,x.uriEncode);AX.parentNode.removeChild(AX);if(x.modifyContentString){p.text=x.modifyContentString(p.text,x.selector)}if(p.text==""){continue}var AK=Math.round(AH*V(n,s)*n)+this.FLASH_PADDING_BOTTOM+r;if(AH>1&&AP){AK+=Math.round((AH-1)*AP)}var AB=AD?c:"100%";var AI="sIFR_replacement_"+L++;var AQ=["id="+AI,"content="+A.escape(p.text),"width="+c,"renderheight="+AK,"link="+A.escape(p.primaryLink.href||""),"target="+A.escape(p.primaryLink.target||""),"size="+n,"css="+A.escape(AC),"cursor="+k,"tunewidth="+(x.tuneWidth||0),"tuneheight="+r,"offsetleft="+(x.offsetLeft||""),"offsettop="+(x.offsetTop||""),"fitexactly="+q,"preventwrap="+AS,"forcesingleline="+AN,"antialiastype="+(x.antiAliasType||""),"thickness="+(x.thickness||""),"sharpness="+(x.sharpness||""),"kerning="+o,"gridfittype="+AJ,"flashfilters="+v,"opacity="+AW,"blendmode="+(x.blendMode||""),"selectable="+(x.selectable==null||AG!=""&&!sIFR.ua.macintosh&&sIFR.ua.gecko&&sIFR.ua.geckoVersion>=sIFR.ua.parseVersion("1.9")?"true":x.selectable===true),"fixhover="+(this.fixHover===true),"events="+z,"delayrun="+G.brokenFlashIE.fixFlash,"version="+this.VERSION];var y=A.encodeVars(AQ);var g=new K(O,AI,AQ,AD,{onReplacement:x.onReplacement,onRollOver:x.onRollOver,onRollOut:x.onRollOut,onRelease:x.onRelease});g.movie=X.create(sIFR,G.brokenFlashIE,AF,T.fixFocus&&x.fixFocus,AI,w,AB,AK,y,AG,e);this.replacements.push(g);this.replacements[AI]=g;if(x.selector){if(!this.replacements[x.selector]){this.replacements[x.selector]=[g]}else{this.replacements[x.selector].push(g)}}d.setAttribute("id",AI+"_alternate");AF.appendChild(d);W.addClass(E.REPLACED,AF)}G.fragmentIdentifier.restore()};this.getReplacementByFlashElement=function(d){for(var c=0;c<O.replacements.length;c++){if(O.replacements[c].id==d.getAttribute("id")){return O.replacements[c]}}};this.redraw=function(){for(var c=0;c<O.replacements.length;c++){O.replacements[c].resetMovie()}};this.prepareClearReferences=function(){G.brokenFlashIE.prepareClearReferences()};this.clearReferences=function(){G.brokenFlashIE.clearReferences();G=null;J=null;delete O.replacements};function C(){if(O.domains.length==0){return true}var d=A.domain();for(var c=0;c<O.domains.length;c++){if(A.domainMatches(d,O.domains[c])){return true}}return false}function a(){if(document.location.protocol=="file:"){if(O.debug){O.errors.fire("isFile")}return true}return false}function M(c){if(T.ie&&c.charAt(0)=="index.html"){c=window.location.toString().replace(/([^:]+)(:\/?\/?)([^\/]+).*/,"$1$2$3")+c}return c}function V(d,e){for(var c=0;c<e.length;c+=2){if(d<=e[c]){return e[c+1]}}return e[e.length-1]||1}function B(g){var e=[];for(var d in g){if(g[d]==Object.prototype[d]){continue}var c=g[d];d=[d.replace(/filter/i,"")+"Filter"];for(var f in c){if(c[f]==Object.prototype[f]){continue}d.push(f+":"+A.escape(A.toJson(c[f],A.toHexString)))}e.push(d.join(","))}return A.escape(e.join(";"))}function Z(d){var e=Z.viewport;var c=W.getViewport();if(e&&c.width==e.width&&c.height==e.height){return}Z.viewport=c;if(O.replacements.length==0){return}if(Z.timer){clearTimeout(Z.timer)}Z.timer=setTimeout(function(){delete Z.timer;for(var f=0;f<O.replacements.length;f++){O.replacements[f].resize()}},200)}function I(f){var g=W.getComputedStyle(f,"fontSize");var d=g.indexOf("px")==-1;var e=f.innerHTML;if(d){f.innerHTML="X"}f.style.paddingTop=f.style.paddingBottom=f.style.borderTopWidth=f.style.borderBottomWidth="0px";f.style.lineHeight="2em";f.style.display="block";g=d?f.offsetHeight/2:parseInt(g,10);if(d){f.innerHTML=e}var c=Math.round(f.offsetHeight/(2*g));f.style.paddingTop=f.style.paddingBottom=f.style.borderTopWidth=f.style.borderBottomWidth=f.style.lineHeight=f.style.display="";if(isNaN(c)||!isFinite(c)||c==0){c=1}return{fontSize:g,lines:c}}function P(c,g,s){s=s||A.uriEncode;var q=[],m=[];var k=null;var e=c.childNodes;var o=false,p=false;var j=0;while(j<e.length){var f=e[j];if(f.nodeType==3){var t=A.textTransform(g,A.normalize(f.nodeValue)).replace(/</g,"&lt;");if(o&&p){t=t.replace(/^\s+/,"")}m.push(t);o=/\s$/.test(t);p=false}if(f.nodeType==1&&!/^(style|script)$/i.test(f.nodeName)){var h=[];var r=f.nodeName.toLowerCase();var n=f.className||"";if(/\s+/.test(n)){if(n.indexOf(E.CLASS)>-1){n=n.match("(\\s|^)"+E.CLASS+"-([^\\s$]*)(\\s|$)")[2]}else{n=n.match(/^([^\s]+)/)[1]}}if(n!=""){h.push('class="'+n+'"')}if(r=="a"){var d=s(f.getAttribute("href")||"");var l=f.getAttribute("target")||"";h.push('href="'+d+'"','target="'+l+'"');if(!k){k={href:d,target:l}}}m.push("<"+r+(h.length>0?" ":"")+h.join(" ")+">");p=true;if(f.hasChildNodes()){q.push(j);j=0;e=f.childNodes;continue}else{if(!/^(br|img)$/i.test(f.nodeName)){m.push("</",f.nodeName.toLowerCase(),">")}}}if(q.length>0&&!f.nextSibling){do{j=q.pop();e=f.parentNode.parentNode.childNodes;f=e[j];if(f){m.push("</",f.nodeName.toLowerCase(),">")}}while(j==e.length-1&&q.length>0)}j++}return{text:m.join("").replace(/^\s+|\s+$|\s*(<br>)\s*/g,"$1"),primaryLink:k||{}}}};
var parseSelector=(function(){var B=/\s*,\s*/;var A=/\s*([\s>+~(),]|^|$)\s*/g;var L=/([\s>+~,]|[^(]\+|^)([#.:@])/g;var F=/(^|\))[^\s>+~]/g;var M=/(\)|^)/;var K=/[\s#.:>+~()@]|[^\s#.:>+~()@]+/g;function H(R,P){P=P||document.documentElement;var S=R.split(B),X=[];for(var U=0;U<S.length;U++){var N=[P],W=G(S[U]);for(var T=0;T<W.length;){var Q=W[T++],O=W[T++],V="";if(W[T]=="("){while(W[T++]!=")"&&T<W.length){V+=W[T]}V=V.slice(0,-1)}N=I(N,Q,O,V)}X=X.concat(N)}return X}function G(N){var O=N.replace(A,"$1").replace(L,"$1*$2").replace(F,D);return O.match(K)||[]}function D(N){return N.replace(M,"$1 ")}function I(N,P,Q,O){return(H.selectors[P])?H.selectors[P](N,Q,O):[]}var E={toArray:function(O){var N=[];for(var P=0;P<O.length;P++){N.push(O[P])}return N}};var C={isTag:function(O,N){return(N=="*")||(N.toLowerCase()==O.nodeName.toLowerCase())},previousSiblingElement:function(N){do{N=N.previousSibling}while(N&&N.nodeType!=1);return N},nextSiblingElement:function(N){do{N=N.nextSibling}while(N&&N.nodeType!=1);return N},hasClass:function(N,O){return(O.className||"").match("(^|\\s)"+N+"(\\s|$)")},getByTag:function(N,O){return O.getElementsByTagName(N)}};var J={"#":function(N,P){for(var O=0;O<N.length;O++){if(N[O].getAttribute("id")==P){return[N[O]]}}return[]}," ":function(O,Q){var N=[];for(var P=0;P<O.length;P++){N=N.concat(E.toArray(C.getByTag(Q,O[P])))}return N},">":function(O,R){var N=[];for(var Q=0,S;Q<O.length;Q++){S=O[Q];for(var P=0,T;P<S.childNodes.length;P++){T=S.childNodes[P];if(T.nodeType==1&&C.isTag(T,R)){N.push(T)}}}return N},".":function(O,Q){var N=[];for(var P=0,R;P<O.length;P++){R=O[P];if(C.hasClass([Q],R)){N.push(R)}}return N},":":function(N,P,O){return(H.pseudoClasses[P])?H.pseudoClasses[P](N,O):[]}};H.selectors=J;H.pseudoClasses={};H.util=E;H.dom=C;return H})();/*****************************************************************************
It is adviced to place the sIFR JavaScript calls in this file, keeping it
separate from the `sifr.js` file. That way, you can easily swap the `sifr.js`
file for a new version, while keeping the configuration.

You must load this file *after* loading `sifr.js`.

That said, you're of course free to merge the JavaScript files. Just make sure
the copyright statement in `sifr.js` is kept intact.
*****************************************************************************/

// Make an object pointing to the location of the Flash movie on your web server.
// Try using the font name as the variable name, makes it easy to remember which
// object you're using. As an example in this file, we'll use Futura.
var franklinBookDemi = {
    src: '/fla/franklinBookDemi.swf'
};
// Now you can set some configuration settings.
// See also <http://wiki.novemberborn.net/sifr3/JavaScript+Configuration>.
// One setting you probably want to use is `sIFR.useStyleCheck`. Before you do that,
// read <http://wiki.novemberborn.net/sifr3/DetectingCSSLoad>.

// sIFR.useStyleCheck = true;

// Next, activate sIFR:
sIFR.activate(franklinBookDemi);

// If you want, you can use multiple movies, like so:
//
//    var futura = { src: '/path/to/futura.swf' };
//    var garamond = { src '/path/to/garamond.swf' };
//    var rockwell = { src: '/path/to/rockwell.swf' };
//    
//    sIFR.activate(futura, garamond, rockwell);
//
// Remember, there must be *only one* `sIFR.activate()`!

// Now we can do the replacements. You can do as many as you like, but just
// as an example, we'll replace all `<h1>` elements with the Futura movie.
// 
// The first argument to `sIFR.replace` is the `futura` object we created earlier.
// The second argument is another object, on which you can specify a number of
// parameters or "keyword arguemnts". For the full list, see "Keyword arguments"
// under `replace(kwargs, mergeKwargs)` at 
// <http://wiki.novemberborn.net/sifr3/JavaScript+Methods>.
// 
// The first argument you see here is `selector`, which is a normal CSS selector.
// That means you can also do things like '#content h1' or 'h1.title'.
//
// The second argument determines what the Flash text looks like. The main text
// is styled via the `.sIFR-root` class. Here we've specified `background-color`
// of the entire Flash movie to be a light grey, and the `color` of the text to
// be red. Read more about styling at <http://wiki.novemberborn.net/sifr3/Styling>.

sIFR.replace(franklinBookDemi, {
    selector: '#mainSection .mainColumn H1',
    css: [ 
        '.sIFR-root { background-color: #ffffff; letter-spacing: -2; }',
        '.red { color: #6d314c; font-family: Franklin Gothic Demi; }',
        '.grey { color: #8b9ea9; font-family: Franklin Gothic Book;}',
        '.blog a { color: #6d314c; text-decoration: none; }',
        '.blog a:hover { color: #6d314c; text-decoration: none; }'
        ],
    wmode: 'transparent'
});

sIFR.replace(franklinBookDemi, {
    selector: '#mainSection .mainColumn #portfolioGallery H2',
    css: '.sIFR-root { background-color: #ffffff; color: #8a99a0; letter-spacing: -1; font-family: Franklin Gothic Book; }',
    wmode: 'transparent'
});

sIFR.replace(franklinBookDemi, {
    selector: '#mainSection .mainColumn H2, .promoBox .title',
    css: '.sIFR-root { background-color: #ffffff; color: #6d314c; letter-spacing: -1; font-family: Franklin Gothic Book; }',
    wmode: 'transparent'
});

sIFR.replace(franklinBookDemi, {
    selector: '#subFooter .column H4, #subFooter .column H1',
    css: '.sIFR-root { background-color: #f2f4f5; color: #5b253d; font-family: Franklin Gothic Book; }',
    wmode: 'transparent' 
});// This is just here to tell JS lint that we need to use a global variable
/*global TVI , document, alert, console, window $ */

/// Declare Namespace

TVI = { version: "0.2" };

// Create function for applying config options to classes
TVI.apply = function(o, c, d){

    // o = object   : The object that is having stuff applied to it.
    // c = config   : The config options that will be applied to the object
    // d = defaults : Any default options that
    
    // See if defaults have been supplied
    if (d) {
        // If they have then call the apply function again with the defaults as the config
        TVI.apply(o, d);
    }

    // Check the object and config are valid objects
    if (o && c && typeof c == 'object') {
        // Loop through the config and add all the properties and methods
        for (var p in c) {
			// Check that we're only dealing with config members, not stuff inherited through the prototype
            if (c.hasOwnProperty(p) && c[p] !== undefined) {
		        o[p] = c[p];
		    }
        }
    }
	
    // Return the original object
    return o;
};


// Closed function - is not global but is instantiated and run immediately
(function() {

    // ********** Set up TVI variable and methods ********** //

    TVI.apply(TVI, {

        /**
        * Counter for creating uniqu ID's for components.
        * @property
        * @type integer
        */
        idSeed: 0,

        /**
        * Function for creating a unique ID for any control
        * @property
        * @type Function
        */
        createID: function(o, prefix) {
            prefix = prefix || "TVI-auto-";
            if (o.id === undefined || o.id === null || o.id === '') {
                var id = prefix + (++this.idSeed);
                o.id = id;
            }
            return o;
        },

        /**
        * A reusable empty function
        * @property
        * @type Function
        */
        emptyFn: function() { },

        /**
        * List of field types used in forms
        * @property
        * @type Array
        */
        fieldTypes: [
		        'textBox',
		        'textArea',
		        'dropDownList',
		        'checkBox',
			    'password',
			    'multiRadio',
			    'multiCheckBox'
		    ],

        /**
        * List of allowed data types when communicating with a database
        * @property
        * @type Array
        */
        dataTypes: [
			    'varchar',
			    'text',
			    'boolean',
			    'integer',
			    'decimal',
			    'date'
		    ],

        /**
        * Ajax - wraps up the jQuery Ajax function and adds defaults
        */
        ajax: function(params) {

            // Defaults for ajax calls
            var defaults = {
                type: 'POST',
                contentType: 'application/json; charset=utf-8',
                dataType: 'json',
                data: '{}'
            };

            var successFunction = params.success;
            var failureFunction = params.failure;

            // Overwrite the default parameters with the ones passed in
            var ajaxParams = TVI.apply(defaults, params);

            // Intercept the success function and add some functionality
            ajaxParams.success = function(data) {

                // Parse the response
                var response = JSON.parse(data.d);

                // Check that the call was successful
                if (response.success === true) {

                    // Run the success function if it exists
                    if (successFunction) {
                        successFunction.call(this, response);
                    }
                }
                else {
                    // Run the failure function if it exists
                    TVI.logError(response);
                    if (failureFunction) {
                        failureFunction.call(this, response);
                    }
                }

            };

            // Intercept the error function and pass it through to the default ajax error function.
            ajaxParams.error = function() {

                var errorCode = params.errorCode || '010004';
                var errorMessage = params.errorMessage || 'Error occured during Ajax call';

                // Log the error to the console
                TVI.logError({
                    "code": errorCode,
                    "message": errorMessage
                });

                // Run the error function if it exists
                if (params.error !== undefined && params.error !== null) {
                    params.error.call();
                }
            };

            // Make the ajax call
            $.ajax(ajaxParams);

        },

        /**
        * Check to see if the Firebug console exists for error logging
        */
        firebugCheck: function() {

            // Attempt top initialise the console if it doesn't exist
            if (typeof console == 'undefined') {
                if (typeof loadFirebugConsole == 'function') {
                    loadFirebugConsole();
                }
            }

            // Now check to see if the console exists
            if ($.browser.mozilla && window.console !== null && window.console !== undefined) {
                return true;
            }
            else {
                return false;
            }
        },

        /**
        * Log an error to the Firebug console.
        * @param {Object} errorObject - An object containing an error code and error message.
        */
        logError: function(errorObject) {

            // Console only exists in Firebug so check it exists before trying to write to it
            if (TVI.firebugCheck() === true) {

                // Check to see if there is an errors colleciton
                if (errorObject.errors) {

                    // Loop through
                    var errorsLength = errorObject.errors.length;
                    for (i = 0; i < errorsLength; i++) {
                        console.error('TVI Error: ' + errorObject.errors[i].code + ' - ' + errorObject.errors[i].message);
                    }
                }
                else {
                    console.error('TVI Error: ' + errorObject.code + ' - ' + errorObject.message);
                }

            }
        },

        /**
        * Log a warning to the Firebug error console.
        * @param {string} warning - The warning to be shown
        */
        logWarning: function(warning) {

            // Console only exists in Firebug so check it exists before trying to write to it
            if (TVI.firebugCheck() === true) {
                console.warn(warning);
            }
        },

        /**
        * Log a comment to the Firebug console.
        * @param {string} comment - The comment to show
        */
        logComment: function(comment) {

            // Console only exists in Firebug so check it exists before trying to write to it
            if (TVI.firebugCheck() === true) {
                console.info(comment);
            }
        },

        /**
        * Wraps up Firebug's console.dir function.
        * @param {Object} o - The object to bad added to the console
        */
        logDir: function(o) {

            // Console only exists in Firebug so check it exists before trying to write to it
            if (TVI.firebugCheck() === true) {
                console.dir(o);
            }
        },

        /**
        * Start a timer in Firebug's console.
        * @param {string} name - The name of the timer. Must match the logTimerEnd name.
        */
        logTimer: function(name) {

            // Console only exists in Firebug so check it exists before trying to write to it
            if (TVI.firebugCheck() === true) {
                console.time(name);
            }
        },

        /**
        * Stops a timer in Firebug's console.
        * @param {string} name - The name of the timer. Must match the start timer name.
        */
        logTimerEnd: function(name) {

            // Console only exists in Firebug so check it exists before trying to write to it
            if (TVI.firebugCheck() === true) {
                console.timeEnd(name);
            }
        },

        /**
        * Starts a group of nested comments/warnings/errors in Firebug's console.
        * @param {string} name - The name of the group. Must match the logGroupEnd name.
        */
        logGroup: function(name) {

            // Console only exists in Firebug so check it exists before trying to write to it
            if (TVI.firebugCheck() === true) {
                console.group(name);
            }
        },

        /**
        * Ends a group of nested comments/warnings/errors in Firebug's console.
        * @param {string} name - The name of the group. Must match the start name.
        */
        logGroupEnd: function(name) {

            // Console only exists in Firebug so check it exists before trying to write to it
            if (TVI.firebugCheck() === true) {
                console.groupEnd(name);
            }
        },

        /**
        * Starts Firebug's profiler.
        * @param {string} title - Optional title for the profiler report.
        */
        logProfile: function(title) {

            // Console only exists in Firebug so check it exists before trying to write to it
            if (TVI.firebugCheck() === true) {
                console.profile(title);
            }
        },

        /**
        * Stops Firebug's profiler.
        */
        logProfileEnd: function() {

            // Console only exists in Firebug so check it exists before trying to write to it
            if (TVI.firebugCheck() === true) {
                console.profileEnd();
            }
        },

        /**
        * Prints an interactive stack trace of JavaScript execution at the point where it is called.
        */
        logTrace: function() {

            // Console only exists in Firebug so check it exists before trying to write to it
            if (TVI.firebugCheck() === true) {
                console.trace();
            }
        }

    });

})();



// ********** TVI UTIL ********** //
TVI.util = {};

TVI.apply(TVI.util, {
	
	/**
     * Adds a new option to a select element.
     * @param {Object} e - the select element we are adding the option to.
     * @param {String} v - the value of the option we want to add.
     * @param {String} t - the text of the option we want to add.
     */
	addSelectOption: function(e, v, t){
		var option = document.createElement("option");
	    option.value = v;
	    
		// Set the text to the same as the value if it hasn't been supplied
		if(t === null || t === "" || t === undefined){
			option.text = v;
		}
		else{
			option.text = t;
		}
	
	    // get current options
	    var o = e.options;
	
	    // get number of options
	    var oL = o.length;
	
	    if (!e.cache) {
	        e.cache = {};
	        // loop through existing options, adding to cache
	        for (var l = 0; l < oL; l++) {
	            e.cache[o[l].value] = l;
	        }
	    }
	
	    // add to cache if it isn't already
	    if (typeof e.cache[v] == "undefined") {
	        e.cache[v] = oL;
	    }
	    e.options[e.cache[v]] = option;
	},
	
	/**
     * Selects an item in the jQuery Select list based on it's value.
     * @param {Object} e - the select element we are adding the option to.
     * @param {String} v - the value of the option we want to select.
     */
	selectOption: function(e, v){
		
		// Find the select list
		e.each(function(){

			// Shortcut to options and length of the options
			o = this.options;
			optionsLength = this.options.length;
			
			// Loop through all the options
			for (var i = 0; i < optionsLength; i++) {
				
				// If the option matches then select it
				if(o[i].value == v){
					o[i].selected = true;
				}

			}
		});

	},
	
	
	/**
     * Returns the text of the selected item in the select list passed in
     * @param {Object} e - the jQuery select element we are adding the option to.
     */
	getSelectedOptionText: function(e){
		
		return e[0].options[e[0].selectedIndex].text;
	},
	
	
	/**
     * converts all special characters in a string to HTML entities and returns the string
     * @param {Object} s - the string to entitify.
     */
	stringToEntities: function(s){
		
		return $('<div/>').text(s).html().replace('"',"&quot;");
	},
	
	/**
     * converts all HTML entities in a string to original characters and returns the string
     * @param {Object} s - the string to deEntitify.
     */
	stringFromEntities: function(s){
		
		$('#temp').html(s);
		return $('#temp').html();
	},
	
	/**
     * converts all quotes in a string to their ascii code equivelants
     * @param {Object} s - the string to encode.
     */
	encodeQuotes: function(s){
		
		var output = s;
		s = s.replace(/"/g,'&#34;');
		s = s.replace(/'/g,'&#39;');
		return s;
	},
	
	/**
     * converts all ascii quote codes in a string back into quotes
     * @param {Object} s - the string to encode.
     */
	decodeQuotes: function(s){
		
		var output = s;
		s = s.replace(/&#34;/g,'"');
		s = s.replace(/&#39;/g,"'");
		return s;
	}

	
}); // End of TVI.util



// ***************************************************************** //
// ******** Override and extend default objects and methods ******** //
// ***************************************************************** //

// Add an Array.indexOf method to IE
if(!Array.indexOf){
	Array.prototype.indexOf = function(obj){
		var L = this.length;
			for(var i=0; i<L; i++){
				if(this[i]==obj){
				return i;
			}
		}
		return -1;
	};
}


//*******************************************************//
//                                                       //
//    TVI Component Manager - Last Updated 01/09/2008    //
//                                                       //
//*******************************************************//

// This is just here to tell JS lint that we need to use a global variable
/*global TVI , document, $ , that */

/** 
* COMPONENT MANAGER - A registry for all components created by the TVI JavaScript Framework.
* @author	Jon Hobbs
* @version 1.0
*/
TVI.ComponentManager = function(allowFunctions) {
	
	this.allowFunctions = allowFunctions === true;
	
	return {
		
		/**
		 * Do we allow functions to be stored in this collection? Always yes because we're using it to store components
		 * @property allowFunctions
		 * @type {boolean}
		 */
		allowFunctions: this.allowFunctions,
		/**
		 * The number of components in the registry
		 * @property length
		 * @type {Integer}
		 */
		length:0,
		/**
		 * An Array of objects, each one being a TVI component.
		 * @property items
		 * @type {Array}
		 */
		items: [],
		/**
		 * An Array of keys, which hold the ID of each component.
		 * @property keys
		 * @type {Array}
		 */
		keys: [],
		/**
		 * An object containing a map of keys to components.
		 * @property map
		 * @type {Object}
		 */
		map: {},
		
		/**
		 * add (public)
	     * Adds a new component to the registry
	     * @param {string}   k		The key of the component to add to the key collection.
	     * @param {object}   o		The component to add to the registry.
	     */
		register: function(k, o){
			
			// Check to see if a key has been supplied
	        if(arguments.length == 1){
				// If no key has been supplied then the component is the first parameter, not the second
	            o = arguments[0];
				// And we need to try to get the key for this component
	            k = this.getKey(o);
	        }
			// Check to see if we now have a key
	        if(typeof k == "undefined" || k === null){
				// if we haven't then register the component anyway, with a null key and don't addid to the map
	            this.length++;
	            this.items.push(o);
	            this.keys.push(null);
	        }else{
				// If we have got a key then check to see if the component is already in the gegistry
	            var old = this.map[k];
	            if(old){
					// If the component is already in the registry then call the replace function instead of adding it.
	                return this.replace(k, o);
	            }
				// If we have a key and the component is not already in the registry then add it and add it to the map.
	            this.length++;
	            this.items.push(o);
	            this.map[k] = o;
	            this.keys.push(k);
	        }
	        return o;
	    },
		
		/**
		 * getKey (public)
	     * Returns the ID of a component to use as the key
	     * @param {o} config	The component to get the key for
	     */
		getKey : function(o){
	         return o.id;
	    },
		
		/**
		 * replace (public)
	     * Replaces a component in the registry
	     * @param {string}   k		The key of the component to add to the key collection.
	     * @param {object}   o		The component to add to the registry.
	     */
		replace : function(k, o){
			
			// Check to see if a key has been supplied
	        if(arguments.length == 1){
				// If no key has been supplied then the component is the first parameter, not the second
	            o = arguments[0];
				// And we need to try to get the key for this component
	            k = this.getKey(o);
	        }
			// Get the old item that is being replaced
	        var old = this.item(k);
			// If no key has been supplied, or the old item couldn't be found then call the add function 
			// instead of replacing anything.
	        if(typeof k == "undefined" || k === null || typeof old == "undefined"){
	             return this.add(k, o);
	        }
			// If the old item has been found then replace it in the items array and in the map
	        var index = this.indexOfKey(k);
	        this.items[index] = o;
	        this.map[k] = o;
	        return o;
	    },
		
		
		/**
		* Returns index of the compnent in the registry
		* @param {Object} o The component to find the index of.
		* @return {Integer} index of the component.
		*/
		indexOf : function(o){
			return this.items.indexOf(o);
		},
	
		/**
		* Returns index of the component using the supplied key.
		* @param {String} key 	The key to find the index of.
		* @return {Integer} index of the key.
		*/
		indexOfKey : function(k){
			return this.keys.indexOf(k);
		},
		
		/**
		* Returns the item associated with the passed key OR index. Key has priority over index.
		* @param {String/Number} k The key or index of the item.
		* @return {Object} The item associated with the passed key.
		*/
		item : function(k){
			
			// Create the item. If a key has been supplied then it will find the item in the map and return it.
			// If it isn't found then k must ben an index, so return the item from the items array
		    var item = typeof this.map[k] != "undefined" ? this.map[k] : this.items[k];
			
			// If the item isn't a function, or functions are allowed then return it, otherwise return null
		    return typeof item != 'function' || this.allowFunctions ? item : null;
		}
			
	};
	
}(); 




//**************************************************//
//                                                  //
//     TVI Panel Bar - Last Updated 08/10/2008      //
//                                                  //
//**************************************************//

// This is just here to tell JS lint that we need to use a global variable
/*global TVI , document, $ , that, alert, i, j, k */

/** 
* PANEL BAR - An object representing a TVI panel bar
* @param {Object} config	Contains all the config options
* @author	Jon Hobbs
* @version 1.0
*/

TVI.PanelBar = function(config) {

	/**
	 * @cfg {string} id
	 * The unique id of the PanelBar
	 */
	/**
	 * @cfg {string} openEffect
	 * The effect to use when opening a panel
	 * Allowed values - slide, fade
	 */
	/**
	 * @cfg {decimal} openSpeed
	 * The number speed to use when opening a panel, in miliseconds
	 */
	/**
	 * @cfg {string} closeEffect
	 * The effect to use when opening a panel
	 * Allowed values - slide, fade
	 */
	/**
	 * @cfg {decimal} closeSpeed
	 * The number speed to use when opening a panel, in miliseconds
	 */
	/**
	 * @cfg {boolean} allowMultipleOpenPanels
	 * Whether to allow more than one panel to be open at a time
	 */
	
	// Declare defaults
	var defaults = {
		openEffect: 'slide',
		openSpeed: 300,
		closeEffect: 'slide',
		closeSpeed: 300,
		allowMultipleOpenPanels: true
	};

	// Apply config
	TVI.apply(this, config, defaults);
	
	// Create unique id if one doesn't already exist
	TVI.createID(this);
	
	// Register with the component manager
	TVI.ComponentManager.register(this.id, this);

	
	// Run the initialize method
	this.initialize();
	
};

TVI.PanelBar.prototype = {
	

	/**
	 * initialize (public)
     * initializes the Panel Bar
     */
	initialize: function(){
		
		var component = this;
		
		// Get the root element
		var element = $('#' + component.id);
		
		//Attach the click events
		element.find('.TVI-panelBar-button').click(function(){
		
			//get the item element and make sure we only get the nearest parent
			var itemElement =  $(this).parents('.TVI-panelBar-item');
			itemElement = itemElement.eq(0);
			
			// *******************************************/
			// **************** Closed Items *************/
			// *******************************************/
			
			if(itemElement.hasClass('closed')){
				
				// Check to see whether to close the other panels or not
				if(component.allowMultipleOpenPanels === false){
					
					//Check what type of animation to use
					switch(component.closeEffect)
					{
						case 'slide':
								element.find('.TVI-panelBar-item.open .TVI-panelBar-panel').slideUp(component.closeSpeed);
							break;    
						case 'fade':
								element.find('.TVI-panelBar-item.open .TVI-panelBar-panel').fadeOut(component.closeSpeed);
							break;
					}
					
					// Get the items
					var items = element.find('.TVI-panelBar-item.open');

					//Switch the classes
					items.removeClass('open');
					items.addClass('closed');
					
				}

				//Get the panel element
				panelElement = itemElement.find('.TVI-panelBar-panel');
				
				//Check what type of animation to use
				switch(component.openEffect)
				{
					case 'slide':
							panelElement.slideDown(component.openSpeed);
						break;    
					case 'fade':
							panelElement.fadeIn(component.openSpeed);
						break;
				}
				
				//Switch the classes
				itemElement.removeClass('closed');
				itemElement.addClass('open');

				// Prevent the default behaviour
				return false;
			}
			
			// *******************************************/
			// **************** Open Items ***************/
			// *******************************************/
			
			else if(itemElement.hasClass('open')){

				
				
				//Get the panel element
				panelElement = itemElement.find('.TVI-panelBar-panel');
				
				//Check what type of animation to use
				switch(component.closeEffect)
				{
					case 'slide':
						panelElement.slideUp(component.closeSpeed);
						//Switch the classes
						itemElement.removeClass('open');
						itemElement.addClass('closed');
						break;    
					case 'fade':
						panelElement.fadeOut(component.closeSpeed, function(){
							//Switch the classes
							itemElement.removeClass('open');
							itemElement.addClass('closed');
						});
						break;
				}
				
				

				// Prevent the default behaviour
				return false;
			}
		
		});

	}
	
};



//**************************************************//
//                                                  //
//     TVI Tool Tips - Last Updated 12/11/2008      //
//                                                  //
//**************************************************//

// This is just here to tell JS lint that we need to use a global variable
/*global TVI , document, $ , that, alert, i, j, k */

///<reference path="TVI.js" />

/**
* Dependency - TVI.js
* Dependency - TVIComponentManager.js
* Dependency - trimpath-template.js
*/


/** 
* TOOL TIP MANAGER - An object representing a TVI Tool tip manager
* @param {Object} config	Contains all the config options
* @author	Jon Hobbs
* @version 1.0
* 
* Method - addTip           : Adds a new tooltip to the tips collection
* Method - removeTip        : Removes a tip from the manager
* Method - hideTip          : Hides a single tip
* Method - hideAllTips      : Hides all toolTips
* Method - showTip          : Shows a single tip
* Method - showAllTips      : Shows all toolTips
*/

TVI.ToolTipManager = function(config) {

	/**
	 * @cfg {string} id
	 * The unique id of the Tool Tip Manager
	 */
	 /**
	 * @cfg {number} layerZIndex
	 * layerZIndex
	 */
	 /**
	 * @cfg {number} allowMultipleTips
	 * If set to false, all other tooltips will be destroyed when a new one is created.
	 */
	
	// Declare defaults
	var defaults = {
	    layerZIndex: 8000000,
	    allowMultipleTips: true
	};

	// Apply config
	TVI.apply(this, config, defaults);
	
	// Create unique id if one doesn't already exist
	TVI.createID(this);
	
	// Register with the component manager
	TVI.ComponentManager.register(this.id, this);

	
	// Run the initialize method
	this.initialize();
	
};

TVI.ToolTipManager.prototype = {
	
	
	/**
	 * @property {number} zIndexCounter
	 * The current Z-Index so that new tooltips always get layered on top of each other.
	 */
	zIndexCounter: 1,
	
	/**
	 * @property {array} tips
	 * An array of TVI.ToolTip objects
	 */
	tips: [],

    /**
	 * initialize (public)
     * initializes the toolTipManager
     */
	initialize: function(){
	
	    var component = this;
	
	    // Create the toolTipManager element on the page
	    $('BODY').append('<div id="' + component.id + '" class="TVI-ToolTipManager" style="z-index:' + 8000000 + ';"></div>');
	
	},


    /**
	 * getNewZIndex (public)
     * Increments zIndexCounter and returns a new Z-index.
     */
     getNewZIndex: function(){
        return this.zIndexCounter++;
     },
     

	/**
	 * addTip (public)
     * Adds a new toolTip to the Manager
     */
	addTip: function(params){
	
	    TVI.logComment("addTip called");
		
		var component = this;
		
		// Check to see if it already exists
		var alreadyExist = false;
		var existingTip  = {};
		var tipsLength = component.tips.length;
		
		for (i=0; i < tipsLength; i++){
		    if(component.tips[i].id == params.id){
		        existingTip = component.tips[i];
		        alreadyExist = true;
		    }
		}
        
        // Hide all other tooltips if we need to
        if (component.allowMultipleTips === false){
            component.hideAllTips();
        }
		
		//If the tip doesn't exist then create it, if it does then just call it's show method.
		if (alreadyExist === false){
		
		    
		    // Merge the toolTip deaults with the settings supplied
		    var settings = component.tipDefaults;
		    settings.skin = {};
		    TVI.apply(settings, params);
    		
		    // Add the skin to the settings
		    var skin = component.skinDefaults; // Get the skin defaults from the manager
		    TVI.apply(skin, params.skin); // Add the skin settings that have been supplied for this tip
		    TVI.apply(settings.skin, skin); // Add them all to the main settings
		    
		    // Add some new settings
		    TVI.apply(settings, {
		        toolTipManagerID: component.id
		    });
    		
		    // Create the new toolTip
		    var tooltip = new TVI.ToolTip(settings);
    		
		    // Add the toolTip to the tips collection
		    component.tips.push(tooltip);
    		
		    // Return a reference to the newly created tooltip
		    return tooltip;
		    
		}
		else{
		
		    // If the tooTip already exists then show it.
		    existingTip.draw();
		    existingTip.show();
		    
		    // Return a reference to the tooltip we just showed
		    return existingTip;
		}
	},
	
	/**
	 * removeTip (public)
     * Removes a tip from the manager
     */
	removeTip: function(params){
	
	    var component = this;

	    // Loop through all the tips in the collection and find the right one
	    var tipsLength = component.tips.length;
		for (i=0; i < tipsLength; i++){
		    if(component.tips[i].id == params.id){
		    
		        // Remove from DOM unless told not to
		        if (params.removeFromDom !== false){
        		    component.tips[i].destroy();
		        }
		    
		        // Remove it from the tips collection
		        component.tips.splice(i,1);
		    }
		}
	},
	
	
	/**
	 * hideTip (public)
     * Calls the hide method of a single tip
     */
	hideTip: function(params){
	    
	    var component = this;
	    
        // Loop through all the toolTips and find the right one
	    var tipsLength = component.tips.length;
	    for (i=0; i < tipsLength; i++){
	    
	        if (component.tips[i].id == params.id){
	            // Call the show method
	            component.tips[i].id.hide();
	        }
		}
	    
	},
	
	
	/**
	 * hideAllTips (public)
     * Hides all of the toolTips
     */
	hideAllTips: function(params){
	    
	    var component = this;
	    
	    // Loop through all the toolTips and call their hide function
	    var tipsLength = component.tips.length;
	    for (i=0; i < tipsLength; i++){
		    component.tips[i].hide();
		}
	    
	},
	
	
	/**
	 * showTip (public)
     * Calls the show method of a single tip
     */
	showTip: function(params){
	    
	    var component = this;
	    
	    // Hide all other tooltips if we need to
        if (component.allowMultipleTips === false){
            component.hideAllTips();
        }
        
        // Loop through all the toolTips and find the right one
	    var tipsLength = component.tips.length;
	    for (i=0; i < tipsLength; i++){
	    
	        if (component.tips[i].id == params.id){
	            // Call the show method
	            component.tips[i].id.show();
	        }
		}
	    
	},
	
	
	/**
	 * showAllTips (public)
     * Shows all of the toolTips
     */
	showAllTips: function(params){
	    
	    var component = this;
	    
	    // Loop through all the toolTips and call their show function
	    var tipsLength = component.tips.length;
	    for (i=0; i < tipsLength; i++){
		    component.tips[i].show();
		}
	    
	}
	
};



/** 
* TOOL TIP - An object representing a TVI Tooltip 
* @param {Object} config	Contains all the config options
* @author	Jon Hobbs
* @version 1.0
* 
* Method - initialize       : Creates the tooltip by adding all the dom elements
* Method - draw             : Draws the tooltip but resizing and positioning all elements around the content
* Method - show             : Shows the toolTip using the chosen effect
* Method - hide             : Hide the toolTip using the chosen effect
* Method - destroy          : Destroys the tooltip
*/



TVI.ToolTip = function(config) {

	/**
	 * @cfg {string} id
	 * The unique id of the Tool Tip
	 */
	 /**
	 * @cfg {string} openEffect
	 * The opening effect of the Tool Tip
	 */
	 /**
	 * @cfg {string} openSpeed
	 * The open speed of the Tool Tip
	 */
	 /**
	 * @cfg {string} closeEffect
	 * The close effect of the Tool Tip
	 */
	 /**
	 * @cfg {string} closeSpeed
	 * The close speed of the Tool Tip
	 */
	 /**
	 * @cfg {string} closeButtonAction
	 * What it does when closing the tooltip (destroy or hide)
	 */
	 /**
	 * @cfg {string} offsetX
	 * The overall offet X of the Tool Tip
	 */
	 /**
	 * @cfg {string} offsetY
	 * The overall offet Y of the Tool Tip
	 */
	
	// Declare defaults
	var defaults = {
	
	    openEffect: 'fade',
	    openSpeed: 'fast',
	    closeEffect: 'fade',
	    closeSpeed: 'fast',
	    closeButtonAction: 'destroy',
	    offsetX: 0,
	    offsetY: 0,
	
	    skin: {
	    
	        usesPng: false,
	    
	        outerLeftWidth: 0,
            outerRightWidth: 0,
            outerTopHeight: 0,
            outerBottomHeight: 0,
            
            pointerTopWidth: 0,
            pointerTopHeight: 0,
            pointerTopSpritePos: 0,
            pointerTopPointX: 0,
            pointerTopPointY: 0,
            pointerTopXOffset: 0,
            pointerTopYOffset: 0,
            
            pointerRightWidth: 0,
            pointerRightHeight: 0,
            pointerRightSpritePos: 0,
            
            pointerBottomWidth: 0,
            pointerBottomHeight: 0,
            pointerBottomSpritePos: 0,
            
            pointerLeftWidth: 0,
            pointerLeftHeight: 0,
            pointerLeftSpritePos: 0
	    }
	};

	// Apply config
	TVI.apply(this, config, defaults);
	
	// Apply the skin again because we overwrote it.
	var skin = defaults.skin;
	TVI.apply(skin, config.skin);
	TVI.apply(this.skin, skin); 
	
	// Create unique id if one doesn't already exist
	TVI.createID(this);
	
	// Register with the component manager
	TVI.ComponentManager.register(this.id, this);
	
	// Run the initialize method
	this.initialize();
	
};

TVI.ToolTip.prototype = {

    /**
    * initialize (public)
    * initializes the toolTip
    */
    initialize: function() {

        TVI.logTimer('Initializing toolTip');

        var component = this;


        // Create HTML for the tooltip element
        var zIndex = TVI.ComponentManager.item(component.toolTipManagerID).getNewZIndex();
        component.toolTipElement = $('<div id="' + component.id + '" class="TVI-ToolTip ' + component.skin.toolTipClass + '" style="position:absolute; visibility:none; z-index:' + zIndex + ';"></div>');

        // Create the HTML for the 9 tooltip divs
        var outerLeftWidth = component.skin.outerLeftWidth + 'px';
        var outerRightWidth = component.skin.outerRightWidth + 'px';
        var outerTopHeight = component.skin.outerTopHeight + 'px';
        var outerBottomHeight = component.skin.outerBottomHeight + 'px';

        component.topLeftElement = $('<div id="' + component.id + '-topLeft" class="' + component.skin.topLeftClass + '" style="position:absolute; width:' + outerLeftWidth + '; height:' + outerTopHeight + ';"></div>');
        component.topMiddleElement = $('<div id="' + component.id + '-topMiddle" class="' + component.skin.topMiddleClass + '" style="position:absolute; height:' + outerTopHeight + ';"></div>');
        component.topRightElement = $('<div id="' + component.id + '-topRight" class="' + component.skin.topRightClass + '" style="position:absolute; width:' + outerRightWidth + '; height:' + outerTopHeight + ';"></div>');
        component.middleLeftElement = $('<div id="' + component.id + '-middleLeft" class="' + component.skin.middleLeftClass + '" style="position:absolute; width:' + outerLeftWidth + ';"></div>');
        component.middleElement = $('<div id="' + component.id + '-middle" class="' + component.skin.middleClass + '" style="position:absolute;"></div>');
        component.middleRightElement = $('<div id="' + component.id + '-middleRight" class="' + component.skin.middleRightClass + '" style="position:absolute; width:' + outerRightWidth + ';"></div>');
        component.bottomLeftElement = $('<div id="' + component.id + '-bottomLeft" class="' + component.skin.bottomLeftClass + '" style="position:absolute; width:' + outerLeftWidth + '; height:' + outerBottomHeight + ';"></div>');
        component.bottomMiddleElement = $('<div id="' + component.id + '-bottomMiddle" class="' + component.skin.bottomMiddleClass + '" style="position:absolute; height:' + outerBottomHeight + ';"></div>');
        component.bottomRightElement = $('<div id="' + component.id + '-bottomRight" class="' + component.skin.bottomRightClass + '" style="position:absolute; width:' + outerRightWidth + '; height:' + outerBottomHeight + ';"></div>');

        // If a content template has been supplied then merge it with the content
        if (component.skin.contentTemplate !== undefined) {
            component.content = TrimPath.parseTemplate(component.skin.contentTemplate).process({ "content": component.content });
        }

        // Add the content to the middle cell
        component.middleElement.append(component.content);

        // Create an element for the bubble
        component.bubbleElement = $('<div id="' + component.id + '-bubble" class="bubble" style="position:absolute"></div>');

        // Create an element for the pointer and set it's class depending on the position
        switch (component.position) {
            case 'top':
                component.pointerElement = $('<div class="pointer ' + component.skin.pointerTopClass + '" style="position:absolute; width:' + component.skin.pointerTopWidth + 'px; height:' + component.skin.pointerTopHeight + 'px;"></div>');
                break;
            case 'right':
                component.pointerElement = $('<div class="pointer ' + component.skin.pointerRightClass + '" style="position:absolute; width:' + component.skin.pointerRightWidth + 'px; height:' + component.skin.pointerRightHeight + 'px;"></div>');
                break;
            case 'bottom':
                component.pointerElement = $('<div class="pointer ' + component.skin.pointerBottomClass + '" style="position:absolute; width:' + component.skin.pointerBottomWidth + 'px; height:' + component.skin.pointerBottomHeight + 'px;"></div>');
                break;
            case 'left':
                component.pointerElement = $('<div class="pointer ' + component.skin.pointerLeftClass + '" style="position:absolute; width:' + component.skin.pointerLeftWidth + 'px; height:' + component.skin.pointerLeftHeight + 'px;"></div>');
                break;
        }
        
        // Set the id and the styles from settings
        component.pointerElement.attr('id', component.id + '-pointer');



        // Add the 9 divs to the bubble element
        component.bubbleElement.append(component.topLeftElement);
        component.bubbleElement.append(component.topMiddleElement);
        component.bubbleElement.append(component.topRightElement);
        component.bubbleElement.append(component.middleLeftElement);
        component.bubbleElement.append(component.middleElement);
        component.bubbleElement.append(component.middleRightElement);
        component.bubbleElement.append(component.bottomLeftElement);
        component.bubbleElement.append(component.bottomMiddleElement);
        component.bubbleElement.append(component.bottomRightElement);

        // Add the bubble and the pointer to an element called innerElement
        component.innerElement = $('<div class="toolTipInner"></div>');
        component.innerElement.append(component.bubbleElement);
        component.innerElement.append(component.pointerElement);

        // Add the inner element to the toolTip
        component.toolTipElement.append(component.innerElement);

        // Add the toolTip element to the page
        if (component.toolTipManagerID !== undefined && component.toolTipManagerID !== null) {
            $('#' + component.toolTipManagerID).append(component.toolTipElement);
        }
        else {
            $('BODY').append(component.toolTipElement);
        }

        // Add the correct z-index to the close button
        zIndex = TVI.ComponentManager.item(component.toolTipManagerID).getNewZIndex();
        component.middleElement.css({ 'z-index': zIndex });


        /***************************************************************/
        /************** Add events *************************************/
        /***************************************************************/

        // Add action to the close button
        component.middleElement.find('.close').click(function() {

            // Check to see what the close button action is
            switch (component.closeButtonAction) {

                case 'destroy':
                    component.destroy();
                    break;

                case 'hide':
                    component.hide();                 
                    break;
            }
            return false;
        });


        TVI.logTimerEnd('Initializing toolTip');

        /***************************************************************/
        /************** Draw and position the Tool Tip *****************/
        /***************************************************************/

        component.draw();
        component.show();

    },


    /**
    * draw (public)
    * Draw and position the tooltip
    */
    draw: function() {

        TVI.logTimer('Drawing toolTip');

        var component = this;

        // Move the toolTip off the screen while we re-draw it.
        component.toolTipElement.css({ left: "-10000px", top: "-10000px" });

        // Position the tooltip out of view and make sure the tip is visible
        component.toolTipElement.show();
        component.toolTipElement.css({ left: "-10000px", top: "-10000px" });
        
        // Set the width if it has been specified
        if (component.width) {
            component.middleElement.width(component.width - component.skin.outerLeftWidth - component.skin.outerRightWidth);
        }

        // Set the height if it has been specified
        if (component.height) {
            component.middleElement.height(component.height - component.skin.outerTopHeight - component.skin.outerBottomHeight);
        }

        // Get the dimensions of the middle div
        var middleWidth = component.middleElement.width();
        var middleHeight = component.middleElement.height();

        // Set the width and height of the bubble
        var bubbleWidth = component.skin.outerLeftWidth + middleWidth + component.skin.outerRightWidth;
        var bubbleHeight = component.skin.outerTopHeight + middleHeight + component.skin.outerBottomHeight;
        component.bubbleElement.width(bubbleWidth);
        component.bubbleElement.height(bubbleHeight);

        // Position everything in the bubble
        component.topMiddleElement.css({ left: component.skin.outerLeftWidth, width: middleWidth });
        component.topRightElement.css({ left: component.skin.outerLeftWidth + middleWidth });
        component.middleLeftElement.css({ top: component.skin.outerTopHeight, height: middleHeight });
        component.middleElement.css({ left: component.skin.outerLeftWidth, top: component.skin.outerTopHeight });
        component.middleRightElement.css({ left: component.skin.outerLeftWidth + middleWidth, top: component.skin.outerTopHeight, height: middleHeight });
        component.bottomLeftElement.css({ top: component.skin.outerTopHeight + middleHeight });
        component.bottomMiddleElement.css({ top: component.skin.outerTopHeight + middleHeight, left: component.skin.outerLeftWidth, width: middleWidth });
        component.bottomRightElement.css({ top: component.skin.outerTopHeight + middleHeight, left: component.skin.outerLeftWidth + middleWidth });

        // Get the source element and it's dimension
        var sourceElement = $('#' + component.relativeTo);
        var sourceTopLeftX = sourceElement.offset().left;
        var sourceTopLeftY = sourceElement.offset().top;
        var sourceWidth = sourceElement.width();
        var sourceHeight = sourceElement.height();

        // Get the position that the tip of the pointer needs to end up
        var tipX = sourceTopLeftX;
        var tipY = sourceTopLeftY;

        switch (component.relativeXpos) {
            case 'middle':
                tipX = sourceTopLeftX + (sourceWidth / 2);
                break;
            case 'right':
                tipX = sourceTopLeftX + (sourceWidth);
                break;
        }

        switch (component.relativeYpos) {
            case 'middle':
                tipY = sourceTopLeftY + (sourceHeight / 2);
                break;
            case 'bottom':
                tipY = sourceTopLeftY + (sourceHeight);
                break;
        }

        /// Create variables to hold the positions
        var pointerLeftPos = 0;
        var pointerTopPos = 0;
        var tipPositionX = 0;
        var tipPositionY = 0;
        var bubbleLeft = 0;
        var bubbleTop = 0;

        // Where are we going to position the bubble?
        switch (component.position) {
            case 'top':

                // Position the pointer
                pointerLeftPos = (bubbleWidth / 2) - component.skin.pointerTopPointX + component.skin.pointerTopXOffset;
                pointerTopPos = bubbleHeight + component.skin.pointerTopYOffset;
                component.pointerElement.css({ left: pointerLeftPos, top: pointerTopPos });

                // Get the X and Y position to place the toolTip at
                tipPositionX = tipX - pointerLeftPos - component.skin.pointerTopPointX;
                tipPositionY = tipY - pointerTopPos - component.skin.pointerTopPointY;

                break;

            case 'right':

                // Position the pointer
                pointerTopPos = (bubbleHeight / 2) - component.skin.pointerRightPointY + component.skin.pointerRightYOffset;
                component.pointerElement.css({ left: 0, top: pointerTopPos });

                // Reposition the bubble
                bubbleLeft = component.skin.pointerRightWidth - component.skin.pointerRightXOffset;
                component.bubbleElement.css({ left: bubbleLeft });

                // Get the X and Y position to place the toolTip at
                tipPositionX = tipX;
                tipPositionY = tipY - pointerTopPos - component.skin.pointerRightPointY;

                break;

            case 'bottom':

                // Position the pointer
                pointerLeftPos = (bubbleWidth / 2) - component.skin.pointerBottomPointX + component.skin.pointerBottomXOffset;
                component.pointerElement.css({ left: pointerLeftPos, top: 0 });

                // Reposition the bubble
                bubbleTop = component.skin.pointerBottomHeight - component.skin.pointerBottomYOffset;
                component.bubbleElement.css({ top: bubbleTop });

                // Get the X and Y position to place the toolTip at
                tipPositionX = tipX - pointerLeftPos - component.skin.pointerBottomPointX;
                tipPositionY = tipY - component.skin.pointerBottomPointY;

                break;

            case 'left':

                // Position the pointer
                pointerLeftPos = bubbleWidth + component.skin.pointerLeftXOffset;
                pointerTopPos = (bubbleHeight / 2) - component.skin.pointerLeftPointY + component.skin.pointerLeftYOffset;
                component.pointerElement.css({ left: pointerLeftPos, top: pointerTopPos });

                // Get the X and Y position to place the toolTip at
                tipPositionX = tipX - pointerLeftPos - component.skin.pointerLeftPointX;
                tipPositionY = tipY - pointerTopPos - component.skin.pointerLeftPointY;

                break;
        }
        
        // Add offset values to reposition overall tooltip
        tipPositionX += component.offsetX;
        tipPositionY += component.offsetY;

        // Position the tooltip
        component.toolTipElement.hide();
        component.toolTipElement.css({ left: tipPositionX + "px", top: tipPositionY + "px" });


        TVI.logTimerEnd('Drawing toolTip');

    },


    /**
    * show (public)
    * Shows the toopTip
    */
    show: function() {

        var component = this;

        TVI.logComment("toolTip.show called for " + component.id);

        // Work out what effect to use to show the tip
        switch (component.openEffect) {

            case 'none':

                component.toolTipElement.show();
                break;
                
            case 'fade':

                // Check to see we're not using a browser or PNG combination that can't do fades.
                TVI.userAgent = navigator.userAgent.toLowerCase();
                $.browser.chrome = /chrome/.test(TVI.userAgent);
                if (($.browser.chrome || $.browser.msie) && component.skin.usesPng === true) {

                    // If the browser/png combination isn't compatible with fades then just show the tip
                    component.toolTipElement.show();
                }
                else {

                    // If it is compatible then do the fade
                    component.toolTipElement.fadeIn(component.openSpeed);
                }

                break;
        }
    },


    /**
    * hide (public)
    * Hides the toopTip
    */
    hide: function() {

        var component = this;

        TVI.logComment("hide called");

        // Work out what effect to use to show the tip
        switch (component.closeEffect) {

            case 'none':

                component.toolTipElement.css({ left: "-10000px", top: "-10000px" });
                break;

            case 'fade':


                // Check to see we're not using a browser or PNG combination that can't do fades.
                TVI.userAgent = navigator.userAgent.toLowerCase();
                $.browser.chrome = /chrome/.test(TVI.userAgent);
                if (($.browser.chrome || $.browser.msie) && component.skin.usesPng === true) {

                    // If the browser/png combination isn't compatible with fades then just show the tip
                    component.toolTipElement.hide();
                }
                else {

                    // If it is compatible then do the fade
                    component.toolTipElement.fadeOut(component.closeSpeed, function() {
                        component.toolTipElement.css({ left: "-10000px", top: "-10000px" });
                    });
                }

                break;
        }


    },

    /**
    * destroy (public)
    * Removes the tooltip from it's manager and from the page
    */
    destroy: function() {

        var component = this;

        // Remove the tooltip from the dom
        component.toolTipElement.remove();

        // Remove it from it's manager
        var toolTipManager = TVI.ComponentManager.item(component.toolTipManagerID);
        toolTipManager.removeTip({
            id: component.id,
            "removeFromDom": false
        });

    }

};



$(document).ready(function(){var a=navigator.userAgent.toLowerCase();$.browser.chrome=/chrome/.test(navigator.userAgent.toLowerCase());if($.browser.msie){$('body').addClass('browserIE');$('body').addClass('browserIE'+$.browser.version.substring(0,1))}if($.browser.chrome){$('body').addClass('browserChrome');a=a.substring(a.indexOf('chrome/index.html')+7);a=a.substring(0,1);$('body').addClass('browserChrome'+a);$.browser.safari=false}if($.browser.safari){$('body').addClass('browserSafari');a=a.substring(a.indexOf('version/index.html')+8);a=a.substring(0,1);$('body').addClass('browserSafari'+a)}if($.browser.mozilla){if(navigator.userAgent.toLowerCase().indexOf('firefox')!=-1){$('body').addClass('browserFirefox');a=a.substring(a.indexOf('firefox/index.html')+8);a=a.substring(0,1);$('body').addClass('browserFirefox'+a)}else{$('body').addClass('browserMozilla')}}if($.browser.opera){$('body').addClass('browserOpera')}});jQuery.preloadImages = function() {
    var a = (typeof arguments[0] == 'object')? arguments[0] : arguments;
    for(var i = a.length -1; i > 0; i--) {
    jQuery("<img>").attr("src", a[i]);
    }
}



// declare web namespace
WEB = {};

// apply default properties and methods to the web namespace
TVI.apply(WEB, {

    /**
    * Remember whether the form is currently open or closed
    */
    isFormOpen: false,

    /**
    * Opens purple form dropdown at top of page
    * @param {String} openEaseType - easing method when opening form
    * @param {Number} openEaseDuration - duration of opening form
    */
    openForm: function(params) {

        var defaultParams = {
            easeType: 'jswing',
            easeDuration: 'fast',
            formName: 'getQuote'
        };

        var params = TVI.apply(defaultParams, params);

        //hide any tooltips
        if (WEB.purpleToolTipManager) {
            WEB.purpleToolTipManager.hideAllTips();
        }

        if (!WEB.isFormOpen) {

            WEB.isFormOpen = true;

            //Slide down unless IE6, in which case 'show'
            if ($('body').hasClass('browserIE6')) {
                $('.dropDown.' + params.formName + ' .middle').show();
            } else {
                $('.dropDown.' + params.formName + ' .middle').slideDown(params.easeDuration, params.easeType);
            }

            $('.dropDown.' + params.formName + ' .top').show();
            $('.dropDown.' + params.formName + ' .bottom').show();

        } else if (WEB.isFormOpen) {

            //Fade to new content unless IE6, in which case 'show'
            if ($('body').hasClass('browserIE6')) {
                $('.dropDown .dropDownContainer').hide(function() {
                    $('.dropDown .middle').hide();
                    $('.dropDown.' + params.formName + ' .middle').show();
                    $('.dropDown .top').hide();
                    $('.dropDown.' + params.formName + ' .top').show();
                    $('.dropDown .bottom').hide();
                    $('.dropDown.' + params.formName + ' .bottom').show();
                    $('.dropDown .dropDownContainer').show();
                });
            } else {
                $('.dropDown .dropDownContainer').fadeTo('fast', 0, function() {
                    $('.dropDown .middle').hide();
                    $('.dropDown.' + params.formName + ' .middle').show();
                    $('.dropDown .top').hide();
                    $('.dropDown.' + params.formName + ' .top').show();
                    $('.dropDown .bottom').hide();
                    $('.dropDown.' + params.formName + ' .bottom').show();
                    $('.dropDown .dropDownContainer').fadeTo('normal', 1);
                });
            }
        }

        //reset form
        switch (params.formName) {
            case "getQuote":
                topnavQuoteReset();
                break;
            case "requestDemo":
                topnavDemoReset();
                break;
            case "contactUs":
                topnavContactReset();
                break;
        }

        //google analytics
        switch (params.formName) {
            case "getQuote":
                pageTracker._trackPageview('/formQuoteOpen');
                break;
            case "requestDemo":
                pageTracker._trackPageview('/formDemoOpen');
                break;
            case "contactUs":
                pageTracker._trackPageview('/formContactOpen');
                break;
        }

    },

    /**
    * Closes purple form dropdown at top of page
    * @param {String} closeEaseType - easing method when closing form
    * @param {Number} closeEaseDuration - duration of closing form
    */
    closeForm: function(params) {

        if (WEB.isFormOpen) {

            var defaultParams = {
                easeType: 'jswing',
                easeDuration: 'normal'
            };

            var params = TVI.apply(defaultParams, params);

            //hide any tooltips
            if (WEB.purpleToolTipManager) {
                WEB.purpleToolTipManager.hideAllTips();
            }

            //Slide up unless IE6, in which case 'hide'
            if ($('body').hasClass('browserIE6')) {
                $('.dropDown .top').hide();
                $('.dropDown .middle').hide();
                $('.dropDown .bottom').hide();
            } else {
                $('.dropDown .top').hide();
                $('.dropDown .middle').slideUp(params.easeDuration, params.easeType);
                $('.dropDown .bottom').slideUp(params.easeDuration * 0.75, params.easeType);
            }

            WEB.isFormOpen = false;

            // Slide map up
            $('.mapPopup').slideUp();

        }
    }
});



// Check that the page has loaded
$(document).ready(function() {

    $('#forms').load('dropDownForms.htm', function() {

        topnavInit();

        // DROP DOWN BOX FUNCTIONALITY    
        $('#topNav li').click(function() {

            if ($(this).hasClass('quote')) {
                WEB.openForm({
                    easeType: 'easeOutElasticTVI',
                    easeDuration: 2000,
                    formName: 'getQuote'
                });
            } else if ($(this).hasClass('demo')) {
                WEB.openForm({
                    easeType: 'easeOutElasticTVI',
                    easeDuration: 2000,
                    formName: 'requestDemo'
                });
            } else if ($(this).hasClass('contact')) {
                WEB.openForm({
                    easeType: 'easeOutElasticTVI',
                    easeDuration: 2000,
                    formName: 'contactUs'
                });

                // Pre-load the picture of our office
                $('.mapCol3').empty().append('<img src="/i/Office.jpg" alt="TVI offices" />');

            }

            $('#topNav li a').removeClass('hover'); // Remove 'hover' from all menu items (reset)

            $(this).find('a').addClass('hover'); // add 'hover' to menu item that was cliked

            return false;
        });


        // Add close functionality top drop down
        $('.dropDown .close').click(function() {

            WEB.closeForm({
                easeDuration: 400
            });

            $('#topNav li a').removeClass('hover'); // Remove 'hover' from all menu items (reset)
        });


        // Map popup
        $('.contactMapDirections').click(function() {

            // Fade in the popup
            $('.mapPopup').fadeIn();

            // Check to see if the map exists and create it if it doesn't.
            if (WEB.map === undefined) {

                // Create a function to run once the google map script has loaded
                WEB.loadMap = function() {

                    if (GBrowserIsCompatible()) {
                        WEB.map = new GMap2(document.getElementById("map"));
                        WEB.map.setCenter(new GLatLng(51.82138, -0.83825), 14);
                        WEB.map.addControl(new GSmallMapControl());
                        WEB.map.addControl(new GScaleControl());
                        WEB.map.addControl(new GMapTypeControl());

                        var TVIIcon = new GIcon();
                        TVIIcon.image = "i/pin.png";
                        TVIIcon.shadow = "i/pin.shaddow.png";
                        TVIIcon.iconSize = new GSize(52, 46);
                        TVIIcon.shadowSize = new GSize(52, 46);
                        TVIIcon.iconAnchor = new GPoint(21, 46);

                        //Add marker
                        tvi_marker = new GMarker(new GLatLng(51.82063, -0.83809), TVIIcon);
                        WEB.map.addOverlay(tvi_marker);

                    }

                    // Add the unload funciton to the body tag
                    $(window).unload(function() { GUnload(); });

                };

                // Load the google maps scripts and call the callback function (loadMap)
                var script = document.createElement("script");
                script.setAttribute("src", "http://maps.google.com/maps?file=api&amp;v=2.x&amp;key=ABQIAAAAlTu0Wl0whd7Rs8E517hr5BRf9kGOvOrE7ymGju7jEZBv_3R1ChSVfkUbCDyJlILiHh8JsqQ-vXVeIg&amp;async=2&amp;callback=WEB.loadMap");
                script.setAttribute("type", "text/javascript");
                document.documentElement.firstChild.appendChild(script);

            }

            return false;
        });

        $('.mapPopup #mapPopupClose').click(function() {
            $('.mapPopup').fadeOut();

            return false;
        });

    });


    // Local scroll
    //$.localScroll({ duration: 300 });

    // Scroll up to top of page and show quote form when request quote menu item is clicked or with class openQuote
    $('#mainMenu .requestQuoteLink, .openQuote').click(function() {

        // Scroll then open form
        $.scrollTo('#header', 300, function() {
            $('#topNav li.quote').click();
        });

        if ($('body').hasClass('browserChrome')) {
        } else {
            return false;
        }
    });

    // Scroll up to top of page and show quote form when request quote menu item is clicked or with class openRequestDemo
    $('.openRequestDemo').click(function() {

        // Scroll then open form
        $.scrollTo('#header', 300, function() {
            $('#topNav li.demo').click();
        });

        if ($('body').hasClass('browserChrome')) {
        } else {
            return false;
        }
    });

    // Scroll up to top of page and show contact form when request contact menu item is clicked or with class openContact
    $('#mainMenu .contactUsLink, .openContact').click(function() {

        $('#textBox_ContactMessage').val('');

        // Scroll then open form
        $.scrollTo('#header', 300, function() {
            $('#topNav li.contact').click();
        });

        if ($('body').hasClass('browserChrome')) {
        } else {
            return false;
        }
    });

    // Scroll up to top of page and show contact form when link with class openConsultation is clicked
    // Also prefill your message textbox
    $('.openConsultation').click(function() {

        $('#textBox_ContactMessage').val("Please arrange a free 60 minute ecommerce consultation. Please call me at the following time (e.g 2pm):");

        // Scroll then open form
        $.scrollTo('#header', 300, function() {
            $('#topNav li.contact').click();
        });

        if ($('body').hasClass('browserChrome')) {
        } else {
            return false;
        }
    });



    // Create main menu panel bar
    var mainMenu = new TVI.PanelBar({
        id: 'mainMenu1',
        openEffect: 'slide',
        openSpeed: 300,
        closeEffect: 'slide',
        closeSpeed: 300
    });
    // Create main menu panel bar
    var mainMenu = new TVI.PanelBar({
        id: 'mainMenu2',
        openEffect: 'slide',
        openSpeed: 300,
        closeEffect: 'slide',
        closeSpeed: 300
    });
    // Create main menu panel bar
    var mainMenu = new TVI.PanelBar({
        id: 'mainMenu3',
        openEffect: 'slide',
        openSpeed: 300,
        closeEffect: 'slide',
        closeSpeed: 300
    });
    // Create main menu panel bar
    var mainMenu = new TVI.PanelBar({
        id: 'mainMenu',
        openEffect: 'slide',
        openSpeed: 300,
        closeEffect: 'slide',
        closeSpeed: 300
    });

	// Create main menu panel bar
    var mainMenu = new TVI.PanelBar({
        id: 'mainMenu2',
        openEffect: 'slide',
        openSpeed: 300,
        closeEffect: 'slide',
        closeSpeed: 300
    });

    // remove background for last sub footer column
    $('#subFooter .column:last').css({ background: 'none' });


    // Quote marks for promo box    
    $('.promoBox .quote').prepend('<img src="i/quote_left.gif" />');
    $('.promoBox .quote').append('<img src="i/quote_right.gif" />');

    //Fix google toobar autocomplete
    var timer;
    for (var count = 0; count < 20; count++) {
        setTimeout("resetInputs()", 50 * count);
    }
    timer = setInterval("resetInputs()", 250);

    // PRELOAD
    var preload = [
                "/i/bg_dropDown_top.gif",
                "i/titles/contact_us.gif",
                "i/titles/get_a_quote.gif", 
                "i/titles/footer_blog.gif", 
                "i/titles/footer_mainMenu.gif", 
                "i/titles/footer_services.gif", 
                "i/titles/footer_smallPrint.gif", 
                "i/titles/request_a_demo.gif", 
                "i/bg_blueberries.jpg", 
                "i/bg_blueberries.jpg", 
                "i/bg_dropdown_bottom.png", 
                "i/bg_dropdown.png", 
                "i/bg_dropdown_bottom_IE.gif", 
                "i/bg_dropdown_IE.gif", 
                "i/bg_dropdown_top.gif", 
                "i/textBoxLabel.gif", 
                "i/textArea_bg.gif", 
                "i/textArea_bg_contact.gif", 
                "i/textArea_bg_getQuote.gif", 
                "i/textAreaBottom.gif", 
                "i/textAreaBottom_contactUs.gif", 
                "i/textAreaBottom_qetQuote.gif", 
                "i/textAreaLabel.gif", 
                "i/textAreaLabel_getQuote.gif", 
                "i/textBox_bg.gif", 
                "i/mainNav_submenu_selected.gif", 
                "i/mainNav_submenu_selected.png", 
                "i/mainMenu_submenu_gradient.gif", 
                "i/mainMenu_submenu_gradient.png"
                ];

        $.preloadImages(preload);

}); 

function resetInputs(){

    $('#forms').find('select').css("background-color", "transparent");
    $('#forms').find('input').css("background-color", "transparent");
}

// Set up the page
function createPage(pageName){
    if (pageName != ""){
        $(document).ready(function() {
            // Once the document is finished loading, get the link to the passed in page and run the click function of its panelbar
            $('.TVI-panelBar-panel-item a[@name=' + pageName + ']').addClass('selected').parents('.TVI-panelBar-item').removeClass("closed").addClass("open");
        });
    }

}
//********************************************//
//                                            //
//     TVI Forms - version 1 - 03/09/2008     //
//                                            //
//********************************************//

// This is just here to tell JS lint that we need to use a global variable
/*global TVI , document, $ , index , scroll , url , that */

// ********** VALIDATION RULE ********** //
TVI.ValidationRule = function(config) {
	
	/**
	 * @cfg {string} id
	 * The unique id of the ValidationRule
	 */
	/**
	 * @cfg {string} type
	 * Type of validation - e.g. required/length/min/max etc.
	 */
	/**
	 * @cfg {string} parameters
	 * parameters to apply to rules - e.g. {"max":"35"}
	 */
	/**
	 * @cfg {string} errorMessage
	 * The error message returned if validation fails
	 */
	
	// Create defaults
	var defaults = {
		errorMessage: "Please check this field."
	};
	
	// Apply config and defaults
	TVI.apply(this, config, defaults);
	
	// Create unique id if one doesn't already exist
	TVI.createID(this);

}; // End of TVI.ValidationRule



// ********** FORM FIELD ********** //
TVI.FormField = function(config) {

	/**
	 * @cfg {string} id
	 * The unique id of the FormField
	 */
	/**
	 * @cfg {string} fieldType
	 * The type of field, should match one of the options in TVI.fieldTypes
	 */
	/**
	 * @cfg {string} dataType
	 * The data type of field, should match one of the options in TVI.dataTypes
	 */
	/**
	 * @cfg {string} fieldIndex
	 * The position of the field in the form
	 */
	/**
	 * @cfg {array} options
	 * An array of options, only used if fieldType is set to dropDownList
	 */
	/**
	 * @cfg {array} validationRules
	 * An array of validation rules which have been created for this field
	 */

	// Apply config
	TVI.apply(this, config);
	
	// Create unique id if one doesn't already exist
	TVI.createID(this);
	


};

TVI.FormField.prototype = {

    /**
    * getControls (public)
    * Returns the html controls which make up the field
    */
    getControls: function() {

        // Find out what the field type is and then return the input elements
        switch (this.fieldType) {
            case 'textBox':
                return $('#textBox_' + this.id);
            case 'password':
                return $('#password_' + this.id);
            case 'textArea':
                return $('#textArea_' + this.id);
            case 'dropDownList':
                return $('#dropDownList_' + this.id);
            case 'multiRadio':
                return $('input[id^="multiRadio_' + this.id + '"]');
            default:
                return $('#' + this.fieldType + '_' + this.id);
        }
    },

    /**
    * getContent (public)
    * Returns the content of the field
    */
    getContent: function(params) {

        // If a params object has been supplied then use it to create private variables
        if (params) {
            var returnText = params.returnText;
        }

        // Check which type of field it is
        switch (this.fieldType) {
            case 'dropDownList':

                // If we're dealing with a drop down list then check to see if we need to return the value or the text
                if (returnText) {
                    return TVI.util.getSelectedOptionText(this.getControls());
                }
                else {
                    return this.getControls().val();
                }
                break;
            case 'multiRadio':
                var content = '';
                this.getControls().each(function() {
                    if (this.checked) {
                        content = this.value;
                    }
                });
                return content;
            default:
                // If it is any other kind of control then just return it's value
                return this.getControls().val();
        }
    },

    /**
    * setContent (public)
    * Sets the content of the field
    */
    setContent: function(content) {

        // Check what the type of the field is
        switch (this.fieldType) {

            case 'textBox':

                // If it's a date then remove the time portion
                if (this.dataType == 'date') {
                    this.getControls().val(content.substring(0, 10));
                }
                else {
                    this.getControls().val(content);
                }
                break;
            case 'password':
                this.getControls().val(content);
                break;
            case 'textArea':
                this.getControls().val(content);
                break;
            case 'dropDownList':
                TVI.util.selectOption(this.getControls(), content);
                break;
            case 'multiRadio':
                this.getControls().each(function() {
                    if (this.value == content) {
                        this.checked = true;
                    }
                });
                break;
            case 'checkBox':
                // TODO
                break;
            case 'multiCheckBox':
                // TODO
                break;
            default:
                // TODO
        }
    }

};  // End of TVI.FormField





// ********** FORM ********** //

TVI.Form = function(config) {

	/**
	 * @cfg {string} id
	 * id of the component and the root HTML element. 
	 */
	/**
	 * @cfg {string} formName
	 * The name of the form
	 */
	/**
	 * @cfg {string} metaDataURL
	 * The URL to use to get the config
	 */
	/**
	 * @cfg {string} loadQuery
	 * The query used to load a record into the form
	 */
	/**
	 * @cfg {string} loadUrl
	 * The URL to use when loading recorda record into the form
	 */
	/**
	 * @cfg {string} saveQuery
	 * The query used to save the contents of a form to a database record
	 */
	/**
	 * @cfg {string} saveUrl
	 * The URL to use when saving the contents of the form
	 */
	/**
	 * @cfg {function} initFailure
	 * Function to run when form fails to initialize
	 */
	/**
	 * @cfg {boolean} autoLoad
	 * Automatically load the contents of the form when it initializes
	 */
	
	// Declare defaults
	var defaults = {
		metaDataURL: 'handlers/forms.aspx/getFormMetaData',
		loadURL: 'handlers/data.aspx/getRecords',
		saveURL: 'handlers/data.aspx/editRecord',
		autoLoad: true,
		initFailure: function(){
			alert('Initialization Error');
		},
		handleError: function(response){
			alert(response);
		}
	};

	// Apply config
	TVI.apply(this, config, defaults);
	
	// Create unique id if one doesn't already exist
	TVI.createID(this);
	
	// Register with the component manager
	TVI.ComponentManager.register(this.id, this);
	
};

TVI.Form.prototype = {

    /**
    * Array of TVI.FormFields representing the HTML form
    * @type Array
    * @property
    */
    fields: [],

    /**
    * initialize (public)
    * Initializes the Form by scanning the HTML and creating an array of TVI.FormFields
    */
    initialize: function() {

        var that = this;

        // Clear the fields array
        this.fields = [];

        // create a jQuery element from the elementID, then create a private variable that references it.
        this.element = $('#' + this.id);
        this.form = this.element;

        // Create JSON data for the
        var jsonData = '{"config":{"id":"' + this.formName + '"}}';

        // Make an ajax call to get the metadata to create the formTable
        $.ajax({
            type: 'POST',
            url: that.metaDataURL,
            data: jsonData,
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            success: function(data) {

                // Get the retorned JSON
                var response = data.d;

                // Check to see if the respone has been successful
                if (response.success) {

                    // Create a counter
                    var fieldCounter = 1;

                    // Create a shortcut to the fields length
                    var fieldsLength = response.fields.length;

                    // Loop through the columns
                    for (i = 0; i < fieldsLength; i++) {

                        // Create an array to hold the validationRules
                        var validationRules = [];

                        // Create a shortcut to the columns length
                        var validationRulesLength = response.fields[i].validationRules.length;

                        // Loop through the validation rules and add them to the array
                        for (j = 0; j < validationRulesLength; j++) {

                            //Set up a new validation rule
                            var newValidationRule = new TVI.ValidationRule();

                            // Fille the validationRule properties
                            newValidationRule.type = response.fields[i].validationRules[j].type;
                            newValidationRule.parameters = response.fields[i].validationRules[j].parameters;
                            newValidationRule.errorMessage = response.fields[i].validationRules[j].errorMessage;

                            // Add the new validation rule to the array
                            validationRules.push(newValidationRule);
                        }


                        // Create an array to hold the optionsW
                        var options = [];

                        // Create a shortcut to the options length
                        var optionsLength = response.fields[i].options.length;

                        // Loop through the options and add them to the array
                        for (k = 0; k < optionsLength; k++) {

                            // Add the option to the options array
                            options.push(response.fields[i].options[k]);
                        }

                        // Create a TVI.FormField to add to the column
                        var newFormField = new TVI.FormField({
                            id: response.fields[i].id,
                            fieldType: response.fields[i].fieldType,
                            dataType: response.fields[i].dataType,
                            fieldIndex: fieldCounter,
                            options: options,
                            validationRules: validationRules
                        });


                        that.fields.push(newFormField);

                        // Increment the field index counter
                        fieldCounter++;
                    }


                    // Create functions for attaching validation events
                    function attachValidation(eventType, field, excludeCurrent) {

                        //Get the field Index to validate up to
                        var fieldIndex = field.fieldIndex;
                        // Minus 1 if we're not going to validate the current element
                        if (excludeCurrent) {
                            fieldIndex--;
                        }

                        // Check which type of event to add
                        switch (eventType) {
                            case 'blur':
                                // Get the controls in this field and attach onBlur function to start validation
                                field.getControls().blur(function() {
                                    that.validate(fieldIndex);
                                });
                                break;
                            case 'focus':
                                // Get the controls in this field and attach onFocus function to start validation
                                field.getControls().focus(function() {
                                    that.validate(fieldIndex);
                                });
                                break;
                            case 'change':
                                // Get the controls in this field and attach onChange function to start validation
                                field.getControls().change(function() {
                                    that.validate(fieldIndex);
                                });
                                break;
                            default:
                                // do nothing if we don't recognise the event type
                        }

                    }


                    // Add all of the validation events to the form fields
                    for (var i = 0; i < that.fields.length; i++) {

                        // Check which type of field it is and attach the correct events
                        switch (that.fields[i].fieldType) {
                            case 'textBox':
                                attachValidation('focus', that.fields[i], true);
                                attachValidation('blur', that.fields[i]);
                                break;
                            case 'textArea':
                                attachValidation('focus', that.fields[i], true);
                                attachValidation('blur', that.fields[i]);
                                break;
                            case 'password':
                                attachValidation('focus', that.fields[i], true);
                                attachValidation('blur', that.fields[i]);
                                break;
                            case 'dropDownList':
                                attachValidation('focus', that.fields[i], true);
                                attachValidation('change', that.fields[i]);
                                break;
                            default:
                                // do nothing if we don't recognise the field type
                        }

                    }



                }
                else {
                    //TODO deal with error message
                }
            },
            failure: function() {
                // If the connection to the server fails then run the failure function passed in
                that.initFailure();
            }
        });


    }, // End of initialize()

    /**
    * validate (public)
    * Validates the form and returns TRUE if all fields validate correctly
    * @param {integer}   index		The index of the control to stop validating at.
    * @param {boolean}   scroll	Should it scroll to the first error after validating.
    */
    validate: function(index, scroll) {

        var errors = false;
        var firstError = "";
        scroll = scroll || false;

        // Loop through all fields
        for (var i = 0; i < this.fields.length; i++) {

            // Only validate fields up to the current field which have validation rules
            if ((this.fields[i].fieldIndex <= index || index === undefined || index === null) && this.fields[i].validationRules.length > 0) {

                var fieldError = false;

                // Loop through the validation rules
                for (var j = 0; j < this.fields[i].validationRules.length; j++) {

                    // Get the field content that needs to be verified 
                    var fieldContent = this.fields[i].getContent();

                    // Create Params for the validator
                    var params = "";
                    if (this.fields[i].validationRules[j].parameters !== null) {
                        params = this.fields[i].validationRules[j].parameters;
                    }

                    // Check it against the relevant validator
                    var validationResponse = TVI.validators[this.fields[i].validationRules[j].type](fieldContent, params);

                    if (validationResponse.success === false) {

                        if (validationResponse.code == "020001" || validationResponse.code == "30003") {

                            // Add the error class to the element
                            $('#' + this.fields[i].id).addClass('error');

                            // Clear error message and add a new one
                            $('#' + this.fields[i].id + ' .errorMessage').empty().append(this.fields[i].validationRules[j].errorMessage);

                            fieldError = true;

                            // Set this as the first error if one doesn't already exist
                            if (!errors) {
                                firstError = this.fields[i].id;
                            }
                            errors = true;
                            break;
                        }
                        else {
                            // TODO
                        }
                    }
                }

                // Remove the error class and message if there are no errors, then set the errors variable
                if (fieldError === false) {
                    $('#' + this.fields[i].id).removeClass('error');
                    $('#' + this.fields[i].id + ' .errorMessage').empty();

                }

            }
        }

        // If there are any errors then scroll to the first one
        if (errors && scroll) {
            $.scrollTo($('#' + firstError), 400, { offset: -50 });

        }
        return (!errors);

    },  // End of validate()


    /**
    * clearForm (public)
    * Resets all the controls in the form
    */
    clearForm: function() {

        // Shortcut to the length of the fields in the form
        var fieldsLength = this.fields.length;

        // Loop through all the fields in the form
        for (var i = 0; i < fieldsLength; i++) {

            // Check what the type of the field is
            switch (this.fields[i].fieldType) {
                case 'textBox':
                    this.fields[i].getControls().val('');
                    break;
                case 'password':
                    this.fields[i].getControls().val('');
                    break;
                case 'textArea':
                    this.fields[i].getControls().val('');
                    break;
                case 'dropDownList':
                    // TODO
                    break;
                case 'multiRadio':
                    break;
                // TODO 
                case 'checkBox':
                    // TODO
                    break;
                case 'multiCheckBox':
                    // TODO
                    break;
                default:
                    // TODO
            }
        }
    },


    /**
    * loadRecord (public)
    * Loads a record from the data layer into the form
    * @param {Object}   params		A list of parameters
    */
    loadRecord: function(params) {

        // If a config object has been supplied then use it to create private variables
        if (params) {
            var rowID = params.rowID;
            var success = params.success;
            var failure = params.failure;
            var error = params.error;
        }

        var that = this;

        // Create the JSON data
        var jsonData = '';
        jsonData += '{"config":{';
        jsonData += '"query":"' + this.loadQuery + '"';
        if (rowID) {
            jsonData += ',"rowID":"' + rowID + '"';
        }
        jsonData += '}}';


        // Put the Ajax function in a function to create a closure
        function ajaxCall() {

            // Make an ajax call to get the records
            $.ajax({
                type: 'POST',
                url: that.loadURL,
                data: jsonData,
                contentType: 'application/json; charset=utf-8',
                dataType: 'json',
                success: function(data) {

                    // Get the retorned JSON
                    var response = JSON.parse(data.d);

                    // Check to see if the response was successful
                    if (response.success === true) {

                        // Clear the form
                        that.clearForm();

                        // Loop through all the fields in the response and insert them into the form
                        var fieldsLength = that.fields.length;
                        for (var i = 0; i < fieldsLength; i++) {

                            //Get index of field in response array
                            var fieldIndex = 0;
                            var arrayFieldsLength = response.columns.length;
                            for (j = 0; j < arrayFieldsLength; j++) {

                                // Check to see if we've found the right field
                                if (response.columns[j] == that.fields[i].id) {

                                    // If we have then record the index so that we can get it's content
                                    fieldIndex = j;
                                }
                            }

                            // Check to make sure we found the field in the response
                            if (fieldIndex !== 0) {

                                // Get the field content from the response
                                var content = response.records[0][fieldIndex];

                                // Convert the quotes
                                content = TVI.util.decodeQuotes(content);

                                // Set the content of the field
                                that.fields[i].setContent(content);
                            }
                        }
                        // If a success function has been passed in then run it
                        if (success) { success(response); }
                    }
                    else {
                        // Log the error and then run the failure function if it exists
                        TVI.logError(response);
                        if (failure) { failure(response); }
                    }
                },
                // If the ajax call fails then log an error and then run the failure function if it exists
                error: function() {
                    TVI.logError({ "code": "050007", "errorMessage": "Failed to load form data from database." });
                    if (error) { error(); }
                }
            });
        }
        // Call the ajax function to get the record
        ajaxCall();
    },


    /**
    * saveData (public)
    * Creates a JSON string and makes a jQuery ajax call to save the form data back to the database via a web method.
    * @param {Object}   params		A list of parameters
    */
    saveData: function(params) {

        TVI.logGroup('SaveData');
        TVI.logComment('started');

        // If a config object has been supplied then use it to create private variables
        if (params) {
            var rowID = params.rowID;
            var success = params.success;
            var failure = params.failure;
        }

        var that = this;

        // Check to see if the form validates before we save it
        if (this.validate() === false) {
            return false;
        }

        // The JSON string that will be sent to the addURL
        var jsonData = "";

        // Create a variable for checking the first item which doesn't need a comma
        var first = true;

        // Create the JSON data
        jsonData += '{"config":{';
        jsonData += '"query":"' + this.saveQuery + '"';
        jsonData += ',"parameters":"{';
        if (rowID) {
            jsonData += '\\"rowID\\":\\"' + rowID + '\\",';
        }

        // Create shortcut to length of columns
        var fieldsLength = this.fields.length;

        // Loop through all fields
        for (var i = 0; i < fieldsLength; i++) {

            // If this isn't the first item then add a comma
            if (first === false) {
                jsonData += ",";
            }
            else {
                first = false;
            }

            // Get the field content that needs to be verified
            jsonData += '\\"' + this.fields[i].id + '\\":\\"' + TVI.util.encodeQuotes(this.fields[i].getContent()) + '\\"';
        }

        // End the JSON data
        jsonData += '}"}}';

        TVI.logGroupEnd('SaveData');


        // Put the Ajax call in a function to create a closure
        function ajaxCall(context) {

            var that = context;

            // Make an ajax call to get the records
            $.ajax({
                type: 'POST',
                url: that.saveURL,
                data: jsonData,
                contentType: 'application/json; charset=utf-8',
                dataType: 'json',
                success: function(data) {

                    // Get the retorned JSON
                    var response = JSON.parse(data.d);

                    // Check to see if the result was positive
                    if (response.success === true) {
                        // If a success function has been passed in then run it
                        if (success) { success(); }
                    }
                    else {
                        // Log the error and then run the failure function if it exists
                        TVI.logError(response);
                        if (failure) { failure(response); }
                    }
                },
                error: function() {

                    // Log the error and then run the failure function if it exists
                    TVI.logError({ "code": "050008", "message": "Failed to save the form data to the database" });
                    if (error) { error(); }
                }
            });

        }

        // Call the ajax function to delete the record
        ajaxCall(this);

    }

};




//*************************************************//
//                                                 //
//     TVI Validators - Last Updated 26/08/2008    //
//                                                 //
//*************************************************//

// This is just here to tell JS lint that we need to use a global variable
/*global TVI , json_parse, document */



// ToDo:

//    regex - { expression: '[ \t\r\n]' }
//TVI.validators.regex = function(content, params){
//    ///<summary>
//    ///Validator to check against a regex
//    ///</summary>
//    params = params.replace("\\", "\\\\");
//    alert(params);
//    try 
//    {
//    var paramsJSON = json_parse(params);
//    }
//    catch(err)
//    {
//    alert(err.toString())
//    }
//    
//    var filter  = new RegExp(paramsJSON["expression"]);
//    return ((filter.test(content)))        
//};
// {"expression":"'/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/'"}

// Date - Needs params for future and past
// Value/Values/Equals parameters need merging
// Tests for matches


/// <reference path="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" />
/// <reference path="JSONParse-Min.js" />


TVI.validators = {};

TVI.validators.JSONRemoveCase = function (JSON){
    ///<summary>
    ///Converts all JSON data entered into lower case
    ///</summary>
    if (JSON.value !== undefined){
        JSON.value = JSON.value.toLowerCase();
    }
    else if (JSON.values !== undefined){
        for ( var i in JSON.values){
			// Check that we're only dealing with proper values, not stuff inherited through the prototype
			if (JSON.values.hasOwnProperty(i)) {
		        JSON.values[i] = JSON.values[i].toLowerCase();
		    }
        }
    }
    return JSON;
};


TVI.apply(TVI.validators, {

    /**
    * String to return for success
    * @type String
    * @property
    */
    defaultValidMessage: { "success": true },
    /**
    * String to return for failure
    * @type String
    * @property
    */
    defaultInvalidMessage: { "success": false, "code": "020001", "message": "Invalid" },
    /**
    * String to return when some parameters have not been supplied to the validator
    * @type String
    * @property
    */
    defaultMissingParamsMessage: { "success": false, "code": "020002", "message": "Some parameters were not supplied" },


    /**
    * required (public)
    * Required Field Validator, returns false for whitespace
    * @param {string}   content	The content of the field being validated
    */
    required: function(content) {

        if (content === undefined) {
            return TVI.validators.defaultMissingParamsMessage;
        }
        else if (content === "") {
            return TVI.validators.defaultInvalidMessage;
        }
        else {
            //Javascript string.trim equivalent
            content = content.replace(/^\s+|\s+$/g, '');
            if (content === "") {
                return TVI.validators.defaultInvalidMessage;
            }
            return TVI.validators.defaultValidMessage;
        }
    },


    /**
    * length (public)
    * length validator, checks the length of the content.
    * @param {string}   content	The content of the field being validated
    * @param {object}   params		Validation parameters
    * {"max":"35", "min":"8", "equals":"8", "between": "3-5"} 
    */
    length: function(content, params) {

        if (content === undefined || params === undefined) {
            return TVI.validators.defaultMissingParamsMessage;
        }
        else if (content === "") {
            return TVI.validators.defaultValidMessage;
        }
        else {

            // Parse JSON Data
            var paramsJSON = JSON.parse(params);

            // Check if we need to invoke the MAX rule
            if (paramsJSON.max !== undefined) {

                // If content is longer than MAX then return invalid message
                if (content.length > paramsJSON.max) {
                    return TVI.validators.defaultInvalidMessage;
                }
            }

            // Check if we need to invoke the MIN rule
            else if (paramsJSON.min !== undefined) {

                // If content is shorter than MIN then return invalid message
                if (content.length < paramsJSON.min) {
                    return TVI.validators.defaultInvalidMessage;
                }
            }

            // Check if we need to invoke the EQUALS rule
            else if (paramsJSON.equals !== undefined) {

                // If the content length does not match the EQUALS parameter then return invalid message
                if (content.length != paramsJSON.equals) {
                    return TVI.validators.defaultInvalidMessage;
                }
            }

            // Check if we need to invoke the BETWEEN rule
            else if (paramsJSON.between !== undefined) {

                // Get the minimum from the BETWEEN parameter
                var min = paramsJSON.between.substring(0, paramsJSON.between.indexOf("-"));

                // Get the maximum from the BETWEEN parameter
                var max = paramsJSON.between.substring(paramsJSON.between.indexOf("-") + 1);

                // If the content length is not between the minimum and maximum then return invalid message
                if (!((content.length >= min) && (content.length <= max))) {
                    return TVI.validators.defaultInvalidMessage;
                }
            }

            // If we can't find any correct paramaters to check then return error code
            else {
                return TVI.validators.defaultMissingParamsMessage;
            }

            // If none of the validation type have failed then return success
            return TVI.validators.defaultValidMessage;
        }

    },


    /**
    * is (public)
    * is validator, checks the content to see if it matches a value or one of an array of values.
    * @param {string}   content	The content of the field being validated
    * @param {object}   params		Validation parameters
    * {"value": "hello", "values": ["one", "two", "three"], "caseSensitive" : "true"}
    */
    is: function(content, params) {

        if (content === undefined || params === undefined) {
            return TVI.validators.defaultMissingParamsMessage;
        }
        else if (content === "") {
            return TVI.validators.defaultValidMessage;
        }
        else {
            // Parse JSON Data
            var paramsJSON = JSON.parse(params);

            //Check for casesensitive and deal with it if not!
            if (!(paramsJSON.caseSensitive !== undefined && paramsJSON.caseSensitive == "true")) {
                paramsJSON = TVI.validators.JSONRemoveCase(paramsJSON);
                content = content.toLowerCase();
            }

            // Check if we need to invoke the VALUE rule
            if (paramsJSON.value !== undefined) {

                // If content doesn't match the value then return invalid message
                if (content !== paramsJSON.value) {
                    return TVI.validators.defaultInvalidMessage;
                }
            }

            // Check if we need to invoke the VALUES rule
            else if (paramsJSON.values !== undefined) {

                // Loop through values parameters and return true if a match is found
                for (var i in paramsJSON.values) {
                    if (content == paramsJSON.values[i]) {
                        return TVI.validators.defaultValidMessage;
                    }
                }
                // If not returned true after looping is finished, return false
                return TVI.validators.defaultInvalidMessage;
            }
            else {
                return TVI.validators.defaultMissingParamsMessage;
            }

            // If none of the validation type have failed then return success
            return TVI.validators.defaultValidMessage;
        }
    },


    /**
    * itemSelected (public)
    * itemSelected validator, checks the content to see an item has been chosen or not.
    * @param {string}   content	The content of the field being validated
    */
    itemSelected: function(content) {

        if (content === undefined) {
            return TVI.validators.defaultMissingParamsMessage;
        }
        else if (content != "") {
            return TVI.validators.defaultValidMessage;
        }
        else {
            return TVI.validators.defaultInvalidMessage;
        }

    },


    /**
    * contains (public)
    * Validator to check contents of string for match
    * @param {string}   content		The content of the field being validated
    * @param {object}   params			Validation parameters 
    * {"value": "hello", "values": ["one", "two", "three"], "caseSensitive" : "true"}
    */
    contains: function(content, params) {
        if (content === undefined || params === undefined) {
            return TVI.validators.defaultMissingParamsMessage;

        }
        else if (content === "") {
            return TVI.validators.defaultValidMessage;
        }
        else {
            // Parse JSON Data
            var paramsJSON = JSON.parse(params);

            //Check for casesensitive and deal with it if not!
            if (!(paramsJSON.caseSensitive !== undefined && paramsJSON.caseSensitive == "true")) {
                paramsJSON = TVI.validators.JSONRemoveCase(paramsJSON);
                content = content.toLowerCase();
            }
            // Check for value parameter and run rule
            if (paramsJSON.value !== undefined) {
                // If content doesn't contain a match then return invalid message
                if (paramsJSON.value.match(content) === null) {
                    return TVI.validators.defaultInvalidMessage;
                }
            }
            // Check for values parameter
            else if (paramsJSON.values !== undefined) {
                // Variable to keep track of if we've found a match
                var returned = false;
                // Loop through values parameters and return true if a match is found
                for (var i in paramsJSON.values) {
                    if (paramsJSON.values[i].match(content)) {
                        return TVI.validators.defaultValidMessage;
                    }
                }
                // If not returned true after looping is finished, return false
                return TVI.validators.defaultInvalidMessage;
            }
            else {
                return TVI.validators.defaultMissingParamsMessage;
            }

            // If none of the validation type have failed then return success
            return TVI.validators.defaultValidMessage;
        }
    },


    /**
    * numeric (public)
    * Checks for a number with optional params
    * @param {string}   content		The content of the field being validated
    * @param {object}   params			Validation parameters 
    * {"max":"35", "min":"8", "equals":"8", "between": "3-5"} 
    */
    numeric: function(content, params) {

        if (content === undefined || params === undefined) {
            return TVI.validators.defaultMissingParamsMessage;
        }
        else
            if (content === "") {
            return TVI.validators.defaultValidMessage;
        }
        else {
            // Parse JSON Data (in an if so that params can be optional)
            if (params !== "") {
                var paramsJSON = JSON.parse(params);
            }

            //Check if its actually a number
            if (isFinite(content)) {
                if (paramsJSON !== undefined) {
                    // Check if we need to invoke the MAX rule
                    if (paramsJSON.max !== undefined) {
                        // If content is higher than MAX then return invalid message
                        if (Number(content) > paramsJSON.max) {
                            return TVI.validators.defaultInvalidMessage;
                        }
                    }
                    // Check if we need to invoke the MIN rule
                    else
                        if (paramsJSON.min !== undefined) {
                        // If content is lower than MIN then return invalid message
                        if (Number(content) < paramsJSON.min) {
                            return TVI.validators.defaultInvalidMessage;
                        }
                    }
                    // Check if we need to invoke the EQUALS rule
                    else
                        if (paramsJSON.equals !== undefined) {
                        // If content does not equal EQUALS return invalid message
                        if (Number(content) != paramsJSON.equals) {
                            return TVI.validators.defaultInvalidMessage;
                        }
                    }
                    // Check if we need to invoke the BETWEEN rule
                    else
                        if (paramsJSON.between !== undefined) {
                        // Get the minimum from the BETWEEN parameter
                        var min = paramsJSON.between.substring(0, paramsJSON.between.indexOf("-"));

                        // Get the maximum from the BETWEEN parameter
                        var max = paramsJSON.between.substring(paramsJSON.between.indexOf("-") + 1);

                        // If the content length is not between the minimum and maximum then return invalid message
                        if (!((Number(content) >= min) && (Number(content) <= max))) {
                            return TVI.validators.defaultInvalidMessage;
                        }
                    }

                    // If we can't find any correct paramaters to check then return error code
                    else {
                        return TVI.validators.defaultMissingParamsMessage;
                    }
                }

                // If none of the validation type have failed then return success
                return TVI.validators.defaultValidMessage;
            }
            else {
                return TVI.validators.defaultInvalidMessage;
            }
        }
    },


    /**
    * integer (public)
    * Checks for a whole number with optional params
    * @param {string}   content		The content of the field being validated
    * @param {object}   params			Validation parameters - max: 35, min: 8, equals: 8, between: 3-5
    */
    integer: function(content, params) {

        if (content === undefined || params === undefined) {
            return TVI.validators.defaultMissingParamsMessage;
        }
        else if (content === "") {
            return TVI.validators.defaultValidMessage;
        }
        else {
            // Parse JSON Data (in an if so that params can be optional)
            if (params !== "") {
                var paramsJSON = JSON.parse(params);
            }
            // Check if its actually a whole number by comparing its value
            // To the output of parseint for it, if it wasn't whole
            // They won't be the same
            if (content == parseInt(content, 10) && parseInt(content, 10) >= 0) {
                // Check if there are params
                if (paramsJSON !== undefined) {
                    // Check if we need to invoke the MAX rule
                    if (paramsJSON.max !== undefined) {
                        // If content is higher than MAX then return invalid message
                        if (Number(content) > paramsJSON.max) {
                            return TVI.validators.defaultInvalidMessage;
                        }
                    }
                    // Check if we need to invoke the MIN rule
                    else
                        if (paramsJSON.min !== undefined) {
                        // If content is lower than MIN then return invalid message
                        if (Number(content) < paramsJSON.min) {
                            return TVI.validators.defaultInvalidMessage;
                        }
                    }
                    // Check if we need to invoke the EQUALS rule
                    else
                        if (paramsJSON.equals !== undefined) {
                        // If content does not equal EQUALS return invalid message
                        if (Number(content) != paramsJSON.equals) {
                            return TVI.validators.defaultInvalidMessage;
                        }
                    }
                    // Check if we need to invoke the BETWEEN rule
                    else
                        if (paramsJSON.between !== undefined) {
                        // Get the minimum from the BETWEEN parameter
                        var min = paramsJSON.between.substring(0, paramsJSON.between.indexOf("-"));

                        // Get the maximum from the BETWEEN parameter
                        var max = paramsJSON.between.substring(paramsJSON.between.indexOf("-") + 1);

                        // If the content length is not between the minimum and maximum then return invalid message
                        if (!((Number(content) >= min) && (Number(content) <= max))) {
                            return TVI.validators.defaultInvalidMessage;
                        }
                    }

                    // If we can't find any correct paramaters to check then return error code
                    else {
                        return TVI.validators.defaultMissingParamsMessage;
                    }
                }

                // If none of the validation type have failed then return success
                return TVI.validators.defaultValidMessage;
            }
            else {
                return TVI.validators.defaultInvalidMessage;
            }
        }
    },


    /**
    * is NOT(public)
    * is NOT validator, checks the content to see if it matches a value or one of an array of values.
    * @param {string}   content	The content of the field being validated
    * @param {object}   params		Validation parameters
    * {"value": "hello", "values": ["one", "two", "three"], "caseSensitive" : "true"}
    */
    isNot: function(content, params) {

        if (content === undefined || params === undefined) {
            return TVI.validators.defaultMissingParamsMessage;
        }
        else if (content === "") {
            return TVI.validators.defaultValidMessage;
        }
        else {
            // Parse JSON Data
            var paramsJSON = JSON.parse(params);

            //Check for casesensitive and deal with it if not!
            if (!(paramsJSON.caseSensitive !== undefined && paramsJSON.caseSensitive == "true")) {
                paramsJSON = TVI.validators.JSONRemoveCase(paramsJSON);
                content = content.toLowerCase();
            }

            // Check if we need to invoke the VALUE rule
            if (paramsJSON.value !== undefined) {

                // If content doesn't match the value then return valid message
                if (content !== paramsJSON.value) {
                    return TVI.validators.defaultValidMessage;
                }
            }

            // Check if we need to invoke the VALUES rule
            else if (paramsJSON.values !== undefined) {

                // Loop through values parameters and return false if a match is found
                for (var i in paramsJSON.values) {
                    if (content == paramsJSON.values[i]) {
                        return TVI.validators.defaultInvalidMessage;
                    }
                }
                // If not returned false after looping is finished, return true
                return TVI.validators.defaultValidMessage;
            }
            else {
                return TVI.validators.defaultMissingParamsMessage;
            }

            // If none of the validation type have succeeded then return invalid
            return TVI.validators.defaultInvalidMessage;
        }
    },


    /**
    * exclude (public)
    * Validator to check contents of string for no match
    * @param {string}   content		The content of the field being validated
    * @param {object}   params			Validation parameters 
    * {"value": "hello", "values": ["one", "two", "three"], "caseSensitive" : "true"}
    */
    exclude: function(content, params) {
        if (content === undefined || params === undefined) {
            return TVI.validators.defaultMissingParamsMessage;

        }
        else if (content === "") {
            return TVI.validators.defaultValidMessage;
        }
        else {
            // Parse JSON Data
            var paramsJSON = JSON.parse(params);

            //Check for casesensitive and deal with it if not!
            if (!(paramsJSON.caseSensitive !== undefined && paramsJSON.caseSensitive == "true")) {
                paramsJSON = TVI.validators.JSONRemoveCase(paramsJSON);
                content = content.toLowerCase();
            }
            // Check for value parameter and run rule
            if (paramsJSON.value !== undefined) {
                // If content doesn't contain a match then return invalid message
                if (paramsJSON.value.match(content) === null) {
                    return TVI.validators.defaultValidMessage;
                }
            }
            // Check for values parameter
            else if (paramsJSON.values !== undefined) {
                // Variable to keep track of if we've found a match
                var returned = false;
                // Loop through values parameters and return true if a match is found
                for (var i in paramsJSON.values) {
                    if (paramsJSON.values[i].match(content)) {
                        return TVI.validators.defaultInvalidMessage;
                    }
                }
                // If not returned true after looping is finished, return false
                return TVI.validators.defaultValidMessage;
            }
            else {
                return TVI.validators.defaultMissingParamsMessage;
            }

            // If none of the validation type have failed then return success
            return TVI.validators.defaultInvalidMessage;
        }
    },



    /**
    * email (public)
    * Validator to check an email address
    * @param {string}   content		The content of the field being validated
    */
    email: function(content) {
        ///<summary>
        ///Validator to check for an email address
        ///</summary>

        //Check for email
        if (content === "" || content === undefined) {
            return TVI.validators.defaultValidMessage;
        }
        else {
            content = content.toLowerCase();
            var filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
            if (filter.test(content)) {
                return TVI.validators.defaultValidMessage;
            }
        }
        return TVI.validators.defaultInvalidMessage;
    },


    /**
    * checked (public)
    * Validator to check whether an item is checked
    * @param {string}   content		The content of the field being validated
    */
    checked: function(content) {
        if (content === "true") {
            return TVI.validators.defaultValidMessage;
        }
        else {
            return TVI.validators.defaultInvalidMessage;
        }
    },


    /**
    * matches (public)
    * Validator to check specified field value against content, ignoreempty allows for the specified field to be empty
    * @param {string}   content		The content of the field being validated
    * @param {object}   params			Validation parameters - 
    *  {"fieldID" : "textBox_confirmPassword", "ignoreEmpty" : true ,"caseSensitive" : "true"}
    */
    matches: function(content, params) {

		// Check that content and parameters have been supplied
        if (content === undefined || params === undefined) {
			
            return TVI.validators.defaultMissingParamsMessage;
        }
		// Check that the content is not empty
        else if (content === "") {
			
            return TVI.validators.defaultValidMessage;
        }
        else {
			
            // Parse JSON Data
            var paramsJSON = JSON.parse(params);
			
            //Check for casesensitive and deal with it if not!
            if (!(paramsJSON.caseSensitive !== undefined && paramsJSON.caseSensitive == "false")) {
                paramsJSON = TVI.validators.JSONRemoveCase(paramsJSON);
                content = content.toLowerCase();
            }
			
            // Check for fieldID param and ignoreEmpty param
            if (paramsJSON.fieldID !== undefined && paramsJSON.ignoreEmpty !== undefined && paramsJSON.ignoreEmpty == "true") {
                //compare content to fieldID document element
                if ((content == document.getElementById(paramsJSON.fieldID).value) || (document.getElementById(paramsJSON.fieldID).value === "")) {
                    return TVI.validators.defaultValidMessage;
                }
                else {
                    return TVI.validators.defaultInvalidMessage;
                }
            }
            else
                if (paramsJSON.fieldID !== undefined) {
                if (content == document.getElementById(paramsJSON.fieldID).value) {
                    return TVI.validators.defaultValidMessage;
                }
                else {
                    return TVI.validators.defaultInvalidMessage;
                }
            }
            else {
                return TVI.validators.defaultInvalidMessage;
            }
        }

    },


    /**
    * date (public)
    * Validator to check a date
    * @param {string}   content		The content of the field being validated
    * @param {object}   params			Validation parameters - 
    * {"from": "27/09/2008", "to": "27/09/2008", "between": "20/05/2008 - 30/05/2008"}
    */
    date: function(content, params) {

        //Function to check whether a date is actually valid
        function isValidDate(year, month, day) {
            try {
				// Create a date
                var dt = new Date(year, month-1, day);
				
				// Check that the date isn't empty
                if (isNaN(dt)) {
                    return false;
                }
				
				// Create variables from the date
                var iYear2 = dt.getFullYear();
                var iMonth2 = dt.getMonth() +1;
                var iDate2 = dt.getDate();
				
				// CHeck to see if the original values are the same as the valid date
                if (iYear2 != year || iMonth2 != month || iDate2 != day) {
                    return false;
                }
                else {
                    return true;
                }
            }
            catch (e) {
                return false;
            }
            return true;
        }
        //If its blank return valid
        if (content === "") {
            return TVI.validators.defaultValidMessage;
        }
        else {
            //Check if its a valid date at all
			
			TVI.logComment(content.substring(6, 10) + '-' + content.substring(3, 5) + '-' + content.substring(0, 2));
			
            if (isValidDate(content.substring(6, 10), content.substring(3, 5), content.substring(0, 2)) && content.length <= 10) {
				
				TVI.logComment('valid date');
				
                //Check for params
                if (params !== "") {
                    //And parse them into an object
                    var paramsJSON = JSON.parse(params);

                    //Setup some vars to hold the param/content dates
                    var contentDate = new Date();
                    var fromDate = new Date();
                    var toDate = new Date();

                    //Grab the date from content
                    contentDate.setFullYear(content.substring(6, 10), content.substring(3, 5), content.substring(0, 2));

					TVI.logComment(contentDate);

                    //Check for from param
                    if (paramsJSON.from !== undefined) {
                        fromDate.setFullYear(paramsJSON.from.substring(6, 10), paramsJSON.from.substring(3, 5), paramsJSON.from.substring(0, 2));
                        if (contentDate < fromDate) {
                            return TVI.validators.defaultInvalidMessage;
                        }
                    }
                    //Check for to param
                    if (paramsJSON.to !== undefined) {
                        toDate.setFullYear(paramsJSON.to.substring(6, 10), paramsJSON.to.substring(3, 5), paramsJSON.to.substring(0, 2));
                        if (contentDate > toDate) {
                            return TVI.validators.defaultInvalidMessage;
                        }
                    }
                    //Check for between param
                    if (paramsJSON.between !== undefined) {
                        fromDate.setFullYear(paramsJSON.between.substring(6, 10), paramsJSON.between.substring(3, 5), paramsJSON.between.substring(0, 2));
                        toDate.setFullYear(paramsJSON.between.substring(19, 23), paramsJSON.between.substring(16, 18), paramsJSON.between.substring(13, 15));
                        if (!((contentDate <= toDate) && (contentDate >= fromDate))) {
                            return TVI.validators.defaultInvalidMessage;
                        }
                    }
                    //If we haven't failed we must have passed!
                    return TVI.validators.defaultValidMessage;

                }
                //If there were no params we've already checked whether the date was valid so output true
                return TVI.validators.defaultValidMessage;
            }
            //If the date was invalid
            return TVI.validators.defaultInvalidMessage;

        }
    },


    /**
    * startWith (public)
    * Validator to check the start of a string
    * @param {string}   content		The content of the field being validated
    * @param {object}   params			Validation parameters - 
    * {"value":"http://", "values": ["http://", "https://", "www."], "caseSensitive" : "true"
    */
    startsWith: function(content, params) {

        if (content === undefined || params === undefined) {
            return TVI.validators.defaultMissingParamsMessage;
        }
        else if (content === "") {
            return TVI.validators.defaultValidMessage;
        }
        else {
            // Parse JSON Data
            var paramsJSON = JSON.parse(params);

            //Check for casesensitive and deal with it if not!
            if (!(paramsJSON.caseSensitive !== undefined && paramsJSON.caseSensitive == "true")) {
                paramsJSON = TVI.validators.JSONRemoveCase(paramsJSON);
                content = content.toLowerCase();
            }

            // Check if we need to invoke the VALUE rule
            if (paramsJSON.value !== undefined) {

                // If content doesn't match the value then return invalid message
                if (content.indexOf(paramsJSON.value) === -1) {
                    return TVI.validators.defaultInvalidMessage;
                }
            }

            // Check if we need to invoke the VALUES rule
            else if (paramsJSON.values !== undefined) {

                // Loop through values parameters and return true if a match is found
                for (var i in paramsJSON.values) {
                    if (content.indexOf(paramsJSON.values[i]) !== -1) {
                        return TVI.validators.defaultValidMessage;
                    }
                }
                // If not returned true after looping is finished, return false
                return TVI.validators.defaultInvalidMessage;
            }
            else {
                return TVI.validators.defaultMissingParamsMessage;
            }

            // If none of the validation type have failed then return success
            return TVI.validators.defaultValidMessage;
        }
    },



    /**
    * endsWith (public)
    * Validator to check the end of a string
    * @param {string}   content		The content of the field being validated
    * @param {object}   params			Validation parameters - "value":"http://", "values": ["http://", "https://", "www."], "caseSensitive" : "true"
    */
    endsWith: function(content, params) {

        if (content === undefined || params === undefined) {
            return TVI.validators.defaultMissingParamsMessage;
        }
        else if (content === "") {
            return TVI.validators.defaultValidMessage;
        }
        else {
            // Parse JSON Data
            var paramsJSON = JSON.parse(params);

            //Check for casesensitive and deal with it if not!
            if (!(paramsJSON.caseSensitive !== undefined && paramsJSON.caseSensitive == "true")) {
                paramsJSON = TVI.validators.JSONRemoveCase(paramsJSON);
                content = content.toLowerCase();
            }

            // Check if we need to invoke the VALUE rule
            if (paramsJSON.value !== undefined) {

                // If content doesn't match the value then return invalid message

                if (!(paramsJSON.value.indexOf(content) == (paramsJSON.value.length - content.length))) {

                    return TVI.validators.defaultInvalidMessage;
                }
            }

            // Check if we need to invoke the VALUES rule
            else if (paramsJSON.values !== undefined) {

                // Loop through values parameters and return true if a match is found
                for (var i in paramsJSON.values) {
                    if (paramsJSON.values[i].indexOf(content) == (paramsJSON.values[i].length - content.length)) {
                        return TVI.validators.defaultValidMessage;
                    }
                }
                // If not returned true after looping is finished, return false
                return TVI.validators.defaultInvalidMessage;
            }
            else {
                return TVI.validators.defaultMissingParamsMessage;
            }

            // If none of the validation type have failed then return success
            return TVI.validators.defaultValidMessage;
        }
    },

    /**
    * ajax (public)
    * Validator to check content against any external webmethod validator
    * @param {string}   content		The content of the field being validated
    * @param {object}   params			Validation parameters - "url" : "Handlers/Users.aspx/checkPassword" + any params you would like to pass to the handler
    */
    ajax: function(content, params, successfunction) {

        // Parse JSON Data
        var paramsJSON = JSON.parse(params);

        //Check for empty content and return true if found
        if (content === "") {
            return TVI.validators.defaultValidMessage;
        }
        else {

            // Add content to params object
            paramsJSON.content = content;
            // Check for run the post and pass it the params object
            if (paramsJSON.url != "") {
                var sendString = JSON.stringify(paramsJSON);
                var returnData;
                $.ajax({
                    type: "POST",
                    url: "Handlers/Users.aspx/checkPassword",
                    data: sendString,
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    async: false,
                    success: function(data) {
                        returnData = JSON.parse(data.d);
                    }
                });

                while (returnData == undefined) {
                    ;
                }
                return returnData;
            }
        }
    }




    // Validation rules end here


});
function topnavInit() {

    //create a toolTip manager
    WEB.purpleToolTipManager = new TVI.ToolTipManager({
        tipDefaults: {
            position: 'top',
            relativeXpos: 'middle',
            relativeYpos: 'top',
            width: 200
        },
        skinDefaults: {

            usesPng: true,
            contentTemplate: '<div class="closeWrapper"><a class="close" href="#"></a></div><div class="contentContainer">${content}</div>',

            toolTipClass: 'dropdownTooltip',
            topLeftClass: 'topLeft',
            topMiddleClass: 'topMiddle',
            topRightClass: 'topRight',
            middleLeftClass: 'middleLeft',
            middleClass: 'middle',
            middleRightClass: 'middleRight',
            bottomLeftClass: 'bottomLeft',
            bottomMiddleClass: 'bottomMiddle',
            bottomRightClass: 'bottomRight',

            outerLeftWidth: 7,
            outerRightWidth: 6,
            outerTopHeight: 9,
            outerBottomHeight: 11,

            pointerTopWidth: 19,
            pointerTopHeight: 19,
            pointerTopPointX: 10,
            pointerTopPointY: 13,
            pointerTopXOffset: 0,
            pointerTopYOffset: -7,
            pointerTopClass: 'pointerTop',

            pointerRightWidth: 14,
            pointerRightHeight: 22,
            pointerRightPointX: 2,
            pointerRightPointY: 8,
            pointerRightXOffset: 0,
            pointerRightYOffset: 0,
            pointerRightClass: 'pointerRight',

            pointerBottomWidth: 15,
            pointerBottomHeight: 13,
            pointerBottomPointX: 8,
            pointerBottomPointY: 1,
            pointerBottomXOffset: 0,
            pointerBottomYOffset: 0,
            pointerBottomClass: 'pointerBottom',

            pointerLeftWidth: 14,
            pointerLeftHeight: 22,
            pointerLeftPointX: 13,
            pointerLeftPointY: 8,
            pointerLeftXOffset: 0,
            pointerLeftYOffset: 0,
            pointerLeftClass: 'pointerLeft'
        }
    });

    //setup quote form
    topnavSetupQuote();

    //setup demo form
    topnavSetupDemo();

    //setup contact form
    topnavSetupContact();

}

function topnavSetupQuote() {

    //reset form
    topnavQuoteReset();

    //setup tooltips
    topnavQuoteToolTips();

    //add click event
    $('#btn_quote').click(function() {

        topnavQuote();

    });

}

function topnavQuoteToolTips() {

    //add tooltips to website, budget and description inputs
    $('#textBox_QuoteCurrent').focus(function() {

        WEB.purpleToolTipManager.hideAllTips();

        var myTooltip = WEB.purpleToolTipManager.addTip({
            id: 'quoteTipWebsite',
            relativeTo: 'textBox_QuoteCurrent',
            content: 'Please enter the url of your current website.'
        });

        //force z-index
        $('#quoteTipWebsite').css('z-index', "9000000000");

    });

    $('#textBox_QuoteBudget').focus(function() {

        WEB.purpleToolTipManager.hideAllTips();

        var myTooltip = WEB.purpleToolTipManager.addTip({
            id: 'quoteTipBudget',
            relativeTo: 'textBox_QuoteBudget',
            content: 'Please enter a rough budget for this project.'
        });

        //force z-index
        $('#quoteTipBudget').css('z-index', "9000000000");

    });

    $('#textArea_QuoteBrief').focus(function() {

        WEB.purpleToolTipManager.hideAllTips();

        var myTooltip = WEB.purpleToolTipManager.addTip({
            id: 'quoteTipDescription',
            width: 250,
            relativeTo: 'textArea_QuoteBrief',
            content: 'Please enter a brief description of your requirements.'
        });

        //force z-index
        $('#quoteTipDescription').css('z-index', "9000000000");

    });
    
    //hide tooltips on blur
    $('#textBox_QuoteCurrent').blur(function() {
        WEB.purpleToolTipManager.hideAllTips();
    });

    $('#textBox_QuoteBudget').blur(function() {
        WEB.purpleToolTipManager.hideAllTips();
    });

    $('#textArea_QuoteBrief').blur(function() {
        WEB.purpleToolTipManager.hideAllTips();
    });

}

//send quote
function topnavQuote() {

    //google analytics
    TVI.logDir(pageTracker);
    pageTracker._trackPageview('/formQuoteSubmit');

    //validate data
    if (validQuote()) {

        WEB.purpleToolTipManager.hideAllTips();
    
        //hide form
        $('#form_quote').hide();
        $('#form_quoteDesc').hide();
        $('#form_quoteLoading').show();

        //get data
        var name = TVI.util.encodeQuotes($('#textBox_QuoteName').val());
        var company = TVI.util.encodeQuotes($('#textBox_QuoteCompanyName').val());
        var email = TVI.util.encodeQuotes($('#textBox_QuoteEmail').val());
        var phone = TVI.util.encodeQuotes($('#textBox_QuotePhone').val());
        var website = TVI.util.encodeQuotes($('#textBox_QuoteCurrent').val());
        var budget = TVI.util.encodeQuotes($('#textBox_QuoteBudget').val());
        var description = TVI.util.encodeQuotes($('#textArea_QuoteBrief').val());

        //build post data
        //eg. {"data": {"name": "Mark"}}
        var data = '{"data": {' +
            '"name": "' + name + '",' +
            '"company": "' + company + '",' +
            '"email": "' + email + '",' +
            '"phone": "' + phone + '",' +
            '"website": "' + website + '",' +
            '"budget": "' + budget + '",' +
            '"description": "' + description + '"' +
            '}}';

        //call handler
        TVI.ajax({
            url: '/handlers/topnav.aspx/quote',
            data: data,
            success: function() {
                
                $('#form_quoteLoading').hide();
                $('#form_quoteSuccess').show();

                //google analytics
                pageTracker._trackPageview('/formQuoteComplete');

            },
            failure: function() {

                $('#form_quoteLoading').hide();
                $('#form_quoteFailed').show();

            },
            error: function() {

                $('#form_quoteLoading').hide();
                $('#form_quoteFailed').show();

            },
            errorCode: '090001',
            errorMessage: 'Ajax error during HttpProxy Load.'
        });

    }

}

function validQuote() {

    //validate name, email, telephone and description
    if ($('#textBox_QuoteName').val() == "") {
        topnavErrorTip('btn_quote', 'Please enter your name.');
        return false;
    }

    if ($('#textBox_QuoteEmail').val() == "" && $('#textBox_QuotePhone').val() == "") {
        topnavErrorTip('btn_quote', 'Please enter your email address or contact telephone number.');
        return false;
    }

    if ($('#textBox_QuoteEmail').val() != "") {

        var result = TVI.validators.email($('#textBox_QuoteEmail').val());

        if (!result.success) {
            topnavErrorTip('btn_quote', 'Please enter a valid email address.');
            return false;
        }
                
    }

    if ($('#textArea_QuoteBrief').val() == "") {
        topnavErrorTip('btn_quote', 'Please enter a brief description of your project.');
        return false;
    }

    return true;

}

function topnavQuoteReset() {

    //clear form
    $('#textBox_QuoteName').val('');
    $('#textBox_QuoteCompanyName').val('');
    $('#textBox_QuoteEmail').val('');
    $('#textBox_QuotePhone').val('');
    $('#textBox_QuoteCurrent').val('');
    $('#textBox_QuoteBudget').val('');
    $('#textArea_QuoteBrief').val('');

    //show form and hide thankyou, loading and failed divs
    $('#form_quote').show();
    $('#form_quoteDesc').show();
    $('#form_quoteLoading').hide();
    $('#form_quoteSuccess').hide();
    $('#form_quoteFailed').hide();

}




function topnavSetupDemo() {

    //request a demo form
    topnavDemoReset();

    topnavDemoToolTips();

    $('#btn_requestDemo').click(function() {

        topnavDemo();

    });

}

function topnavDemoToolTips() {

    //add tooltips to description
    $('#textArea_DemoBrief').focus(function() {

        WEB.purpleToolTipManager.hideAllTips();

        var myTooltip = WEB.purpleToolTipManager.addTip({
            id: 'demoTipDescription',
            width: 350,
            relativeTo: 'textArea_DemoBrief',
            content: 'Please enter a brief description of your project.'
        });

        //force z-index
        $('#demoTipDescription').css('z-index', "9000000000");

    });

    //hide tooltips on blur
    $('#textArea_DemoBrief').blur(function() {
        WEB.purpleToolTipManager.hideAllTips();
    });

}

//request a demo
function topnavDemo() {

    //google analytics
    pageTracker._trackPageview('/formDemoSubmit');

    //validate data
    if (validDemo()) {

        WEB.purpleToolTipManager.hideAllTips();

        //hide form
        $('#form_demo').hide();
        $('#form_demoLoading').show();

        //get data
        var name = TVI.util.encodeQuotes($('#textBox_DemoName').val());
        var phone = TVI.util.encodeQuotes($('#textBox_DemoPhone').val());
        var free = TVI.util.encodeQuotes($('#textBox_DemoFree').val());
        var description = TVI.util.encodeQuotes($('#textArea_DemoBrief').val());

        //build post data
        //eg. {"data": {"name": "Mark"}}
        var data = '{"data": {' +
            '"name": "' + name + '",' +
            '"phone": "' + phone + '",' +
            '"free": "' + free + '",' +
            '"description": "' + description + '"' +
            '}}';

        //call handler
        TVI.ajax({
            url: '/handlers/topnav.aspx/demo',
            data: data,
            success: function() {

                $('#form_demoLoading').hide();
                $('#form_demoSuccess').show();

                //google analytics
                pageTracker._trackPageview('/formDemoComplete');

            },
            failure: function() {

                $('#form_demoLoading').hide();
                $('#form_demoFailed').show();

            },
            error: function() {

                $('#form_demoLoading').hide();
                $('#form_demoFailed').show();

            },
            errorCode: '090001',
            errorMessage: 'Ajax error during HttpProxy Load.'
        });

    }

}

function validDemo() {

    //validate name, email, telephone and description
    if ($('#textBox_DemoName').val() == "") {
        topnavErrorTip('btn_requestDemo', 'Please enter your name.');
        return false;
    }

    if ($('#textBox_DemoPhone').val() == "") {
        topnavErrorTip('btn_requestDemo', 'Please enter your contact telephone number.');
        return false;
    }

    return true;

}

function topnavDemoReset() {

    //clear form
    $('#textBox_DemoName').val('');
    $('#textBox_DemoPhone').val('');
    $('#textBox_DemoFree').val('');
    $('#textArea_DemoBrief').val('');

    $('#form_demo').show();
    $('#form_demoLoading').hide();
    $('#form_demoSuccess').hide();
    $('#form_demoFailed').hide();

}




function topnavSetupContact() {

    //contact form
    topnavContactReset();

    $('#btn_contact').click(function() {

        topnavContact();

    });

}


//contact form
function topnavContact() {

    //google analytics
    pageTracker._trackPageview('/formContactSubmit');

    //validate data
    if (validContact()) {

        WEB.purpleToolTipManager.hideAllTips();

        //hide form
        $('#TVI-form_contactUsForm').hide();
        $('#form_contactLoading').show();

        //get data
        var name = TVI.util.encodeQuotes($('#textBox_ContactName').val());
        var phone = TVI.util.encodeQuotes($('#textBox_ContactPhone').val());
        var email = TVI.util.encodeQuotes($('#textBox_ContactEmail').val());
        var message = TVI.util.encodeQuotes($('#textBox_ContactMessage').val());

        //build post data
        //eg. {"data": {"name": "Mark"}}
        var data = '{"data": {' +
            '"name": "' + name + '",' +
            '"phone": "' + phone + '",' +
            '"email": "' + email + '",' +
            '"message": "' + message + '"' +
            '}}';

        //call handler
        TVI.ajax({
            url: '/handlers/topnav.aspx/contact',
            data: data,
            success: function() {

                $('#form_contactLoading').hide();
                $('#form_contactSuccess').show();

                //google analytics
                pageTracker._trackPageview('/formContactComplete');

            },
            failure: function() {

                $('#form_contactLoading').hide();
                $('#form_contactFailed').show();

            },
            error: function() {

                $('#form_contactLoading').hide();
                $('#form_contactFailed').show();

            },
            errorCode: '090001',
            errorMessage: 'Ajax error during HttpProxy Load.'
        });

    }

}

function validContact() {

    //validate name, email, telephone and message
    if ($('#textBox_ContactName').val() == "") {
        topnavErrorTip('btn_contact', 'Please enter your name.');
        return false;
    }

    if ($('#textBox_ContactPhone').val() == "" && $('#textBox_ContactEmail').val() == "") {
        topnavErrorTip('btn_contact', 'Please enter your email address or contact telephone number.');
        return false;
    }

    if ($('#textBox_ContactEmail').val() != "") {

        var result = TVI.validators.email($('#textBox_ContactEmail').val());

        if (!result.success) {
            topnavErrorTip('btn_contact', 'Please enter a valid email address.');
            return false;
        }

    }

    if ($('#textBox_ContactMessage').val() == "") {
        topnavErrorTip('btn_contact', 'Please enter your message.');
        return false;
    }

    return true;

}

function topnavContactReset() {

    //clear form
    $('#textBox_ContactName').val('');
    $('#textBox_ContactPhone').val('');
    $('#textBox_ContactEmail').val('');
    $('#textBox_ContactMessage').val('');

    $('#TVI-form_contactUsForm').show();
    $('#form_contactLoading').hide();
    $('#form_contactSuccess').hide();
    $('#form_contactFailed').hide();

}




function topnavErrorTip(e, m) {

    //e: element
    //m: message

    //remove tooltip and create new one
    WEB.purpleToolTipManager.removeTip({ id: 'topnavErrorTip' });

    var myTooltip = WEB.purpleToolTipManager.addTip({
        id: 'topnavErrorTip',
        width: 250,
        relativeTo: e,
        content: m
    });

    //force z-index
    $('#topnavErrorTip').css('z-index', "9000000000");

}