/*
 * jQuery JavaScript Library v1.3.2
 * http://jquery.com/
 *
 * Copyright (c) 2009 John Resig
 * Dual licensed under the MIT and GPL licenses.
 * http://docs.jquery.com/License
 *
 * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
 * Revision: 6246
 */
(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F<J;F++){var G=M[F];if(G.selected){K=o(G).val();if(H){return K}L.push(K)}}return L}return(E.value||"").replace(/\r/g,"")}return g}if(typeof K==="number"){K+=""}return this.each(function(){if(this.nodeType!=1){return}if(o.isArray(K)&&/radio|checkbox/.test(this.type)){this.checked=(o.inArray(this.value,K)>=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G<E;G++){L.call(K(this[G],H),this.length>1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H<I;H++){if((G=arguments[H])!=null){for(var F in G){var K=J[F],L=G[F];if(J===L){continue}if(E&&L&&typeof L==="object"&&!L.nodeType){J[F]=o.extend(E,K||(L.length!=null?[]:{}),L)}else{if(L!==g){J[F]=L}}}}}return J};var b=/z-?index|font-?weight|opacity|zoom|line-?height/i,q=document.defaultView||{},s=Object.prototype.toString;o.extend({noConflict:function(E){l.$=p;if(E){l.jQuery=y}return o},isFunction:function(E){return s.call(E)==="[object Function]"},isArray:function(E){return s.call(E)==="[object Array]"},isXMLDoc:function(E){return E.nodeType===9&&E.documentElement.nodeName!=="HTML"||!!E.ownerDocument&&o.isXMLDoc(E.ownerDocument)},globalEval:function(G){if(G&&/\S/.test(G)){var F=document.getElementsByTagName("head")[0]||document.documentElement,E=document.createElement("script");E.type="text/javascript";if(o.support.scriptEval){E.appendChild(document.createTextNode(G))}else{E.text=G}F.insertBefore(E,F.firstChild);F.removeChild(E)}},nodeName:function(F,E){return F.nodeName&&F.nodeName.toUpperCase()==E.toUpperCase()},each:function(G,K,F){var E,H=0,I=G.length;if(F){if(I===g){for(E in G){if(K.apply(G[E],F)===false){break}}}else{for(;H<I;){if(K.apply(G[H++],F)===false){break}}}}else{if(I===g){for(E in G){if(K.call(G[E],E,G[E])===false){break}}}else{for(var J=G[0];H<I&&K.call(J,H,J)!==false;J=G[++H]){}}}return G},prop:function(H,I,G,F,E){if(o.isFunction(I)){I=I.call(H,F)}return typeof I==="number"&&G=="curCSS"&&!b.test(E)?I+"px":I},className:{add:function(E,F){o.each((F||"").split(/\s+/),function(G,H){if(E.nodeType==1&&!o.className.has(E.className,H)){E.className+=(E.className?" ":"")+H}})},remove:function(E,F){if(E.nodeType==1){E.className=F!==g?o.grep(E.className.split(/\s+/),function(G){return !o.className.has(F,G)}).join(" "):""}},has:function(F,E){return F&&o.inArray(E,(F.className||F).toString().split(/\s+/))>-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+"></"+T+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!O.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!O.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!O.indexOf("<td")||!O.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!O.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||!o.support.htmlSerialize&&[1,"div<div>","</div>"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/<tbody/i.test(S),N=!O.indexOf("<table")&&!R?L.firstChild&&L.firstChild.childNodes:Q[1]=="<table>"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E<F;E++){if(H[E]===G){return E}}return -1},merge:function(H,E){var F=0,G,I=H.length;if(!o.support.getAll){while((G=E[F++])!=null){if(G.nodeType!=8){H[I++]=G}}}else{while((G=E[F++])!=null){H[I++]=G}}return H},unique:function(K){var F=[],E={};try{for(var G=0,H=K.length;G<H;G++){var J=o.data(K[G]);if(!E[J]){E[J]=true;F.push(K[G])}}}catch(I){F=K}return F},grep:function(F,J,E){var G=[];for(var H=0,I=F.length;H<I;H++){if(!E!=!J(F[H],H)){G.push(F[H])}}return G},map:function(E,J){var F=[];for(var G=0,H=E.length;G<H;G++){var I=J(E[G],G);if(I!=null){F[F.length]=I}}return F.concat.apply([],F)}});var C=navigator.userAgent.toLowerCase();o.browser={version:(C.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[0,"0"])[1],safari:/webkit/.test(C),opera:/opera/.test(C),msie:/msie/.test(C)&&!/opera/.test(C),mozilla:/mozilla/.test(C)&&!/(compatible|webkit)/.test(C)};o.each({parent:function(E){return E.parentNode},parents:function(E){return o.dir(E,"parentNode")},next:function(E){return o.nth(E,2,"nextSibling")},prev:function(E){return o.nth(E,2,"previousSibling")},nextAll:function(E){return o.dir(E,"nextSibling")},prevAll:function(E){return o.dir(E,"previousSibling")},siblings:function(E){return o.sibling(E.parentNode.firstChild,E)},children:function(E){return o.sibling(E.firstChild)},contents:function(E){return o.nodeName(E,"iframe")?E.contentDocument||E.contentWindow.document:o.makeArray(E.childNodes)}},function(E,F){o.fn[E]=function(G){var H=o.map(this,F);if(G&&typeof G=="string"){H=o.multiFilter(G,H)}return this.pushStack(o.unique(H),E,G)}});o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(E,F){o.fn[E]=function(G){var J=[],L=o(G);for(var K=0,H=L.length;K<H;K++){var I=(K>0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}});
/*
 * Sizzle CSS Selector Engine - v0.9.3
 *  Copyright 2009, The Dojo Foundation
 *  Released under the MIT, BSD, and GPL Licenses.
 *  More information: http://sizzlejs.com/
 */
(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa<ab.length;aa++){if(ab[aa]===ab[aa-1]){ab.splice(aa--,1)}}}}}return ab};F.matches=function(T,U){return F(T,null,null,U)};F.find=function(aa,T,ab){var Z,X;if(!aa){return[]}for(var W=0,V=I.order.length;W<V;W++){var Y=I.order[W],X;if((X=I.match[Y].exec(aa))){var U=RegExp.leftContext;if(U.substr(U.length-1)!=="\\"){X[1]=(X[1]||"").replace(/\\/g,"");Z=I.find[Y](X,T,ab);if(Z!=null){aa=aa.replace(I.match[Y],"");break}}}}if(!Z){Z=T.getElementsByTagName("*")}return{set:Z,expr:aa}};F.filter=function(ad,ac,ag,W){var V=ad,ai=[],aa=ac,Y,T,Z=ac&&ac[0]&&Q(ac[0]);while(ad&&ac.length){for(var ab in I.filter){if((Y=I.match[ab].exec(ad))!=null){var U=I.filter[ab],ah,af;T=false;if(aa==ai){ai=[]}if(I.preFilter[ab]){Y=I.preFilter[ab](Y,aa,ag,ai,W,Z);if(!Y){T=ah=true}else{if(Y===true){continue}}}if(Y){for(var X=0;(af=aa[X])!=null;X++){if(af){ah=U(af,Y,X,aa);var ae=W^!!ah;if(ag&&ah!=null){if(ae){T=true}else{aa[X]=false}}else{if(ae){ai.push(af);T=true}}}}}if(ah!==g){if(!ag){aa=ai}ad=ad.replace(I.match[ab],"");if(!T){return[]}break}}}if(ad==V){if(T==null){throw"Syntax error, unrecognized expression: "+ad}else{break}}V=ad}return aa};var I=F.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(T){return T.getAttribute("href")}},relative:{"+":function(aa,T,Z){var X=typeof T==="string",ab=X&&!/\W/.test(T),Y=X&&!ab;if(ab&&!Z){T=T.toUpperCase()}for(var W=0,V=aa.length,U;W<V;W++){if((U=aa[W])){while((U=U.previousSibling)&&U.nodeType!==1){}aa[W]=Y||U&&U.nodeName===T?U||false:U===T}}if(Y){F.filter(T,aa,true)}},">":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){var W=Y.parentNode;Z[V]=W.nodeName===U?W:false}}}else{for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){Z[V]=X?Y.parentNode:Y.parentNode===U}}if(X){F.filter(U,Z,true)}}},"":function(W,U,Y){var V=L++,T=S;if(!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("parentNode",U,V,W,X,Y)},"~":function(W,U,Y){var V=L++,T=S;if(typeof U==="string"&&!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("previousSibling",U,V,W,X,Y)}},find:{ID:function(U,V,W){if(typeof V.getElementById!=="undefined"&&!W){var T=V.getElementById(U[1]);return T?[T]:[]}},NAME:function(V,Y,Z){if(typeof Y.getElementsByName!=="undefined"){var U=[],X=Y.getElementsByName(V[1]);for(var W=0,T=X.length;W<T;W++){if(X[W].getAttribute("name")===V[1]){U.push(X[W])}}return U.length===0?null:U}},TAG:function(T,U){return U.getElementsByTagName(T[1])}},preFilter:{CLASS:function(W,U,V,T,Z,aa){W=" "+W[1].replace(/\\/g,"")+" ";if(aa){return W}for(var X=0,Y;(Y=U[X])!=null;X++){if(Y){if(Z^(Y.className&&(" "+Y.className+" ").indexOf(W)>=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return U<T[3]-0},gt:function(V,U,T){return U>T[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W<T;W++){if(Y[W]===Z){return false}}return true}}}},CHILD:function(T,W){var Z=W[1],U=T;switch(Z){case"only":case"first":while(U=U.previousSibling){if(U.nodeType===1){return false}}if(Z=="first"){return true}U=T;case"last":while(U=U.nextSibling){if(U.nodeType===1){return false}}return true;case"nth":var V=W[2],ac=W[3];if(V==1&&ac==0){return true}var Y=W[0],ab=T.parentNode;if(ab&&(ab.sizcache!==Y||!T.nodeIndex)){var X=0;for(U=ab.firstChild;U;U=U.nextSibling){if(U.nodeType===1){U.nodeIndex=++X}}ab.sizcache=Y}var aa=T.nodeIndex-ac;if(V==0){return aa==0}else{return(aa%V==0&&aa/V>=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V<T;V++){U.push(X[V])}}else{for(var V=0;X[V];V++){U.push(X[V])}}}return U}}var G;if(document.documentElement.compareDocumentPosition){G=function(U,T){var V=U.compareDocumentPosition(T)&4?-1:U===T?0:1;if(V===0){hasDuplicate=true}return V}}else{if("sourceIndex" in document.documentElement){G=function(U,T){var V=U.sourceIndex-T.sourceIndex;if(V===0){hasDuplicate=true}return V}}else{if(document.createRange){G=function(W,U){var V=W.ownerDocument.createRange(),T=U.ownerDocument.createRange();V.selectNode(W);V.collapse(true);T.selectNode(U);T.collapse(true);var X=V.compareBoundaryPoints(Range.START_TO_END,T);if(X===0){hasDuplicate=true}return X}}}}(function(){var U=document.createElement("form"),V="script"+(new Date).getTime();U.innerHTML="<input name='"+V+"'/>";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="<a href='#'></a>";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="<p class='TEST'></p>";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="<div class='test e'></div><div class='test'></div>";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1&&!ac){T.sizcache=Y;T.sizset=W}if(T.nodeName===Z){X=T;break}T=T[U]}ad[W]=X}}}function S(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1){if(!ac){T.sizcache=Y;T.sizset=W}if(typeof Z!=="string"){if(T===Z){X=true;break}}else{if(F.filter(Z,[T]).length>0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z<U;Z++){F(T,V[Z],W)}return F.filter(X,W)};o.find=F;o.filter=F.filter;o.expr=F.selectors;o.expr[":"]=o.expr.filters;F.selectors.filters.hidden=function(T){return T.offsetWidth===0||T.offsetHeight===0};F.selectors.filters.visible=function(T){return T.offsetWidth>0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},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 toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F<E.length){o.event.proxy(G,E[F++])}return this.click(o.event.proxy(G,function(H){this.lastToggle=(this.lastToggle||0)%F;H.preventDefault();return E[this.lastToggle++].apply(this,arguments)||false}))},hover:function(E,F){return this.mouseenter(E).mouseleave(F)},ready:function(E){B();if(o.isReady){E.call(document,o)}else{o.readyList.push(E)}return this},live:function(G,F){var E=o.event.proxy(F);E.guid+=this.selector+G;o(document).bind(i(G,this.selector),this.selector,E);return this},die:function(F,E){o(document).unbind(i(F,this.selector),E?{guid:E.guid+this.selector+F}:null);return this}});function c(H){var E=RegExp("(^|\\.)"+H.type+"(\\.|$)"),G=true,F=[];o.each(o.data(this,"events").live||[],function(I,J){if(E.test(J.type)){var K=o(H.target).closest(J.data)[0];if(K){F.push({elem:K,fn:J})}}});F.sort(function(J,I){return o.data(J.elem,"closest")-o.data(I.elem,"closest")});o.each(F,function(){if(this.fn.call(this.elem,H,this.fn.data)===false){return(G=false)}});return G}function i(F,E){return["live",F,E.replace(/\./g,"`").replace(/ /g,"|")].join(".")}o.extend({isReady:false,readyList:[],ready:function(){if(!o.isReady){o.isReady=true;if(o.readyList){o.each(o.readyList,function(){this.call(document,o)});o.readyList=null}o(document).triggerHandler("ready")}}});var x=false;function B(){if(x){return}x=true;if(document.addEventListener){document.addEventListener("DOMContentLoaded",function(){document.removeEventListener("DOMContentLoaded",arguments.callee,false);o.ready()},false)}else{if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);o.ready()}});if(document.documentElement.doScroll&&l==l.top){(function(){if(o.isReady){return}try{document.documentElement.doScroll("left")}catch(E){setTimeout(arguments.callee,0);return}o.ready()})()}}}o.event.add(l,"load",o.ready)}o.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error").split(","),function(F,E){o.fn[E]=function(G){return G?this.bind(E,G):this.trigger(E)}});o(l).bind("unload",function(){for(var E in o.cache){if(E!=1&&o.cache[E].handle){o.event.remove(o.cache[E].handle.elem)}}});(function(){o.support={};var F=document.documentElement,G=document.createElement("script"),K=document.createElement("div"),J="script"+(new Date).getTime();K.style.display="none";K.innerHTML='   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';var H=K.getElementsByTagName("*"),E=K.getElementsByTagName("a")[0];if(!H||!H.length||!E){return}o.support={leadingWhitespace:K.firstChild.nodeType==3,tbody:!K.getElementsByTagName("tbody").length,objectAll:!!K.getElementsByTagName("object")[0].getElementsByTagName("*").length,htmlSerialize:!!K.getElementsByTagName("link").length,style:/red/.test(E.getAttribute("style")),hrefNormalized:E.getAttribute("href")==="/a",opacity:E.style.opacity==="0.5",cssFloat:!!E.style.cssFloat,scriptEval:false,noCloneEvent:true,boxModel:null};G.type="text/javascript";try{G.appendChild(document.createTextNode("window."+J+"=1;"))}catch(I){}F.insertBefore(G,F.firstChild);if(l[J]){o.support.scriptEval=true;delete l[J]}F.removeChild(G);if(K.attachEvent&&K.fireEvent){K.attachEvent("onclick",function(){o.support.noCloneEvent=false;K.detachEvent("onclick",arguments.callee)});K.cloneNode(true).fireEvent("onclick")}o(function(){var L=document.createElement("div");L.style.width=L.style.paddingLeft="1px";document.body.appendChild(L);o.boxModel=o.support.boxModel=L.offsetWidth===2;document.body.removeChild(L).style.display="none"})})();var w=o.support.cssFloat?"cssFloat":"styleFloat";o.props={"for":"htmlFor","class":"className","float":w,cssFloat:w,styleFloat:w,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",tabindex:"tabIndex"};o.fn.extend({_load:o.fn.load,load:function(G,J,K){if(typeof G!=="string"){return this._load(G)}var I=G.indexOf(" ");if(I>=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("<div/>").append(M.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},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(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H<F;H++){var E=o.data(this[H],"olddisplay");this[H].style.display=E||"";if(o.css(this[H],"display")==="none"){var G=this[H].tagName,K;if(m[G]){K=m[G]}else{var I=o("<"+G+" />").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H<F;H++){this[H].style.display=o.data(this[H],"olddisplay")||""}return this}},hide:function(H,I){if(H){return this.animate(t("hide",3),H,I)}else{for(var G=0,F=this.length;G<F;G++){var E=o.data(this[G],"olddisplay");if(!E&&E!=="none"){o.data(this[G],"olddisplay",o.css(this[G],"display"))}}for(var G=0,F=this.length;G<F;G++){this[G].style.display="none"}return this}},_toggle:o.fn.toggle,toggle:function(G,F){var E=typeof G==="boolean";return o.isFunction(G)&&o.isFunction(F)?this._toggle.apply(this,arguments):G==null||E?this.each(function(){var H=E?G:o(this).is(":hidden");o(this)[H?"show":"hide"]()}):this.animate(t("toggle",3),G,F)},fadeTo:function(E,G,F){return this.animate({opacity:G},E,F)},animate:function(I,F,H,G){var E=o.speed(F,H,G);return this[E.queue===false?"each":"queue"](function(){var K=o.extend({},E),M,L=this.nodeType==1&&o(this).is(":hidden"),J=this;for(M in I){if(I[M]=="hide"&&L||I[M]=="show"&&!L){return K.complete.call(this)}if((M=="height"||M=="width")&&this.style){K.display=o.css(this,"display");K.overflow=this.style.overflow}}if(K.overflow!=null){this.style.overflow="hidden"}K.curAnim=o.extend({},I);o.each(I,function(O,S){var R=new o.fx(J,K,O);if(/toggle|show|hide/.test(S)){R[S=="toggle"?L?"show":"hide":S](I)}else{var Q=S.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),T=R.cur(true)||0;if(Q){var N=parseFloat(Q[2]),P=Q[3]||"px";if(P!="px"){J.style[O]=(N||1)+P;T=((N||1)/R.cur(true))*T;J.style[O]=T+P}if(Q[1]){N=((Q[1]=="-="?-1:1)*N)+T}R.custom(T,N,P)}else{R.custom(T,S,"")}}});return true})},stop:function(F,E){var G=o.timers;if(F){this.queue([])}this.each(function(){for(var H=G.length-1;H>=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J<K.length;J++){if(!K[J]()){K.splice(J--,1)}}if(!K.length){clearInterval(n);n=g}},13)}},show:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.show=true;this.custom(this.prop=="width"||this.prop=="height"?1:0,this.cur());o(this.elem).show()},hide:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(H){var G=e();if(H||G>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})();/*
 * jQuery Autocomplete plugin 1.1
 *
 * Copyright (c) 2009 Jörn Zaefferer
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.autocomplete.js 15 2009-08-22 10:30:27Z joern.zaefferer $
 */

;(function($) {
	
$.fn.extend({
	autocomplete: function(urlOrData, options) {
		var isUrl = typeof urlOrData == "string";
		options = $.extend({}, $.Autocompleter.defaults, {
			url: isUrl ? urlOrData : null,
			data: isUrl ? null : urlOrData,
			delay: isUrl ? $.Autocompleter.defaults.delay : 10,
			max: options && !options.scroll ? 10 : 150
		}, options);
		
		// if highlight is set to false, replace it with a do-nothing function
		options.highlight = options.highlight || function(value) { return value; };
		
		// if the formatMatch option is not specified, then use formatItem for backwards compatibility
		options.formatMatch = options.formatMatch || options.formatItem;
		
		return this.each(function() {
			new $.Autocompleter(this, options);
		});
	},
	result: function(handler) {
		return this.bind("result", handler);
	},
	search: function(handler) {
		return this.trigger("search", [handler]);
	},
	flushCache: function() {
		return this.trigger("flushCache");
	},
	setOptions: function(options){
		return this.trigger("setOptions", [options]);
	},
	unautocomplete: function() {
		return this.trigger("unautocomplete");
	}
});

$.Autocompleter = function(input, options) {

	var KEY = {
		UP: 38,
		DOWN: 40,
		DEL: 46,
		TAB: 9,
		RETURN: 13,
		ESC: 27,
		COMMA: 188,
		PAGEUP: 33,
		PAGEDOWN: 34,
		BACKSPACE: 8
	};

	// Create $ object for input element
	var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass);

	var timeout;
	var previousValue = "";
	var cache = $.Autocompleter.Cache(options);
	var hasFocus = 0;
	var lastKeyPressCode;
	var config = {
		mouseDownOnSelect: false
	};
	var select = $.Autocompleter.Select(options, input, selectCurrent, config);
	
	var blockSubmit;
	
	// prevent form submit in opera when selecting with return key
	$.browser.opera && $(input.form).bind("submit.autocomplete", function() {
		if (blockSubmit) {
			blockSubmit = false;
			return false;
		}
	});
	
	// only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all
	$input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) {
		// a keypress means the input has focus
		// avoids issue where input had focus before the autocomplete was applied
		hasFocus = 1;
		// track last key pressed
		lastKeyPressCode = event.keyCode;
		switch(event.keyCode) {
		
			case KEY.UP:
				event.preventDefault();
				if ( select.visible() ) {
					select.prev();
				} else {
					onChange(0, true);
				}
				break;
				
			case KEY.DOWN:
				event.preventDefault();
				if ( select.visible() ) {
					select.next();
				} else {
					onChange(0, true);
				}
				break;
				
			case KEY.PAGEUP:
				event.preventDefault();
				if ( select.visible() ) {
					select.pageUp();
				} else {
					onChange(0, true);
				}
				break;
				
			case KEY.PAGEDOWN:
				event.preventDefault();
				if ( select.visible() ) {
					select.pageDown();
				} else {
					onChange(0, true);
				}
				break;
			
			// matches also semicolon
			case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA:
			case KEY.TAB:
			case KEY.RETURN:
				if( selectCurrent() ) {
					// stop default to prevent a form submit, Opera needs special handling
					event.preventDefault();
					blockSubmit = true;
					return false;
				}
				break;
				
			case KEY.ESC:
				select.hide();
				break;
				
			default:
				clearTimeout(timeout);
				timeout = setTimeout(onChange, options.delay);
				break;
		}
	}).focus(function(){
		// track whether the field has focus, we shouldn't process any
		// results if the field no longer has focus
		hasFocus++;
	}).blur(function() {
		hasFocus = 0;
		if (!config.mouseDownOnSelect) {
			hideResults();
		}
	}).click(function() {
		// show select when clicking in a focused field
		if ( hasFocus++ > 1 && !select.visible() ) {
			onChange(0, true);
		}
	}).bind("search", function() {
		// TODO why not just specifying both arguments?
		var fn = (arguments.length > 1) ? arguments[1] : null;
		function findValueCallback(q, data) {
			var result;
			if( data && data.length ) {
				for (var i=0; i < data.length; i++) {
					if( data[i].result.toLowerCase() == q.toLowerCase() ) {
						result = data[i];
						break;
					}
				}
			}
			if( typeof fn == "function" ) fn(result);
			else $input.trigger("result", result && [result.data, result.value]);
		}
		$.each(trimWords($input.val()), function(i, value) {
			request(value, findValueCallback, findValueCallback);
		});
	}).bind("flushCache", function() {
		cache.flush();
	}).bind("setOptions", function() {
		$.extend(options, arguments[1]);
		// if we've updated the data, repopulate
		if ( "data" in arguments[1] )
			cache.populate();
	}).bind("unautocomplete", function() {
		select.unbind();
		$input.unbind();
		$(input.form).unbind(".autocomplete");
	});
	
	
	function selectCurrent() {
		var selected = select.selected();
		if( !selected )
			return false;
		
		var v = selected.result;
		previousValue = v;
		
		if ( options.multiple ) {
			var words = trimWords($input.val());
			if ( words.length > 1 ) {
				var seperator = options.multipleSeparator.length;
				var cursorAt = $(input).selection().start;
				var wordAt, progress = 0;
				$.each(words, function(i, word) {
					progress += word.length;
					if (cursorAt <= progress) {
						wordAt = i;
						return false;
					}
					progress += seperator;
				});
				words[wordAt] = v;
				// TODO this should set the cursor to the right position, but it gets overriden somewhere
				//$.Autocompleter.Selection(input, progress + seperator, progress + seperator);
				v = words.join( options.multipleSeparator );
			}
			v += options.multipleSeparator;
		}
		
		$input.val(v);
		hideResultsNow();
		$input.trigger("result", [selected.data, selected.value]);
		return true;
	}
	
	function onChange(crap, skipPrevCheck) {
		if( lastKeyPressCode == KEY.DEL ) {
			select.hide();
			return;
		}
		
		var currentValue = $input.val();
		
		if ( !skipPrevCheck && currentValue == previousValue )
			return;
		
		previousValue = currentValue;
		
		currentValue = lastWord(currentValue);
		if ( currentValue.length >= options.minChars) {
			$input.addClass(options.loadingClass);
			if (!options.matchCase)
				currentValue = currentValue.toLowerCase();
			request(currentValue, receiveData, hideResultsNow);
		} else {
			stopLoading();
			select.hide();
		}
	};
	
	function trimWords(value) {
		if (!value)
			return [""];
		if (!options.multiple)
			return [$.trim(value)];
		return $.map(value.split(options.multipleSeparator), function(word) {
			return $.trim(value).length ? $.trim(word) : null;
		});
	}
	
	function lastWord(value) {
		if ( !options.multiple )
			return value;
		var words = trimWords(value);
		if (words.length == 1) 
			return words[0];
		var cursorAt = $(input).selection().start;
		if (cursorAt == value.length) {
			words = trimWords(value)
		} else {
			words = trimWords(value.replace(value.substring(cursorAt), ""));
		}
		return words[words.length - 1];
	}
	
	// fills in the input box w/the first match (assumed to be the best match)
	// q: the term entered
	// sValue: the first matching result
	function autoFill(q, sValue){
		// autofill in the complete box w/the first match as long as the user hasn't entered in more data
		// if the last user key pressed was backspace, don't autofill
		if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) {
			// fill in the value (keep the case the user has typed)
			$input.val($input.val() + sValue.substring(lastWord(previousValue).length));
			// select the portion of the value not typed by the user (so the next character will erase)
			$(input).selection(previousValue.length, previousValue.length + sValue.length);
		}
	};

	function hideResults() {
		clearTimeout(timeout);
		timeout = setTimeout(hideResultsNow, 200);
	};

	function hideResultsNow() {
		var wasVisible = select.visible();
		select.hide();
		clearTimeout(timeout);
		stopLoading();
		if (options.mustMatch) {
			// call search and run callback
			$input.search(
				function (result){
					// if no value found, clear the input box
					if( !result ) {
						if (options.multiple) {
							var words = trimWords($input.val()).slice(0, -1);
							$input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") );
						}
						else {
							$input.val( "" );
							$input.trigger("result", null);
						}
					}
				}
			);
		}
	};

	function receiveData(q, data) {
		if ( data && data.length && hasFocus ) {
			stopLoading();
			select.display(data, q);
			autoFill(q, data[0].value);
			select.show();
		} else {
			hideResultsNow();
		}
	};

	function request(term, success, failure) {
		if (!options.matchCase)
			term = term.toLowerCase();
		var data = cache.load(term);
		// recieve the cached data
		if (data && data.length) {
			success(term, data);
		// if an AJAX url has been supplied, try loading the data now
		} else if( (typeof options.url == "string") && (options.url.length > 0) ){
			
			var extraParams = {
				timestamp: +new Date()
			};
			$.each(options.extraParams, function(key, param) {
				extraParams[key] = typeof param == "function" ? param() : param;
			});
			
			$.ajax({
				// try to leverage ajaxQueue plugin to abort previous requests
				mode: "abort",
				// limit abortion to this input
				port: "autocomplete" + input.name,
				dataType: options.dataType,
				url: options.url,
				data: $.extend({
					q: lastWord(term),
					limit: options.max
				}, extraParams),
				success: function(data) {
					var parsed = options.parse && options.parse(data) || parse(data);
					cache.add(term, parsed);
					success(term, parsed);
				}
			});
		} else {
			// if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match
			select.emptyList();
			failure(term);
		}
	};
	
	function parse(data) {
		var parsed = [];
		var rows = data.split("\n");
		for (var i=0; i < rows.length; i++) {
			var row = $.trim(rows[i]);
			if (row) {
				row = row.split("|");
				parsed[parsed.length] = {
					data: row,
					value: row[0],
					result: options.formatResult && options.formatResult(row, row[0]) || row[0]
				};
			}
		}
		return parsed;
	};

	function stopLoading() {
		$input.removeClass(options.loadingClass);
	};

};

$.Autocompleter.defaults = {
	inputClass: "ac_input",
	resultsClass: "ac_results",
	loadingClass: "ac_loading",
	minChars: 1,
	delay: 400,
	matchCase: false,
	matchSubset: true,
	matchContains: false,
	cacheLength: 10,
	max: 100,
	mustMatch: false,
	extraParams: {},
	selectFirst: true,
	formatItem: function(row) { return row[0]; },
	formatMatch: null,
	autoFill: false,
	width: 0,
	multiple: false,
	multipleSeparator: ", ",
	highlight: function(value, term) {
		return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
	},
    scroll: true,
    scrollHeight: 180
};

$.Autocompleter.Cache = function(options) {

	var data = {};
	var length = 0;
	
	function matchSubset(s, sub) {
		if (!options.matchCase) 
			s = s.toLowerCase();
		var i = s.indexOf(sub);
		if (options.matchContains == "word"){
			i = s.toLowerCase().search("\\b" + sub.toLowerCase());
		}
		if (i == -1) return false;
		return i == 0 || options.matchContains;
	};
	
	function add(q, value) {
		if (length > options.cacheLength){
			flush();
		}
		if (!data[q]){ 
			length++;
		}
		data[q] = value;
	}
	
	function populate(){
		if( !options.data ) return false;
		// track the matches
		var stMatchSets = {},
			nullData = 0;

		// no url was specified, we need to adjust the cache length to make sure it fits the local data store
		if( !options.url ) options.cacheLength = 1;
		
		// track all options for minChars = 0
		stMatchSets[""] = [];
		
		// loop through the array and create a lookup structure
		for ( var i = 0, ol = options.data.length; i < ol; i++ ) {
			var rawValue = options.data[i];
			// if rawValue is a string, make an array otherwise just reference the array
			rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue;
			
			var value = options.formatMatch(rawValue, i+1, options.data.length);
			if ( value === false )
				continue;
				
			var firstChar = value.charAt(0).toLowerCase();
			// if no lookup array for this character exists, look it up now
			if( !stMatchSets[firstChar] ) 
				stMatchSets[firstChar] = [];

			// if the match is a string
			var row = {
				value: value,
				data: rawValue,
				result: options.formatResult && options.formatResult(rawValue) || value
			};
			
			// push the current match into the set list
			stMatchSets[firstChar].push(row);

			// keep track of minChars zero items
			if ( nullData++ < options.max ) {
				stMatchSets[""].push(row);
			}
		};

		// add the data items to the cache
		$.each(stMatchSets, function(i, value) {
			// increase the cache size
			options.cacheLength++;
			// add to the cache
			add(i, value);
		});
	}
	
	// populate any existing data
	setTimeout(populate, 25);
	
	function flush(){
		data = {};
		length = 0;
	}
	
	return {
		flush: flush,
		add: add,
		populate: populate,
		load: function(q) {
			if (!options.cacheLength || !length)
				return null;
			/* 
			 * if dealing w/local data and matchContains than we must make sure
			 * to loop through all the data collections looking for matches
			 */
			if( !options.url && options.matchContains ){
				// track all matches
				var csub = [];
				// loop through all the data grids for matches
				for( var k in data ){
					// don't search through the stMatchSets[""] (minChars: 0) cache
					// this prevents duplicates
					if( k.length > 0 ){
						var c = data[k];
						$.each(c, function(i, x) {
							// if we've got a match, add it to the array
							if (matchSubset(x.value, q)) {
								csub.push(x);
							}
						});
					}
				}				
				return csub;
			} else 
			// if the exact item exists, use it
			if (data[q]){
				return data[q];
			} else
			if (options.matchSubset) {
				for (var i = q.length - 1; i >= options.minChars; i--) {
					var c = data[q.substr(0, i)];
					if (c) {
						var csub = [];
						$.each(c, function(i, x) {
							if (matchSubset(x.value, q)) {
								csub[csub.length] = x;
							}
						});
						return csub;
					}
				}
			}
			return null;
		}
	};
};

$.Autocompleter.Select = function (options, input, select, config) {
	var CLASSES = {
		ACTIVE: "ac_over"
	};
	
	var listItems,
		active = -1,
		data,
		term = "",
		needsInit = true,
		element,
		list;
	
	// Create results
	function init() {
		if (!needsInit)
			return;
		element = $("<div/>")
		.hide()
		.addClass(options.resultsClass)
		.css("position", "absolute")
		.appendTo(document.body);
	
		list = $("<ul/>").appendTo(element).mouseover( function(event) {
			if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') {
	            active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event));
			    $(target(event)).addClass(CLASSES.ACTIVE);            
	        }
		}).click(function(event) {
			$(target(event)).addClass(CLASSES.ACTIVE);
			select();
			// TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus
			input.focus();
			return false;
		}).mousedown(function() {
			config.mouseDownOnSelect = true;
		}).mouseup(function() {
			config.mouseDownOnSelect = false;
		});
		
		if( options.width > 0 )
			element.css("width", options.width);
			
		needsInit = false;
	} 
	
	function target(event) {
		var element = event.target;
		while(element && element.tagName != "LI")
			element = element.parentNode;
		// more fun with IE, sometimes event.target is empty, just ignore it then
		if(!element)
			return [];
		return element;
	}

	function moveSelect(step) {
		listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE);
		movePosition(step);
        var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE);
        if(options.scroll) {
            var offset = 0;
            listItems.slice(0, active).each(function() {
				offset += this.offsetHeight;
			});
            if((offset + activeItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) {
                list.scrollTop(offset + activeItem[0].offsetHeight - list.innerHeight());
            } else if(offset < list.scrollTop()) {
                list.scrollTop(offset);
            }
        }
	};
	
	function movePosition(step) {
		active += step;
		if (active < 0) {
			active = listItems.size() - 1;
		} else if (active >= listItems.size()) {
			active = 0;
		}
	}
	
	function limitNumberOfItems(available) {
		return options.max && options.max < available
			? options.max
			: available;
	}
	
	function fillList() {
		list.empty();
		var max = limitNumberOfItems(data.length);
		for (var i=0; i < max; i++) {
			if (!data[i])
				continue;
			var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term);
			if ( formatted === false )
				continue;
			var li = $("<li/>").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0];
			$.data(li, "ac_data", data[i]);
		}
		listItems = list.find("li");
		if ( options.selectFirst ) {
			listItems.slice(0, 1).addClass(CLASSES.ACTIVE);
			active = 0;
		}
		// apply bgiframe if available
		if ( $.fn.bgiframe )
			list.bgiframe();
	}
	
	return {
		display: function(d, q) {
			init();
			data = d;
			term = q;
			fillList();
		},
		next: function() {
			moveSelect(1);
		},
		prev: function() {
			moveSelect(-1);
		},
		pageUp: function() {
			if (active != 0 && active - 8 < 0) {
				moveSelect( -active );
			} else {
				moveSelect(-8);
			}
		},
		pageDown: function() {
			if (active != listItems.size() - 1 && active + 8 > listItems.size()) {
				moveSelect( listItems.size() - 1 - active );
			} else {
				moveSelect(8);
			}
		},
		hide: function() {
			element && element.hide();
			listItems && listItems.removeClass(CLASSES.ACTIVE);
			active = -1;
		},
		visible : function() {
			return element && element.is(":visible");
		},
		current: function() {
			return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]);
		},
		show: function() {
			var offset = $(input).offset();
			element.css({
				width: typeof options.width == "string" || options.width > 0 ? options.width : $(input).width(),
				top: offset.top + input.offsetHeight,
				left: offset.left
			}).show();
            if(options.scroll) {
                list.scrollTop(0);
                list.css({
					maxHeight: options.scrollHeight,
					overflow: 'auto'
				});
				
                if($.browser.msie && typeof document.body.style.maxHeight === "undefined") {
					var listHeight = 0;
					listItems.each(function() {
						listHeight += this.offsetHeight;
					});
					var scrollbarsVisible = listHeight > options.scrollHeight;
                    list.css('height', scrollbarsVisible ? options.scrollHeight : listHeight );
					if (!scrollbarsVisible) {
						// IE doesn't recalculate width when scrollbar disappears
						listItems.width( list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")) );
					}
                }
                
            }
		},
		selected: function() {
			var selected = listItems && listItems.filter("." + CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE);
			return selected && selected.length && $.data(selected[0], "ac_data");
		},
		emptyList: function (){
			list && list.empty();
		},
		unbind: function() {
			element && element.remove();
		}
	};
};

$.fn.selection = function(start, end) {
	if (start !== undefined) {
		return this.each(function() {
			if( this.createTextRange ){
				var selRange = this.createTextRange();
				if (end === undefined || start == end) {
					selRange.move("character", start);
					selRange.select();
				} else {
					selRange.collapse(true);
					selRange.moveStart("character", start);
					selRange.moveEnd("character", end);
					selRange.select();
				}
			} else if( this.setSelectionRange ){
				this.setSelectionRange(start, end);
			} else if( this.selectionStart ){
				this.selectionStart = start;
				this.selectionEnd = end;
			}
		});
	}
	var field = this[0];
	if ( field.createTextRange ) {
		var range = document.selection.createRange(),
			orig = field.value,
			teststring = "<->",
			textLength = range.text.length;
		range.text = teststring;
		var caretAt = field.value.indexOf(teststring);
		field.value = orig;
		this.selection(caretAt, caretAt + textLength);
		return {
			start: caretAt,
			end: caretAt + textLength
		}
	} else if( field.selectionStart !== undefined ){
		return {
			start: field.selectionStart,
			end: field.selectionEnd
		}
	}
};

})(jQuery);/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-07-21 18:45:56 -0500 (Sat, 21 Jul 2007) $
 * $Rev: 2447 $
 *
 * Version 2.1.1
 */
(function($){$.fn.bgIframe=$.fn.bgiframe=function(s){if($.browser.msie&&/6.0/.test(navigator.userAgent)){s=$.extend({top:'auto',left:'auto',width:'auto',height:'auto',opacity:true,src:'javascript:false;'},s||{});var prop=function(n){return n&&n.constructor==Number?n+'px':n;},html='<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+'style="display:block;position:absolute;z-index:-1;'+(s.opacity!==false?'filter:Alpha(Opacity=\'0\');':'')+'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+'"/>';return this.each(function(){if($('> iframe.bgiframe',this).length==0)this.insertBefore(document.createElement(html),this.firstChild);});}return this;};})(jQuery);/*  
 *  Font UnStack 0.1
 * 
 *  Developed by Phil Oye
 *  Copyright (c) 2009 Phil Oye, http://philoye.com/
 *
 *  Licensed under the MIT license:
 *  http://www.opensource.org/licenses/mit-license.php
 *
 */

(function($) {
  $.fn.fontunstack = function(defaults, opts) {
     $.fontunstack.init(defaults,opts,this);
  };

  $.fontunstack = {

    options: {
      class_prefix: "set_in_"
    },

    init: function(stack, opts, elems){
       var elems = elems || "body";
       $.extend(this.options,opts);

       if( this.options.class_prefix == "") {
         this.options.class_prefix = "set_in_";
       }

       // If a css-style font-family declaration (string) passed in, convert to array
        if (typeof stack == "string") {
          stack = stack.match(/[^'",;\s][^'",;]*/g) || [];
        }
       this.analyzeStack(stack, elems);
     },

     analyzeStack: function(stack, elems) {
       var generics = ["monospace", "sans-serif", "serif", "cursive", "fantasy"];
       var baseline = generics[0];
       var num_fonts = stack.length;
       var last_resort = stack[num_fonts -1];

      // If author hasn't included a generic (tsk, tsk), let's add one
      if ($.inArray(last_resort, generics)) { 
        stack.push(baseline);
        num_fonts++;
      }
      
      // If the generic is the same as our baseline, let's use another.
      if (last_resort == baseline) {
        baseline = generics[1]; 
      };
    
      // At this point we're sure there is a generic fallback font, so we'll only iterate though the non-generics.
      for (var i=0; i<num_fonts -1; i++) {
        font = stack[i];
        if ($.fontunstack.testFont(font, baseline)) {

          // Remove any class that has our prefix to prevent doubles.
          var re = new RegExp("\\b" + this.options.class_prefix + ".*?\\b","g");
          $(elems).get(0).className = $(elems).get(0).className.replace(re, "");

          // This should convert UTF8 to lowercase ANSI, removing all punctuation/spaces, but regexp scares me.
          safe_font_name = encodeURIComponent( font.replace( /[\s\-.!~*'()"]/g, "").toLowerCase() );
          $(elems).addClass(this.options.class_prefix + safe_font_name);
          break; //We only want to find one installed font per stack.
        }
      }
    },

    testFont: function(requested_font, baseline_font) {
      var span = $('<span id="font_tester" style="font-family:' + baseline_font + '; font-size:144px;position:absolute;left:-10000px;top:-10000px;visibility:hidden;">mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmml</span>');
      $("body").prepend(span);

      var baseline_width = span.width();
      span.css("font-family", requested_font + "," + baseline_font );
      var requested_width = span.width();
      span.remove();

      // If the dimensions change, the font is installed
      return (requested_width != baseline_width);
    }

  };

})(jQuery);	/*
 * JTicker 0.5 Beta
 * By Jason Levine (http://www.jasons-toolbox.com)
 * A ticker plugin for the jquery library.
 */
$.JTickerObjArray = new Array();
$.fn.jticker = function(passedOptions, data) {
	var options = {
	    TickerID: "",
		delay: 1000,
		newwindow: false,
		url: "tickerdata.xml",
		transition: "slide",
		speed: "slow",
		contentcounter: -1,
		ArrayIndex: -1,
		dataXML: {
		},
		timerid: -1,
		setRSS: function(ArrayIndex) {
			$("#" + options.TickerID).hide();
			// Load Data
			$.get(options.url, function(data){
				options.dataXML = data;
				options.contentcounter = -1;
				options.FillSlide();
			}, "xml");
		},
		FillSlide: function() {
			var Item, TickerHTML, Title, URL, Desc;
			$("#" + options.TickerID).empty();
			options.contentcounter++;
			if (options.contentcounter == $("item", options.dataXML).length) {
				options.contentcounter = 0;
			}
			var maxSize = 131;
			Item = $("item", options.dataXML).get(options.contentcounter);
			Title = $("title", Item).text();
			source = $("source", Item).text();
			date = $("pubDate", Item).text();
			
			var dateObj = new Date(date);
			var month = ["January", "Febuary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
			var monthString = month[dateObj.getMonth()];
			date = monthString + " " + dateObj.getDate() + ", " + dateObj.getFullYear();
			
			var htmlString = "";
			if (source.length > 0 || date.length > 0) {
				htmlString += "<span class=\"delimiter\">|</span><cite>";
				if (source.length > 0) {
					htmlString += "From: " + source;
					if (date.length > 0) {
						htmlString += "<span class=\"delimiter\"> | </span>";
					}
				}
				if (date.length > 0) {
					htmlString += date;
				}
				htmlString += "</cite>";
			}
			var titleLength = Math.min(maxSize - htmlString.replace(/(<([^>]+)>)/ig, "").length, 80);
			if (Title.length > titleLength) {
				Title = Title.substring(0,Title.substr(0,titleLength - 4).lastIndexOf(" ")) + " ...";
			}
			URL = $("link", Item).text();
			TickerHTML = "<p><a href=\"" + URL + "\""
			if (options.newwindow) {
				TickerHTML += " class=\"openNewWindow\""
			}
			TickerHTML += ">" + Title + " <span class=\"chevron\">&#187;</span></a></p>";
			TickerHTML += htmlString;
			$("#" + options.TickerID).append(TickerHTML);
			options.EnterSlide();
			
		},
	    ExitSlide: function() {
			if (options.contentcounter > -1) {
				clearTimeout(options.timerid);
				switch (options.transition.toLowerCase()) {
					case "slide":
						$("#" + options.TickerID).slideUp(
							options.speed,
							options.ExitSlideStep2()
						);
						break;
					default:
						$("#" + options.TickerID).fadeOut(
							options.speed,
							options.ExitSlideStep2()
						);
						break;
				}
			} else {
				options.ExitSlideStep2(ArrayIndex);
			}
	    },
	    ExitSlideStep2: function() {
			var tempid;
			
			tempid = setTimeout("$.JTickerObjArray[" + options.ArrayIndex + "].FillSlide();", 500);
		},
	    EnterSlide: function() {
			var ArrayIndex = options.ArrayIndex;
			switch (options.transition.toLowerCase()) {
				case "slide":
					$("#" + options.TickerID).slideDown(
						options.speed,
						options.EnterSlideStep2()
					);
					break;
				default:
					$("#" + options.TickerID).fadeIn(
						options.speed,
						options.EnterSlideStep2()
					);
					break;
			}
	    },
	    EnterSlideStep2: function() {
			options.timerid = setTimeout("$.JTickerObjArray[" + options.ArrayIndex + "].ExitSlide();", options.delay);
		}
	};
	if (passedOptions) {
		$.extend(options, passedOptions);
	}
	
	return this.each(function(){
		options.TickerID = this.id;
		$.JTickerObjArray.push(options);
		options.ArrayIndex = $.JTickerObjArray.length - 1;
		$("#" + options.TickerID).hover(function() {
			clearTimeout(options.timerid);
		}, function() {
			options.timerid = setTimeout("$.JTickerObjArray[" + options.ArrayIndex + "].ExitSlide();", options.delay);
		});
		$.JTickerObjArray[options.ArrayIndex].setRSS(options.ArrayIndex);
	});
};/*
 * tools.expose 1.0.5 - Make HTML elements stand out
 * 
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/expose.html
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Launch  : June 2008
 * Date: ${date}
 * Revision: ${revision} 
 */
(function(b){b.tools=b.tools||{};b.tools.expose={version:"1.0.5",conf:{maskId:null,loadSpeed:"slow",closeSpeed:"fast",closeOnClick:true,closeOnEsc:true,zIndex:9998,opacity:0.8,color:"#456",api:false}};function a(){if(b.browser.msie){var f=b(document).height(),e=b(window).height();return[window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,f-e<20?e:f]}return[b(window).width(),b(document).height()]}function c(h,g){var e=this,j=b(this),d=null,f=false,i=0;b.each(g,function(k,l){if(b.isFunction(l)){j.bind(k,l)}});b(window).resize(function(){e.fit()});b.extend(this,{getMask:function(){return d},getExposed:function(){return h},getConf:function(){return g},isLoaded:function(){return f},load:function(n){if(f){return e}i=h.eq(0).css("zIndex");if(g.maskId){d=b("#"+g.maskId)}if(!d||!d.length){var l=a();d=b("<div/>").css({position:"absolute",top:0,left:0,width:l[0],height:l[1],display:"none",opacity:0,zIndex:g.zIndex});if(g.maskId){d.attr("id",g.maskId)}b("body").append(d);var k=d.css("backgroundColor");if(!k||k=="transparent"||k=="rgba(0, 0, 0, 0)"){d.css("backgroundColor",g.color)}if(g.closeOnEsc){b(document).bind("keydown.unexpose",function(o){if(o.keyCode==27){e.close()}})}if(g.closeOnClick){d.bind("click.unexpose",function(o){e.close(o)})}}n=n||b.Event();n.type="onBeforeLoad";j.trigger(n);if(n.isDefaultPrevented()){return e}b.each(h,function(){var o=b(this);if(!/relative|absolute|fixed/i.test(o.css("position"))){o.css("position","relative")}});h.css({zIndex:Math.max(g.zIndex+1,i=="auto"?0:i)});var m=d.height();if(!this.isLoaded()){d.css({opacity:0,display:"block"}).fadeTo(g.loadSpeed,g.opacity,function(){if(d.height()!=m){d.css("height",m)}n.type="onLoad";j.trigger(n)})}f=true;return e},close:function(k){if(!f){return e}k=k||b.Event();k.type="onBeforeClose";j.trigger(k);if(k.isDefaultPrevented()){return e}d.fadeOut(g.closeSpeed,function(){k.type="onClose";j.trigger(k);h.css({zIndex:b.browser.msie?i:null})});f=false;return e},fit:function(){if(d){var k=a();d.css({width:k[0],height:k[1]})}},bind:function(k,l){j.bind(k,l);return e},unbind:function(k){j.unbind(k);return e}});b.each("onBeforeLoad,onLoad,onBeforeClose,onClose".split(","),function(k,l){e[l]=function(m){return e.bind(l,m)}})}b.fn.expose=function(d){var e=this.eq(typeof d=="number"?d:0).data("expose");if(e){return e}if(typeof d=="string"){d={color:d}}var f=b.extend({},b.tools.expose.conf);d=b.extend(f,d);this.each(function(){e=new c(b(this),d);b(this).data("expose",e)});return d.api?e:this}})(jQuery);/*
 * tools.overlay 1.1.2 - Overlay HTML with eye candy.
 * 
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/overlay.html
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Launch  : March 2008
 * Date: ${date}
 * Revision: ${revision} 
 */
(function(c){c.tools=c.tools||{};c.tools.overlay={version:"1.1.2",addEffect:function(e,f,g){b[e]=[f,g]},conf:{top:"10%",left:"center",absolute:false,speed:"normal",closeSpeed:"fast",effect:"default",close:null,oneInstance:true,closeOnClick:true,closeOnEsc:true,api:false,expose:null,target:null}};var b={};c.tools.overlay.addEffect("default",function(e){this.getOverlay().fadeIn(this.getConf().speed,e)},function(e){this.getOverlay().fadeOut(this.getConf().closeSpeed,e)});var d=[];function a(g,k){var o=this,m=c(this),n=c(window),j,i,h,e=k.expose&&c.tools.expose.version;var f=k.target||g.attr("rel");i=f?c(f):null||g;if(!i.length){throw"Could not find Overlay: "+f}if(g&&g.index(i)==-1){g.click(function(p){o.load(p);return p.preventDefault()})}c.each(k,function(p,q){if(c.isFunction(q)){m.bind(p,q)}});c.extend(o,{load:function(u){if(o.isOpened()){return o}var r=b[k.effect];if(!r){throw'Overlay: cannot find effect : "'+k.effect+'"'}if(k.oneInstance){c.each(d,function(){this.close(u)})}u=u||c.Event();u.type="onBeforeLoad";m.trigger(u);if(u.isDefaultPrevented()){return o}h=true;if(e){i.expose().load(u)}var t=k.top;var s=k.left;var p=i.outerWidth({margin:true});var q=i.outerHeight({margin:true});if(typeof t=="string"){t=t=="center"?Math.max((n.height()-q)/2,0):parseInt(t,10)/100*n.height()}if(s=="center"){s=Math.max((n.width()-p)/2,0)}if(!k.absolute){t+=n.scrollTop();s+=n.scrollLeft()}i.css({top:t,left:s,position:"absolute"});u.type="onStart";m.trigger(u);r[0].call(o,function(){if(h){u.type="onLoad";m.trigger(u)}});if(k.closeOnClick){c(document).bind("click.overlay",function(w){if(!o.isOpened()){return}var v=c(w.target);if(v.parents(i).length>1){return}c.each(d,function(){this.close(w)})})}if(k.closeOnEsc){c(document).unbind("keydown.overlay").bind("keydown.overlay",function(v){if(v.keyCode==27){c.each(d,function(){this.close(v)})}})}return o},close:function(q){if(!o.isOpened()){return o}q=q||c.Event();q.type="onBeforeClose";m.trigger(q);if(q.isDefaultPrevented()){return}h=false;b[k.effect][1].call(o,function(){q.type="onClose";m.trigger(q)});var p=true;c.each(d,function(){if(this.isOpened()){p=false}});if(p){c(document).unbind("click.overlay").unbind("keydown.overlay")}return o},getContent:function(){return i},getOverlay:function(){return i},getTrigger:function(){return g},getClosers:function(){return j},isOpened:function(){return h},getConf:function(){return k},bind:function(p,q){m.bind(p,q);return o},unbind:function(p){m.unbind(p);return o}});c.each("onBeforeLoad,onStart,onLoad,onBeforeClose,onClose".split(","),function(p,q){o[q]=function(r){return o.bind(q,r)}});if(e){if(typeof k.expose=="string"){k.expose={color:k.expose}}c.extend(k.expose,{api:true,closeOnClick:k.closeOnClick,closeOnEsc:false});var l=i.expose(k.expose);l.onBeforeClose(function(p){o.close(p)});o.onClose(function(p){l.close(p)})}j=i.find(k.close||".close");if(!j.length&&!k.close){j=c('<div class="close"></div>');i.prepend(j)}j.click(function(p){o.close(p)})}c.fn.overlay=function(e){var f=this.eq(typeof e=="number"?e:0).data("overlay");if(f){return f}if(c.isFunction(e)){e={onBeforeLoad:e}}var g=c.extend({},c.tools.overlay.conf);e=c.extend(true,g,e);this.each(function(){f=new a(c(this),e);d.push(f);c(this).data("overlay",f)});return e.api?f:this}})(jQuery);/*
 * site_search JS
 * @author Engineering
 * @fileoverview
 * 
 * Javascript for site_search component
 *
 */

 
/*
 * site search code
 * @class siteSearch
 */ 
var strSearchMetaPath;
var aCategoryOpts = [];

function ResultItem()
{
  this.cat = null;
  this.docs = new Array();
  this.totalweight = 0;
  this.totalscore = 0.0;
  this.numfound = 0;
  this.calcMean = null;
  this.mean = function() {
    if (this.calcMean == null)
    {
      if (this.numfound > 0)
        this.calcMean = (this.totalscore/this.numfound).toFixed(1);
      else
        this.calcMean = 0;
    }
    return this.calcMean;
  }
  this.query = null;
  this.queryDone = false;
}

var siteSearch = function () {
  /*
   * local variables
   */     

  var cachedElements = {
    searchField: null,
    searchForm: null,
    searchSubmit: null,
    moreResults: null,
    resultsContainer: null,
    results: null,
    messageContainer: null
  };

  var messaging = {
    blankSearchTerm: 'Please enter a search term',
    invalidSearchTerm: 'Invalid, please try again.'
  }
    
  var constants = {
    closedClass: 'closed',
    openClass: 'open',
    inputDefaultText: 'Search',
    submitButtonSuffix_submit: '_submit',
    submitButtonSuffix_searchClose: '_searchClose',
    searchAction_search: 'search',
    searchAction_close: 'close'
  }

  var defaultInputValue;
  var messagingDisplayed = false;
  var strSolrSearchUrl;
  var strSolrSuggestUrl;
  var aCategoryDefs;
  var iNumResCats = 5;
  var mDialogProps;
  var aPrevTerms = new Array();
  var aPrevPages = new Array();
  var strUserOrga = "";
  var strUserState = "";
  var strUserPostalCode = "";
  var submitClicked = false;
  var searchAction = constants.searchAction_search;
  var maxCategoriesForDisplay = 6;
  var maxResultsPerCategory = 4;
  var iMaxNumToAvg = 6;
  var iNumQueriesToRun = 0;
  var blurbLength = 160;
  var strCategory = "";
  var strSubcategory = "";
  var strTitle = "";
  var strTitleWeight = "10.0";
  var strCategoryWeight = "10.0";
  var strSubcategoryWeight = "10.0";
  var strOrgaWeight = "7.0";
  var strStateWeight = "7.0";
  var strCmPath = "";
  var strCmTitle = "";
  var strPrefix = "";
  
  return {
    init: function (solrSearchUrl, solrSuggestUrl, searchMetaPath, categoryDefs, dialogProps, pagePath,
                  category, subcategory, title, prevPageCookie, blurbLengthFromProp, cmPath, cmTitle, prefix) {
      strSolrSearchUrl = solrSearchUrl;
      strSolrSuggestUrl = solrSuggestUrl;
      strSearchMetaPath = searchMetaPath;
      strCategory = category;
      strSubcategory = subcategory;
      strTitle = title;
      strCmPath = cmPath;
      strCmTitle = cmTitle;
      strPrefix = prefix;
      
      aCategoryDefs = categoryDefs;
      mDialogProps = dialogProps;
      blurbLength = blurbLengthFromProp;
      // Populate options for the dialog
      var iCat = 0;
      var catName;
      aCategoryOpts[iCat++] = { "text": "-Normal Search Ranking-", "value": "-Normal Search Ranking-", "qtip": "-Normal Search Ranking-"};
      for (catName in aCategoryDefs)
      {
        var cat = aCategoryDefs[catName];
        if ((cat.title != null) && (cat.title.length > 0))
          aCategoryOpts[iCat++] = { "text": cat.title, "value": cat.title, "qtip": cat.title};
      }

      aCategoryDefs["Programs"].query="";
      aCategoryDefs["Courses"].query="";

      siteSearch.cacheFormElements();
      (cachedElements.searchForm).attr('autocomplete','off');

      if (mDialogProps['currPageTitle'] != null)
        strTitleWeight = mDialogProps['currPageTitle'];
      if (mDialogProps['currPageCategory'] != null)
        strCategoryWeight = mDialogProps['currPageCategory'];
      if (mDialogProps['currPageSubcategory'] != null)
           strSubcategoryWeight = mDialogProps['currPageSubcategory'];
      if (mDialogProps['orgaBoost'] != null)
          strOrgaWeight = mDialogProps['orgaBoost'];
      if (mDialogProps['stateBoost'] != null)
          strStateWeight = mDialogProps['stateBoost'];
  
      // Get the user location from the backend -- DO NOT USE THE CACHED FORM...MAKE SURE THE '?' IS PRESENT!!!
      $.getJSON("/public/bin/servlet/altcloud/UserServlet.location.json?", {},
        function(resp) {
          if (resp) 
          {
            if (resp.orga)
              strUserOrga = resp.orga;
            if (resp.state)
              strUserState = resp.state;
            if (resp.postal_code)
              strUserPostalCode = resp.postal_code;
          }
        }
      );
      siteSearch.bindEvents();
      
      if (prevPageCookie != null)
        aPrevPages = prevPageCookie.split(",");
      
      siteSearch.addPrevPage(pagePath);
    },
    /*
     * adds events to various search form elements
     * 
     * What it does:
     *    bind 'focus' event to search field -- s failure class if currently applied and sets value of field to blank. bind 'blur' event to search field -- if 
     *    the search field doesn't contain a value, replace the default input text. bind 'keydown' event to search field -- if there is error messaging behind displayed,
     *    clear the field, remove failure class if currently applied and set messaging flag to false. bind 'mouseover/out' events to submit button -- if the submit button 
     *    src contains '_off', replace with '_on' and vice versa. bind 'submit' event to form -- catch the submit event and check to see if the search field has a valid 
     *    entry (ie, not blank, not the default text, not error messaging). If not, display error messaging. If so, perform the submit actions
     * 
     */         
    bindEvents: function () {
      (cachedElements.searchField).bind('focus', function () {
    siteSearch.updateSearchButton('panelState_closed'); 
    
      });
      (cachedElements.searchField).bind('blur', function () {

      if ((cachedElements.resultsContainer).css('display') === 'block') {   
      siteSearch.updateSearchButton('panelState_open'); 
      }
      else {
      siteSearch.updateSearchButton('panelState_closed'); 
      }     
      });
      (cachedElements.searchField).bind('keydown', function() {
        if (messagingDisplayed) {
          (cachedElements.messageContainer).hide();
          messagingDisplayed = false;
        } 
      }); 
    
      (cachedElements.searchSubmit).bind('click', function () {});
      
      (cachedElements.searchForm).submit (function (e) {
        e.preventDefault();
    
        if (searchAction === constants.searchAction_search) {
          if (messagingDisplayed) {
            (cachedElements.messageContainer).hide();
            messagingDisplayed = false;
          } 

          if (!(cachedElements.searchField).val() || (cachedElements.searchField).val() === constants.inputDefaultText || (cachedElements.searchField).val() === messaging.invalidSearchTerm) {
            siteSearch.displayMessaging(messaging.invalidSearchTerm, constants.failureClass);
          }
          else {
            if (mDialogProps['useWeightedSort']) 
              siteSearch.runQueryUpdated((cachedElements.searchField).val());
            else 
              siteSearch.runQuery((cachedElements.searchField).val());             
          }
          siteSearch.updateSearchButton('panelState_open');       
        }
        else {
          (cachedElements.resultsContainer).hide();
          (cachedElements.results).hide();
          (cachedElements.messageContainer).hide(); 
          (cachedElements.searchField).val(constants.inputDefaultText);
          siteSearch.updateSearchButton('panelState_closed');   
        }
      });     
      (cachedElements.moreResultsLink).bind('click',function (e) {
			var e = e || window.event;				
			e.preventDefault();	

			var strDimFilters = siteSearch.getDimAutoFilters((cachedElements.searchField).val());
			var strQuery = strDimFilters + "&q=" + (cachedElements.searchField).val();
			var strRequest = strPrefix + "/search.html?solr_q=" + encodeURIComponent(strQuery);     
			window.location.href = strRequest;
      });
      // Bind the JQuery Autocomplete control to the search field
      (cachedElements.searchField).autocomplete(strSolrSuggestUrl + "/?wt=json&json.wrf=?&jsoncallback=?", {
        dataType: "jsonp",
        cacheLength: 1,
        selectFirst: false,
        extraParams: {
          q: function () { return "topic:\"" + (cachedElements.searchField).val() + "\"" },
          rows: 10,
          indent: "on",
          sort:"topic_count desc"
        },
        mustMatch: false,
        minChars: 1,
        delay: 1,
        parse: function(data) {
          return $.map(data.response.docs, function(doc, idx) {
            return {
              data: doc.topic,
              value: doc.topic,
              result: doc.topic
            }
          });
        },
        formatItem: function(term) {
          return term;
        }
      }).result(function(e, term) {
      if (mDialogProps['useWeightedSort']) 
        siteSearch.runQueryUpdated(term);
      else 
        siteSearch.runQuery(term);
      });
      // Bind the enter up key to blur to clear the autocomplete list if someone presses enter...
      (cachedElements.searchField).keyup(function(e) {
        if (e.keyCode == 13)
        {
          (cachedElements.searchField).blur();
          siteSearch.updateSearchButton('panelState_open'); 
       }
      });
    },
    /*
     * store DOM elements in local variables
     * 
     * What it does:
     *    gather various form elements in local variables
     * 
     */       
    cacheFormElements: function () {
      cachedElements.searchField = $('input#siteSearchInput');
      cachedElements.searchSubmit = $('input#siteSearchSubmit');
      cachedElements.searchForm = $('div#siteSearch form');    
      cachedElements.moreResultsLink = $('a#search_more_results');
      cachedElements.resultsContainer = $('div#apts_results_frame');
      cachedElements.results = $('div#apts_results');
      cachedElements.messageContainer = $('div#apts_message');
    },
    closeSearch: function () {
      (cachedElements.resultsContainer).hide();
      (cachedElements.results).hide();
      (cachedElements.messageContainer).hide(); 
      (cachedElements.searchField).val(constants.inputDefaultText);
      siteSearch.updateSearchButton('panelState_closed');     
    },
    /*
     * displays error messaging for invalid search terms
     * 
     * What it does:
     *    add the passed class for messaging to search field element, set the search field to the passed message string and set messaging flag to true
     * 
     */         
    displayMessaging: function (messageString, messageStatus) {
      (cachedElements.searchField).addClass(messageStatus);
      (cachedElements.searchField).val(messageString);
      messagingDisplayed = true;            
    },
    /*
     * performs the query
     * 
     * What it does:
     *    calls the solr search and formats the results 
     * 
     */         
    runQuery: function (strSearchVal) {
      var strDimFilters = siteSearch.getDimAutoFilters(strSearchVal);
      var strQuery = strDimFilters + "&rows=200&q=" + strSearchVal;
      var strRequestString = strSolrSearchUrl + "/?wt=json&json.wrf=?&jsoncallback=?" + strQuery;

      // close subnav tabs when triggering search
      topNav.closeTabs();
      siteSearch.addPrevTerm(strSearchVal);
      $.getJSON(strRequestString, {},
        function(resp) {
        
          // We need to figure out what the top 5 categories are.
          var aCategories = new Array();
          var iLen = resp.response.docs.length;

          if (iLen == 0)
          {
            (cachedElements.resultsContainer).show();
            (cachedElements.results).hide();
            (cachedElements.messageContainer).show();
            siteSearch.updateSearchButton('panelState_closed'); 
            messagingDisplayed = true;
            // See if there are any suggested spellings

            if ((resp.spellcheck != null) && 
                (resp.spellcheck.suggestions != null) && 
                (resp.spellcheck.suggestions.length > 0) &&
                (resp.spellcheck.suggestions[1].suggestion != null) &&
                (resp.spellcheck.suggestions[1].suggestion.length > 0))
            {
              var strSuggestion = resp.spellcheck.suggestions[1].suggestion[0];
              $("#apts_suggestions").html("Did you mean: <a href=\"javascript:siteSearch.runSuggestionQuery('" + 
                        strSuggestion + "')\">" + strSuggestion + "</a>");
              $("#apts_suggestions").show();
            }
            else
            {
              $("#apts_suggestions").hide();
            }
          }
          else
          {
            $("#search_ico").attr("src","/etc/designs/common/images/ico_cancel.png");

            // This is yucky...need to figure out a more efficient way to do this.
            var mResCats = new Object();

            for (var idx = 0; idx < iLen; idx++)
            {
              var doc = resp.response.docs[idx];

              if (!mResCats[doc.category])
                mResCats[doc.category] = "true";
            }

            // Set the pinned categories in
            siteSearch.checkProperty(mDialogProps['left_top'], 0, aCategories, mResCats);
            siteSearch.checkProperty(mDialogProps['right_top'], 1, aCategories, mResCats);
            siteSearch.checkProperty(mDialogProps['left_middle'], 2, aCategories, mResCats);
            siteSearch.checkProperty(mDialogProps['right_middle'], 3, aCategories, mResCats);
            siteSearch.checkProperty(mDialogProps['bottom'], 4, aCategories, mResCats);
            var iCurrCat = 0;
            for (var idx = 0; idx < iLen; idx++)
            {
              var doc = resp.response.docs[idx];
              var itm = null;     
              // See if we have already added this one
              for (var iCat = 0; !itm && (iCat < aCategories.length); iCat++)
              {
                if (aCategories[iCat] && (aCategories[iCat].cat == doc.category))
                  itm = aCategories[iCat];
              }
              if (!itm)
              {
                while (aCategories[iCurrCat])
                  iCurrCat++;

                itm = new ResultItem();
                itm.docs[0] = doc;
                itm.cat = doc.category;
                aCategories[iCurrCat] = itm;
              }
              else
              {
                var catDef = aCategoryDefs[itm.cat];
                
                // Note: catDef will only be null if the result has a category that no
                //       longer exists in the category definitions.
                if (catDef != null)
                {
                  if (itm.docs.length < catDef.display_num_results)
                    itm.docs[itm.docs.length] = doc;
                }
              }
            }
            cachedElements.results.find(".searchResults .column").empty();
            (cachedElements.resultsContainer).show();
            // hack to lift results container up above form controls in IE6
            (cachedElements.resultsContainer).bgiframe();
            (cachedElements.results).show();
            (cachedElements.messageContainer).hide();
            siteSearch.updateSearchButton('panelState_open'); 
            var messagingDisplayed = false;     
            for (var iResCat = 0; iResCat < aCategories.length; iResCat++)
            {
              var itm = aCategories[iResCat];
              if (itm)
                siteSearch.addCategoryResults(iResCat, itm, strSearchVal);
            }

            for (var iHideCat = aCategories.length; iHideCat < iNumResCats; iHideCat++)
            {
              $("#apts_result_" + iHideCat).hide();
            }
          }
        }
      );
    },
    runQueryUpdated: function (strSearchVal) {
      var strDimFilters = siteSearch.getDimAutoFilters(strSearchVal);
      var strQuery = strDimFilters + "&rows=0&q=" + escape(strSearchVal);
      var strRequestString = strSolrSearchUrl + "/?wt=json&json.wrf=?&jsoncallback=?" + strQuery;

      // close subnav tabs when triggering search
      topNav.closeTabs();
      siteSearch.addPrevTerm(strSearchVal);
      $.getJSON(strRequestString, {},
        function(resp) {

          // We need to figure out what the top 5 categories are.
          var aCategories = new Array();
          var mCategories = new Array();
          var facet = resp.facet_counts;
          var iCatCount = facet.facet_fields.category.length;
          var iCat;
          var iTotalRes = 0;
          
          for (iCat = 0; iCat < iCatCount; iCat += 2)
          {
            var strCat = facet.facet_fields.category[iCat];
            var iFacetCount = facet.facet_fields.category[iCat + 1];
            var fFacetTotalScore = 0.0;
            
            iTotalRes += iFacetCount;
            
            if (iFacetCount > 0)
            {
            
              if ((facet.facet_total_scores != null) && (facet.facet_total_scores[strCat] != null))
                fFacetTotalScore = facet.facet_total_scores[strCat].toFixed(2);
              itm = new ResultItem();
              itm.cat = strCat;
              if (aCategoryDefs[strCat] != null)
                itm.query = aCategoryDefs[strCat].query;
              itm.totalscore = fFacetTotalScore;
              itm.numfound = iFacetCount;
              aCategories[aCategories.length] = itm;
              mCategories[strCat] = itm;
            }
          }
          aCategories.sort(function(a, b) {return b.mean() - a.mean()});

          if (iTotalRes == 0)
          {
            (cachedElements.resultsContainer).show();
            (cachedElements.results).hide();
            (cachedElements.messageContainer).show();
            siteSearch.updateSearchButton('panelState_closed');
            messagingDisplayed = true;
            // See if there are any suggested spellings
            if ((resp.spellcheck != null) &&
                (resp.spellcheck.suggestions != null) &&
                (resp.spellcheck.suggestions.length > 0) &&
                (resp.spellcheck.suggestions[1].suggestion != null) &&
                (resp.spellcheck.suggestions[1].suggestion.length > 0))
            {
              var strSuggestion = resp.spellcheck.suggestions[1].suggestion[0];
              $("#apts_suggestions").html("Did you mean: <a href=\"javascript:siteSearch.runSuggestionQuery('" +
                        strSuggestion + "')\">" + strSuggestion + "</a>");
              $("#apts_suggestions").show();
            }
            else
            {
              $("#apts_suggestions").hide();
            }
            if(typeof cmCreatePageviewTag == 'function')
              cmCreatePageviewTag("SEARCH: Unsucessful Search", "/home/search/", strSearchVal, iTotalRes);
          }
          else
          {
            $("#search_ico").attr("src","/etc/designs/common/images/ico_cancel.png");

            // Calculate the number of queries to run...
            iNumQueriesToRun = 1; // For the "null" cat query
            
            for (var iCat=0; iCat < aCategories.length; iCat++) {
              var cat = aCategories[iCat];
              if (cat.query != null)
                iNumQueriesToRun++;
            }

            siteSearch.runCatQuery(null, mCategories, aCategories, strSearchVal, 200);

            for (var iCat=0; iCat < aCategories.length; iCat++) {
              var cat = aCategories[iCat];

              // See if the categories have their own queries
              if (cat.query != null)
                siteSearch.runCatQuery(cat, mCategories, aCategories, strSearchVal, 4);
            }
            if(typeof cmCreatePageviewTag == 'function')
              cmCreatePageviewTag("SEARCH: Sucessful Search", "/home/search/", strSearchVal, iTotalRes);
          }
        }
      );
    },  
    /*
     * adds the current term to the list of previously searched terms.
     * 
     * What it does:
     *    maintains a list of 5 previously searched terms stored like a stack.
     * 
     */         
    addPrevTerm: function(strTerm)
    {
      var strPrevTerms;
      
      // It'd be nice to use Array.unshift for this but it sounds like it's unreliable on IE.
      // So...
      var aTemp = new Array();
      aTemp[0] = strTerm;
      
      strPrevTerms = strTerm;
      for (var i=0; (i < aPrevTerms.length) && (i < 4); i++)
      {
        strPrevTerms += ",";
        strPrevTerms += aPrevTerms[i];
        aTemp[aTemp.length] = aPrevTerms[i];
      }
      aPrevTerms = aTemp;

      var exdate = new Date();
      exdate.setDate(exdate.getDate() + 90);
      setCookie("prev_search_terms", strPrevTerms, exdate, "/");
    },
    /*
     * adds the current term to the list of previously searched terms.
     * 
     * What it does:
     *    maintains a list of 5 previously searched terms stored like a stack.
     * 
     */         
    addPrevPage: function(strPagePath)
    {
      if ((aPrevPages.length == 0) || (aPrevPages[0] != strPagePath))
      {
        var strPrevPages;

        // It'd be nice to use Array.unshift for this but it sounds like it's unreliable on IE.
        // So...
        var aTemp = new Array();

        aTemp[0] = strPagePath;

        strPrevPages = strPagePath;
        for (var i=0; (i < aPrevPages.length) && (i < 4); i++)
        {
          strPrevPages += ",";
          strPrevPages += aPrevPages[i];
          aTemp[aTemp.length] = aPrevPages[i];
        }
        aPrevPages = aTemp;

        var exdate = new Date();
        exdate.setDate(exdate.getDate() + 90);
        setCookie("prev_pages", strPrevPages, exdate, "/");
      }
    },
    /*
     * returns a string representing the solr dimension auto filters
     * 
     * What it does:
     *    builds up a string with the location boost query, previous search term boost queries, etc.
     * 
     */         
    getDimAutoFilters: function(strSearchTerm)
    {
      var strDimFilters = "";
      
      if (mDialogProps['enableLocationDim'] != "false")
      {
        // Apply location filters
        if (strUserOrga != "")
          strDimFilters += "&bq=dim_orga:" + strUserOrga + "^" + strOrgaWeight;
        if (strUserState != "")
          strDimFilters += "&bq=dim_state:" + strUserState + "^" + strStateWeight;
      }
      
      if (mDialogProps['enableSearchHistory'] == "true")
      {
        if (aPrevTerms[0])
          strDimFilters += "&bq=all_text:" + escape(aPrevTerms[0]) + "^" + mDialogProps['prevSearch1'];
        if (aPrevTerms[1])
          strDimFilters += "&bq=all_text:" + escape(aPrevTerms[1]) + "^" + mDialogProps['prevSearch2'];
        if (aPrevTerms[2])
          strDimFilters += "&bq=all_text:" + escape(aPrevTerms[2]) + "^" + mDialogProps['prevSearch3'];
      }
      // Add in the path stuff
      if (mDialogProps['enablePageHistory'] == "true")
      {
        if ((strCategory != null) && (strCategory.length > 0))
          strDimFilters += "&bq=category:%22" + escape(strCategory) + "%22^" + strCategoryWeight;
        if ((strSubcategory != null) && (strSubcategory.length > 0))
          strDimFilters += "&bq=subcategory:%22" + escape(strSubcategory) + "%22^" + strSubcategoryWeight;
        if ((strTitle != null) && (strTitle.length > 0))
          strDimFilters += "&bq=title:%22" + escape(strTitle) + "%22^" + strSubcategoryWeight;
      }
      // Finally, add the search term to the path query
      strDimFilters += "&bq=spath:" + escape(strSearchTerm) + "^3.0";
      
      return strDimFilters;
    },
    /*
     * gets the page name from a fqn path.
     * 
     * What it does:
     *    pulls the last name out of a path.
     * 
     */         
    buildPathQuery: function(strPath, strWeight)
    {
      var astrPath = strPath.split("/");
      var strName = strPath;
      var strQry = "";
      
      if (strWeight != null)
      {
        var strPath0 = null;
        var strPath1 = null;
        
        if (astrPath.length > 0)
          strPath0 = astrPath[astrPath.length - 1];
        if (astrPath.length > 1)
          strPath1 = astrPath[astrPath.length - 2];
      
        if ((strPath0 != null) && (strPath0.length > 0))
          strQry += "&bq=all_text:" + strPath0 + "^" + strWeight;
        if ((strPath1 != null) && (strPath1.length > 0))
          strQry += "&bq=all_text:" + strPath1 + "^" + strWeight;
      }
      return strQry;
    },
    /*
     * runs the misspelling query
     * 
     * What it does:
     *    puts the suggested value into the search field and runs the query.
     * 
     */         
    runSuggestionQuery: function(strQueryText)
    {
      (cachedElements.searchField).val(strQueryText);
    if (mDialogProps['useWeightedSort']) 
      siteSearch.runQueryUpdated(strQueryText);
    else 
        siteSearch.runQuery(strQueryText);      
    },
    /*
     * checks to see if the specified result item has a category pinned or not.
     * 
     * What it does:
     *    TODO
     * 
     */         
    checkProperty: function(strPropCat, idxArray, aCategories, mResCats)
    {
      if ((strPropCat != "") && (strPropCat != "-Normal Search Ranking-"))
      {
        var idx = 0;

        if (mResCats[strPropCat] == "true")
        {
          itm = new ResultItem();
          itm.cat = strPropCat;
          aCategories[idxArray] = itm;
        }
      }
    },
    /*
     * adds a category to the results
     * 
     * What it does:
     *    TODO
     * 
     */         
    addCategoryResults: function(iResCat, itm, strSearchVal)
    {
      // Note: catDef will only be null if the result has a category that no
      //       longer exists in the category definitions.
      var catDef = aCategoryDefs[itm.cat];
      if (catDef == null)
        return;
      var strHtml = "";
      var col = iResCat % 2 == 0 ? "left" : "right";
      var strQuery = siteSearch.getDimAutoFilters((cachedElements.searchField).val()) + "&q=" + strSearchVal;
      var strRequest = strPrefix + "/search.html?solr_q=" + encodeURIComponent(strQuery) + "&category=" + escape(itm.cat);

      strHtml += "<span class='category_result_seperator'></span><div id='apts_result_" + col + "' class='res_" + col + "'>" +
              "<div class='componentTitle'>" +
                "<h3>" + 
                  "<a href='" + strRequest + "'>" + 
                    itm.cat + "&nbsp;&#187;" + 
                  "</a>" + 
                "</h3>" +
              "</div>" +
              "<div id='apts_res_" + col + "_content' class='res_content'>";

        var iDocs = itm.docs.length;
      strHtml += "<ul>";

      for (var iDoc = 0; iDoc < iDocs; iDoc++)
      {
        var doc = itm.docs[iDoc];

        strHtml += '<li>';

        var strUrl = doc.url;

        if (!strUrl.match("\\.aspx$") && !strUrl.match("\\.html$"))
          strUrl += ".html";

        if (catDef.display_blurb_image) {
          if (doc.blurb_image) {
            strHtml += '<img alt="" src="' + doc.blurb_image + '">';
          }
        }

        strHtml += '<a href="' + strUrl + '">' + doc.title + '&nbsp;&#187;</a>';

        if (catDef.display_blurb)
        {
          var strBlurb = doc.blurb.substring(0, blurbLength);
          if (doc.blurb.length > blurbLength)
            strBlurb += "...";

          strHtml += '<p>' + strBlurb + '</p>';
        }
        strHtml += '</li>';
     }
     strHtml += '</ul></div>';
     strHtml += "</div>";
     var lastSearchResultsDiv;
     if (col == "left") {
        lastSearchResultsDiv = cachedElements.results.find(".searchResults .col_left");
        lastSearchResultsDiv.append(strHtml);
     } else {
        lastSearchResultsDiv = cachedElements.results.find(".searchResults .col_right");
        lastSearchResultsDiv.append(strHtml);
     }
    },
    addCategoryResultsUpdated: function(col, itm, strSearchVal)
    {
      // Note: catDef will only be null if the result has a category that no
      //       longer exists in the index
      var catDef = aCategoryDefs[itm.cat];
      if (catDef == null)
      {
        return false;
      }
      var strHtml = "";
      var strQuery = siteSearch.getDimAutoFilters((cachedElements.searchField).val()) + "&q=" + strSearchVal;
      
      var strRequest = strPrefix + "/search.html?solr_q=" + encodeURIComponent(strQuery) + "&category=" + escape(itm.cat);
      
      strHtml += "<span class='category_result_seperator'></span><div id='apts_result_" + col + "' class='res_" + col + "'>" +
              "<div class='componentTitle'>" +
                "<h3>" + 
                  "<a href='" + strRequest + "'>" + 
                    itm.cat + "&nbsp;&#187;" + 
                  "</a>" + 
                "</h3>" +
              "</div>" +
              "<div id='apts_res_" + col + "_content' class='res_content'>";

      var iDocs = itm.docs.length;
      strHtml += "<ul>";

      for (var iDoc = 0; iDoc < iDocs; iDoc++)
      {
        var doc = itm.docs[iDoc];

        strHtml += '<li>';

        var strUrl = doc.url;

        if (!strUrl.match("\\.aspx$") && !strUrl.match("\\.html$"))
        {
          if (strUrl.length == 0)
            strUrl = "index";
          strUrl += ".html";
        }  

        if (catDef.display_blurb_image) {
          if (doc.blurb_image) {
            strHtml += '<img alt="" src="' + doc.blurb_image + '" />';
          }
        }

        strHtml += '<a href="' + strUrl + '">' + doc.title + '&nbsp;&#187;</a>';

        if (doc.blurb && doc.blurb.length > 0)
        {
          var strBlurb = doc.blurb.substring(0, blurbLength);
          if (doc.blurb.length > blurbLength)
            strBlurb += "...";

          strHtml += '<p>' + strBlurb + '</p>';
        }
        strHtml += '</li>';
      }
      strHtml += '</ul></div>';
      strHtml += "</div>";
      var lastSearchResultsDiv;
      if (col == "left") {
        lastSearchResultsDiv = cachedElements.results.find(".searchResults .col_left");
        lastSearchResultsDiv.append(strHtml);
      } else {
        lastSearchResultsDiv = cachedElements.results.find(".searchResults .col_right");
        lastSearchResultsDiv.append(strHtml);
      }
      return true;
    },
    updateSearchButton: function (state) {
      if (state === 'panelState_open') {
        var regexp = new RegExp(constants.submitButtonSuffix_submit,'g');
        (cachedElements.searchSubmit).attr('src', ((cachedElements.searchSubmit).attr('src')).replace(regexp, constants.submitButtonSuffix_searchClose));
        searchAction = constants.searchAction_close;
      }
      else {
        var regexp = new RegExp(constants.submitButtonSuffix_searchClose,'g');
        (cachedElements.searchSubmit).attr('src', ((cachedElements.searchSubmit).attr('src')).replace(regexp, constants.submitButtonSuffix_submit));
        searchAction = constants.searchAction_search;
      } 
    },
    /*
     * runs the query for a given category.  If null is passed in, a generic query is run.
     * 
     * What it does:
     *    runs a query.
     * 
     */    
    runCatQuery: function(cat, mCategories, aCategories, strSearchVal, iNumRows) {
      var strDimFilters = siteSearch.getDimAutoFilters(strSearchVal);
      var strQuery = strDimFilters + "&rows=" + iNumRows + "&q=" + strSearchVal;
      var iCat;

      if (cat != null)
      {
        strQuery += "&fq=category:\"" + escape(cat.cat) + "\"";
        
        if  ((cat.query != null) && (cat.query.length > 0))
          strQuery += "&" + cat.query;
      }
      else
      {
        // Add filter query in for all non-query cats to increase performance
        var strCatFilter = "";
        for (iCat = 0; iCat < aCategories.length; iCat++)
        {
          var aCat = aCategories[iCat];

          if (aCat.query == null)
            strCatFilter += "category:\"" + escape(aCat.cat) + "\" ";
        }
        if (strCatFilter.length > 0)
          strQuery += "&fq=" + strCatFilter;
      }
      
      var strRequestString = strSolrSearchUrl + "/?wt=json&json.wrf=?&jsoncallback=?" + strQuery;

      // close subnav tabs when triggering search
      topNav.closeTabs();
      siteSearch.addPrevTerm(strSearchVal);
      $.getJSON(strRequestString, {},
        function(resp) {
          var iDoc;

          if (cat == null)
          {
            // Populate all the categories
            for (iDoc = 0; iDoc < resp.response.docs.length; iDoc++)
            {
              var doc = resp.response.docs[iDoc];
              var qryCat = mCategories[doc.category];
              
              if (qryCat != null)
              {
                if (qryCat.query == null)
                {
                  if (qryCat.docs.length < maxResultsPerCategory)
                  {
                    qryCat.docs[qryCat.docs.length] = doc;
                  }
                }
              }
            }
          }
          else
          {
            for (iDoc = 0; iDoc < resp.response.docs.length; iDoc++)
              cat.docs[iDoc] = resp.response.docs[iDoc];
          }
          iNumQueriesToRun--;
          
          if (iNumQueriesToRun < 1)
          {
            siteSearch.populateDivs(aCategories, strSearchVal);
          }          
        }
      );    
    },
    /*
     * runs the query for a given category.  If null is passed in, a generic query is run.
     * 
     * What it does:
     *    runs a query.
     * 
     */    
    populateDivs: function(aCategories, strSearchVal) {
      cachedElements.results.find(".searchResults .column").empty();
      (cachedElements.resultsContainer).show();
      // hack to lift results container up above form controls in IE6
      (cachedElements.resultsContainer).bgiframe();
      (cachedElements.results).show();
      (cachedElements.messageContainer).hide();
      siteSearch.updateSearchButton('panelState_open');
      var messagingDisplayed = false;
      var col = "";
      var iItemsAdded = 0;
      
      for (var iResCat = 0; iResCat < aCategories.length && iResCat < maxCategoriesForDisplay ; iResCat++)
      {
        var itm = aCategories[iResCat];

        col = ((iItemsAdded % 2) == 0) ? "left" : "right";
        
        if ((itm.cat != null) && (itm) && (itm.docs.length > 0))
        {
          siteSearch.addCategoryResultsUpdated(col, itm, strSearchVal);
          iItemsAdded++;
        }
      }
      for (var iHideCat = aCategories.length; iHideCat < iNumResCats; iHideCat++)
      {
        $("#apts_result_" + iHideCat).hide();
      }
    }
  };
}();  

/*
 * populates the dimension values for the properties dialog.  Doesn't seem to work
 * when it's inside the siteSearch object...
 * 
 * What it does:
 *    just sets the selection objects options to the aCategoryOpts variable.
 * 
 */         
function populateDimVals(sel, path, record) 
{ 
  sel.setOptions(aCategoryOpts); 
}
/*
 * topnav JS
 * @author Engineering
 * @fileoverview
 * 
 * Javascript for topnav component
 *
 */

 
/*
 * topnav code
 * @class topNav
 */ 
var topNav = function () {
	var variables = {};
	
	var classes = {
		highlighted: 'highlighted',
		highlightedPrev: 'highlightedPrev'    		
	};

	return {					
		init: function () {
			topNav.cacheVariables();
			topNav.addClasses();
			topNav.bindTabLinks();
		},
		/*
		 * add classes to various elements
		 * 
		 * What it does:
		 * 		if the li.highlighted list item if it exists and adds the highlightedPrev to the element before it
		 * 
		 */						
		addClasses: function () {
			(variables.nav).find('li.highlighted').prev().addClass(classes.highlightedPrev);
			(variables.nav).find('ul#topNavTabLinks > li:first').addClass(COMMON_globalConstants.firstChild);
			(variables.nav).find('ul#topNavTabLinks > li:last').addClass(COMMON_globalConstants.lastChild);
		},
		/*
		 * bind events to tab links
		 * 
		 * What it does:
		 * 		gather all tab links. When a tab is clicked on, remove highlighted/highlightedPrev classes from any of the tablink list items. also gather all the close
		 *		links. when a close link is clicked on, hide the sub nav tab content and remove any 'current' related classes that COMMON_tabs_display might have added. 
		 * 		also retrieve the tab that was previously highlighted and add the highlighted class back to it (and highlightedPrev to the element before it.)
		 */						
		bindTabLinks: function () { 			
			var tabLinks = (variables.nav).find('ul#topNavTabLinks > li a.tabLink');
			var tabListItems = (variables.nav).find('ul#topNavTabLinks > li');
			
			tabLinks.bind('click', function (e) {
				var tabLink = $(this);
				var tabIndex = tabLinks.index(this);
				var tabLinkListItem = tabLink.parents('li')
				var e = e || window.event;
				e.preventDefault();	
				

				// remove 'current' from all content tabs
				(variables.nav).children('div.tabContentContainer').children('div.tabContent').removeClass(COMMON_globalConstants.current);
				
				if (tabLinkListItem.hasClass(COMMON_globalConstants.current)) {				
					topNav.updateTabListItemClasses(tabListItems);
				}
				else {
					topNav.updateTabListItemClasses(tabListItems);
					
					// add 'current' to the list item for the link just clicked
					tabLinkListItem.addClass(COMMON_globalConstants.current);				
					// add 'currentPrev' to the sibling of the list item for the link just clicked
					tabLinkListItem.prev().addClass(COMMON_globalConstants.currentPrev);          
					// add 'currentNext' to the sibling of the list item for the link just clicked
					tabLinkListItem.next().addClass(COMMON_globalConstants.currentNext);
					
					// add 'current to the content tab that corresponds to the index of the tab link clicked 
					$((variables.nav).children('div.tabContentContainer').children('div.tabContent').get(tabIndex)).addClass(COMMON_globalConstants.current);
				}
				
				siteSearch.closeSearch();					
								
			});	

			var closeLinks = (variables.nav).find('div#topNavTabContentContainer > div.tabContent div.closeTabLink a');
			closeLinks.bind('click', function (e) {
				var closeLink = $(this);
				var tabIndex = (variables.nav).find('div#topNavTabContentContainer > div.tabContent').index($('div.current'));
				var e = e || window.event;
				e.preventDefault();
				
				
				closeLink.parents('div.tabContent').removeClass(COMMON_globalConstants.current);		
				var oldCurrent = $(tabListItems.get(tabIndex));
				oldCurrent.removeClass(COMMON_globalConstants.current);
				oldCurrent.removeClass(COMMON_globalConstants.currentPrev);
				oldCurrent.prev().removeClass(COMMON_globalConstants.currentPrev);
				oldCurrent.removeClass(COMMON_globalConstants.currentFirstChild);
				oldCurrent.removeClass(COMMON_globalConstants.currentLastChild);
								
				var restoredHighlight = $(tabListItems.get(variables.initialHighlightedIndex));			
				restoredHighlight.addClass(classes.highlighted);
				restoredHighlight.prev().addClass(classes.highlightedPrev);
				
			});	
		},
		/*
		 * store variables for later use
		 * 
		 * What it does:
		 * 		store jquery nav object and the index of the tab that was highlighted on load (will get -1 if nothing was initially highlighted).
		 */								
		cacheVariables: function () {
			variables.nav = $('div.topNav');
			variables.initialHighlightedIndex = (variables.nav).find('ul#topNavTabLinks > li').index($('li.highlighted'));
		},
		closeTabs: function () {
			$('div.topNav').each (function () {
				var thisTabsComponent = $(this);
				
				// remove 'current' from all tab list items
				thisTabsComponent.find('ul#topNavTabLinks > li').removeClass(COMMON_globalConstants.current);
				thisTabsComponent.find('ul#topNavTabLinks > li:first').removeClass(COMMON_globalConstants.currentFirstChild);
				thisTabsComponent.find('ul#topNavTabLinks > li:last').removeClass(COMMON_globalConstants.currentLastChild);
				// remove 'currentPrevious' and 'currentNext' from all tab list items
				thisTabsComponent.find('ul#topNavTabLinks > li').removeClass(COMMON_globalConstants.currentPrev);
				thisTabsComponent.find('ul#topNavTabLinks > li').removeClass(COMMON_globalConstants.currentNext);  
				
				thisTabsComponent.find('div#topNavTabContentContainer > div.tabContent').removeClass(COMMON_globalConstants.current);				
			});
		},		
		updateTabListItemClasses: function (tabListItems) {
			tabListItems.each(function () {
				$(this).removeClass(classes.highlighted);	
				$(this).removeClass(classes.highlightedPrev);	
				// remove 'current' from all tab list items
				$(this).removeClass(COMMON_globalConstants.current);
				// remove 'currentPrevious' and 'currentNext' from all tab list items
				$(this).removeClass(COMMON_globalConstants.currentPrev);
				$(this).removeClass(COMMON_globalConstants.currentNext);         														
			});			
		}
	};
}();	/*
 * newsfeed JS
 * @author Engineering
 * @fileoverview
 * 
 * Javascript for newsfeed component
 *
 */

 
/*
 * newsfeed code
 * @class newsfeed
 */ 
var newsfeed = function () {
	return {
		/*
		 * set up newsticker params
		 * 
		 * What it does:
		 * 		create jticker object for newsticker element
		 * 
		 */						
		init: function () {
			$("#newsticker").jticker({
				delay: 5000,
				newwindow: true,
				url: "${currentNode.path}.rss.xml",
				transition: "fade",
				speed: "slow"
			});
		}	
	};
}();	/*
 * social links JS
 * @author Engineering
 * @fileoverview
 * 
 * Javascript for social_links component
 *
 */

 
/*
 * socialLinks code
 * @class socialLinks
 */ 
var socialLinks = function () {
	var emailVariables = {
		subject:  "Interesting item on University of Phoenix website",
		body: "I thought you'd be interested in this item from University of Phoenix:\r\n\r\n"
	}
	
	return {					
		init: function () {
			emailVariables.pageURL = window.location.href;			
			socialLinks.addClasses();
			socialLinks.bindMouseEvents();
		},
		addClasses: function () {
			$('ul.socialLinks li:first').addClass(COMMON_globalConstants.firstChild);
			$('ul.socialLinks li:last').addClass(COMMON_globalConstants.lastChild);			
		},
		bindMouseEvents: function () {
			$('ul.socialLinks li.share').bind('mouseenter', function () {
				$(this).addClass(COMMON_globalConstants.IE6Hover);
			});

			$('ul.socialLinks li.share').bind('mouseleave', function () {
				$(this).removeClass(COMMON_globalConstants.IE6Hover);			
			});			
			
			$('ul.socialLinks li.share').children('a').bind('click', function (e) {
				var e = e || window.event;
				e.preventDefault();								
			});			

			$('ul.socialLinks li.share ul li a').bind('click', function (e) {
				var e = e || window.event;
				e.preventDefault();	

				window.open($(this).attr('href'),'socialLink');
			});			

			
			$('ul.socialLinks li.print a').bind('click', function (e) {
				var e = e || window.event;
				e.preventDefault();	
				window.print();		
			});
			
      $('ul.socialLinks li.email a').bind('click', function (e) {
        var e = e || window.event;
        e.preventDefault(); 
        socialLinks.emailPage();   
      });
		},
		emailPage: function () {
			window.location = "mailto:?subject=" + escape(emailVariables.subject) + "&body=" + escape(emailVariables.body + emailVariables.pageURL);
		}
	};
}();/*
 * social feeds JS
 * @author Engineering
 * @fileoverview
 * 
 * Javascript for socialfeeds component
 *
 */

 
/*
 * socialFeeds code
 * @class socialFeeds
 */ 
var socialFeeds = function () {	
	return {					
		init: function () {		
			socialFeeds.addFlashParams;
		},
		/*
		 * add needed flash param to YouTub social feeds videos to correct z-index issue with social links dropdown menu
		 * 
		 * What it does:
		 * 		append param HTML to video objects
		 */						
		addFlashParams: function () {
			$('div.socialfeeds div#ytvideos object').append('<param value="opaque" name="wmode">');
		}
	};
}();/*
 * articleSetting JS
 * @author Engineering
 * @fileoverview
 * 
 * Javascript for articlesetting component
 *
 */

 
/*
 * articleSetting code
 * @class articleSetting
 */ 
var articleSetting = function () {
	return {
		init: function () {
			articleSetting.bindMouseEvents();
		},
		bindMouseEvents: function () {
			$('div.article div.more a').bind('click', function (e) {
				var e = e || window.event;
				e.preventDefault();								
				
				var articleContainer = $(this).parents('div.article');
				articleContainer.find('div.excerpt').hide();
				articleContainer.find('div.articleText').show();
				articleContainer.find('div.more').hide();
				
				var thisContentPager = $(this).parents('div.featuredPager_bottom');
				if (thisContentPager.length) {
					// force redraw to reposition controls
					thisContentPager.find('div.pagerControlsContainer').attr('style','border-width: 0');
					thisContentPager.find('div.pagerControlsContainer').removeAttr('style');
				}
				
			});
			
			$('div.articleText div.closeArticleLink a').bind('click', function (e) {
				var e = e || window.event;
				e.preventDefault();								

				var articleContainer = $(this).parents('div.article');
				articleContainer.find('div.excerpt').show();
				articleContainer.find('div.articleText').hide();
				articleContainer.find('div.more').show();
				
				var thisContentPager = $(this).parents('div.featuredPager_bottom');
				if (thisContentPager.length) {
					// force redraw to reposition controls
					thisContentPager.find('div.pagerControlsContainer').attr('style','border-width: 0');
					thisContentPager.find('div.pagerControlsContainer').removeAttr('style');
				}
				
			});
		}
	};
}();	/*
 * GoogleMapTool JS
 * @author Engineering
 * 
 * Shared javascript functions for loading google map
 *
 */

 
/*
 * GoogleMapTool code
 * @class googleMapTool
 */

//Constructor of the googleMapTool class
function googleMapTool(divObject, displayControl, dirPanel){
  this.map = new GMap2(divObject);
  if(displayControl && displayControl != 0){
    if(displayControl == 1){
      this.map.addControl(new GSmallMapControl());
    } else if(displayControl == 2){
      this.map.addControl(new GLargeMapControl());
    }
    this.map.addControl(new GMapTypeControl());
  }
  this.map.setCenter(new GLatLng(33.413025, -111.982443), 13); 
  this.markerBounds = new GLatLngBounds();
  //GClientGeocoder --This class is used to communicate directly with Google servers to obtain geocodes for user specified addresses
  this.geocoder = new GClientGeocoder();
  this.directionsPanel = null;
  if(dirPanel){
    this.directionsPanel = dirPanel;
  }
  
  this.fromAddr = "";
  this.toAddr = "";
  this.directions = null;
}

/*
 * Function that will be called back by the google geocoder to add an address into the map 
 */
googleMapTool.prototype.addAddressToMap = function(response){
  if (response && response.Status.code == 200) {
    place = response.Placemark[0];
    point = new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]);
    marker = new GMarker(point);
    this.map.clearOverlays();
    this.map.addOverlay(marker);
    this.map.setCenter(point, 13);
  }
}

/*
 * Setter function of the class' directions panel
 */
googleMapTool.prototype.setDirectionsPanel = function(dirPanel){
  if(dirPanel){
    this.directionsPanel = dirPanel;
  }
}

/*
 * Clears the direction panel
 */
googleMapTool.prototype.clearDirectionsPanel = function(){
  if(this.directionsPanel != null){
    this.directionsPanel.innerHTML = "";
  }
}

/*
 * Add a learning center onto the map while keeping any existing learning centers already on the map
 * The argument must be an object literal in the form of:
 * {lat:(long), lng:(long), popupHtml:(HTML String)} 
 */
googleMapTool.prototype.addLearningCenter = function(item){
  point = new GLatLng(item.lat, item.lng);
  marker = new GMarker(point);
    
  //Add the campus into the map
  this.map.addOverlay(marker);
  marker.bindInfoWindowHtml(item.popupHtml);
  this.markerBounds.extend(point);
  
  //Reset the center of the map using GLatLngBounds
  this.map.setCenter(this.markerBounds.getCenter(), this.map.getBoundsZoomLevel(this.markerBounds));
}

/*
 * Add multiple learning centers onto the map while keeping any existing learning centers already on the map
 * The argument must be an array of object literals in the form of:
 * {lat:(long), lng:(long), popupHtml:(HTML String)} 
 */
googleMapTool.prototype.addLearningCenters = function(itemList) {
  for(i = 0; i < itemList.length; i++){
    var currentItem = itemList[i];
    point = new GLatLng(currentItem.lat, currentItem.lng);
    marker = new GMarker(point);
        
    //Add the campus into the map
    this.map.addOverlay(marker);
    marker.bindInfoWindowHtml(currentItem.popupHtml);
    this.markerBounds.extend(point);
  }
  
  //Reset the center of the map using GLatLngBounds
  this.map.setCenter(this.markerBounds.getCenter(), this.map.getBoundsZoomLevel(this.markerBounds));
}

/*
 * Add a learning center onto the map and remove any existing location already on the map
 * The argument is an address string of the learning center
 */
googleMapTool.prototype.addLearningCenterByAddress = function(address){
  this.geocoder.getLocations(address.replace("%92","'"), retainThisObject(this, this.addAddressToMap));
}

/*
 * Returns the directions status 
 */
googleMapTool.prototype.getDirectionsStatus = function(){
  return this.directions.getStatus();
}

/*
 * Display the directions that is specified from the FromAddress and the ToAddress arguments
 * if callbackFn exists, it will be called after the directions have been loaded
 */
googleMapTool.prototype.displayDirections = function(FromAddress, ToAddress, callbackFn){
    this.directionsPanel.innerHTML="";
    this.map.clearOverlays();
    this.fromAddr = FromAddress;
    this.toAddr = ToAddress;
    currentDirections = new GDirections(this.map, this.directionsPanel);
    
    if(callbackFn){
      GEvent.addListener(currentDirections, "addoverlay", function() {
        callbackFn();
      });
      
      //Calling the callbackFn since the addoverlay event wont get fired in the event of error
      GEvent.addListener(currentDirections, "error", function() {
        callbackFn();
      });
    }
    currentDirections.load(FromAddress + " to " + ToAddress);
    this.directions = currentDirections;
}/*
 * shared_program_tuition JS
 * @author Danny
 * 
 * Shared javascript for program_filter and tuitioninfo component
 *
 */
var rfiCookieValueMap = {
  "arts-and-sciences" : "9",
  "business-and-management": "1",
  "criminal-justice-and-security": "2",
  "education": "3",
  "nursing-and-health-care": "5",
  "human-services": "4",
  "psychology": "6",
  "technology": "7"
};

var rfiProgramValueIDMap = {
    "1": "business-and-management",
    "2": "criminal-justice-and-security",
    "3": "education",
    "4": "human-services",
    "5": "nursing-and-health-care",
    "6": "psychology",
    "7": "technology",
    "9": "arts-and-sciences"
}

var formatRfiMap = {
    "Campus": "ground",
    "Online": "online"
}

var lvlProgTuitionMap = {
    "associates": "undergrad",
    "bachelors": "undergrad",
    "masters": "grad",
    "doctoral": "grad"
}

function setCookieVals(strCookieName, strCookieVal, rfiCookieName)
{
  var exdate=new Date();
  exdate.setDate(exdate.getDate() + 90);

  setRfiCookieVal(strCookieName, strCookieVal, rfiCookieName);
  setCookie("pf_" + strCookieName, strCookieVal, exdate, "/");
}
function setRfiCookieVal(strCookieName, strCookieVal, rfiCookieName)
{
  var exdate=new Date();
  exdate.setDate(exdate.getDate() + 90);

  var strRfiCookieName = mapToRfiCookieName(strCookieName);
  var strRfiCookieValue = mapToRfiCookieValue(strRfiCookieName, strCookieVal);
  
  if(strRfiCookieName && strRfiCookieName.length > 0 && strRfiCookieValue && strRfiCookieValue.length > 0){
    setCookieValue(rfiCookieName,strRfiCookieName + "=" + strRfiCookieValue);
  }
}
function clearPfCookieVal(strCookieName)
{
  var exdate=new Date();
  exdate.setDate(exdate.getDate() + 90);
  setCookie("pf_" + strCookieName, "", exdate, "/");
}
function clearCookieVals(strCookieName, rfiCookieName)
{
  clearPfCookieVal(strCookieName);
  setRfiCookieVal(strCookieName, "", rfiCookieName);
}
function getCookieVal(strCookieName)
{
  var strRet = null;
  strRet = getCookie("pf_" + strCookieName);
  return strRet;
}
function allowedInNumberInput(e){
	var allowed = true;
	if (e.which > 47 && e.which < 58){
		//Numeric characters. 
		//Allowed
	} else if (e.which == 8) {
    	//Backspace
    	//Allowed
	} else if(e.which == 0){
    	//Arrow keys
    	//Allowed
	} else {
		allowed = false; 
	}
	return allowed;
}

function mapToRfiCookieName(cookieName){
  switch(cookieName){
    case 'learning_format': 
      return 'program_type';
      break;
    case 'program_area': 
      return 'program_type2';
      break;
    default:
      return cookieName;
  }
  return cookieName;
}

function mapToRfiCookieValue(rfiCookieName, cookieValue){
  switch(rfiCookieName){
    case 'program_type':
      switch(cookieValue){
        case 'ground':
          return 'Campus';
          break;
        case 'online':
          return 'Online';
          break;
        default:
          return cookieValue;
      }
      break;
    case 'program_type2':
      if(cookieValue === "nursing" || cookieValue === "health-care"){
        cookieValue = "nursing-and-health-care"
      }
      var value = rfiCookieValueMap[cookieValue];
      if(value){
        return value;
      } else {
        return "";
      }
      break;
    default: 
      return cookieValue;
  }
  return cookieValue;
}
/*
 * column control JS
 * @author Engineering
 * @fileoverview
 * 
 * Javascript for column component under altcloud
 *
 */

 
/*
 * colCtrl code
 * @class UPX_colCtrl
 */ 
var UPX_colCtrl = function () {
	var classes = {
		shadowBottom: 'shadowBottom',
		shadowLeft: 'shadowLeft',
		shadowRight: 'shadowRight'
	}
	return {					
		init: function () {
			UPX_colCtrl.addContainers();
		},
		/*
		 * wrap components in additional containers for styling
		 * 
		 * What it does:
		 * 		for each shadowed col control, get div with numColsContainer and wrap in 3 containers: div.shadowBottom, div.shadowLeft, div.shadowRight. Append numColsContainer div
		 *		as child of div.shadowRight and append 2 empty corner elements to main div.shadowed container.
		 * 
		 */								
		addContainers: function () {		
			$('div.shadowed').each(function () {
				var thisColCtrl = this;
				var numColsContainer = ($(thisColCtrl).find('div.numColsContainer')).get(0);
				
				var shadowBottom = document.createElement('div');
				shadowBottom.className = classes.shadowBottom;
				
				var shadowLeft = document.createElement('div');
				shadowLeft.className = classes.shadowLeft;
				shadowBottom.appendChild(shadowLeft);
				
				var shadowRight = document.createElement('div');
				shadowRight.className = classes.shadowRight;
				shadowRight.appendChild(numColsContainer);
				shadowLeft.appendChild(shadowRight);
				
				thisColCtrl.appendChild(shadowBottom);

				$(thisColCtrl).append('<div class="corner leftCorner"></div>');
				$(thisColCtrl).append('<div class="corner rightCorner"></div>');		
				
			});
		}
		
	};
}();/*
 * content pager JS
 * @author Engineering
 * @fileoverview
 * 
 * Javascript for column component under altcloud
 *
 */

 
/*
 * contentPager code
 * @class UPX_contentPager
 */ 
var UPX_contentPager = function () {
	var classes = {
		shadowBottom: 'shadowBottom',
		shadowLeft: 'shadowLeft',
		shadowRight: 'shadowRight'
	}
	return {					
		init: function () {
			UPX_contentPager.addContainers();
		},
		/*
		 * wrap components in additional containers for styling
		 * 
		 * What it does:
		 * 		for each shadowed col control, get div with numColsContainer and wrap in 3 containers: div.shadowBottom, div.shadowLeft, div.shadowRight. Append numColsContainer div
		 *		as child of div.shadowRight and append 2 empty corner elements to main div.shadowed container.
		 * 
		 */								
		addContainers: function () {	
			$('div.shadowedPager_top, div.shadowedPager_bottom').each(function () {
				var thisPager = $(this);
				thisPager.children('div').wrapAll('<div class="shadowBottom"><div class="shadowLeft"><div class="shadowRight"></div></div></div>');
				thisPager.append('<div class="corner leftCorner"></div>');
				thisPager.append('<div class="corner rightCorner"></div>');

			});
		}
		
	};
}();/*
 * tabs_display JS
 * @author Engineering
 * @fileoverview
 * 
 * Javascript for altcloud tabs_display component behavior
 *
 */

 
/*
 * UPX_tabsDisplay code
 * @class UPX_tabsDisplay
 */ 
var UPX_tabsDisplay = function () {
	var classes = {
		numCols1: 'numCols1',
		numCols2: 'numCols2',
		numCols2_7030: 'numCols2-7030',
		numCols2_3070: 'numCols2-3070',
		numCols2_6040: 'numCols2-6040',
		numCols2_4060: 'numCols2-4060',
		numCols3: 'numCols3',
		numCols4: 'numCols4',
		numColsContainer: 'numColsContainer',
		conversationTabs_top: 'conversationTabs_top',
		contentTabs_top: 'contentTabs_top',
		contentTabs_bottom: 'contentTabs_bottom'
	};
	
	
	var strings = {
		numCols_curr_prefix: '_col',
		numCols_curr_suffix: 'curr'	
	};
	
	return {					
		init: function () {
			UPX_tabsDisplay.removeTabLinkClasses();
			UPX_tabsDisplay.bindTabLinks();
		},
		/*
		 * bind events to tab links
		 * 
		 * What it does:
		 * 		gather all tab links. When a tab is clicked on, remove highlighted/highlightedPrev classes from any of the tablink list items. also gather all the close
		 *		links. when a close link is clicked on, hide the sub nav tab content and remove any 'current' related classes that COMMON_tabs_display might have added. 
		 * 		also retrieve the tab that was previously highlighted and add the highlighted class back to it (and highlightedPrev to the element before it.)
		 */						
		bindTabLinks: function () { 				
			$('div.conversationTabs_top').each (function () {
				var tabsComponent = $(this);
				var currNumCols;
				
				
				var tabLinks = tabsComponent.children('ul.tabLinks').find('li a.tabLink');
				var tabLinksList = tabLinks.parents('ul');				
				tabLinksList.addClass('numTabs' + tabLinks.length);
				
				var colControl_numColsContainer = tabsComponent.parents('div.tabs_display').prevAll('div.conversation').children('div.numColsContainer');
				
				if (colControl_numColsContainer.hasClass(classes.numCols1)) {
					currNumCols = classes.numCols1;
				}
				if (colControl_numColsContainer.hasClass(classes.numCols2)) {
					currNumCols = classes.numCols2;
				}
				if (colControl_numColsContainer.hasClass(classes.numCols2_7030)) {
					currNumCols = classes.numCols2_7030;
				}
				if (colControl_numColsContainer.hasClass(classes.numCols2_3070)) {
					currNumCols = classes.numCols2_3070;
				}
				if (colControl_numColsContainer.hasClass(classes.numCols2_6040)) {
					currNumCols = classes.numCols2_6040;
				}
				if (colControl_numColsContainer.hasClass(classes.numCols2_4060)) {
					currNumCols = classes.numCols2_4060;
				}
				if (colControl_numColsContainer.hasClass(classes.numCols3)) {
					currNumCols = classes.numCols3;
				}
				if (colControl_numColsContainer.hasClass(classes.numCols4)) {
					currNumCols = classes.numCols4;
				}
				
				tabLinks.bind('click', function (e) {
					var tabLink = $(this);
					var tabIndex = tabLinks.index(this);
					var e = e || window.event;
					
					if (!tabLink.hasClass(COMMON_globalConstants.tabClass_link)) {           					
						e.preventDefault();	
						
						if (tabLink.hasClass(COMMON_globalConstants.tabClass_close)) {
							colControl_numColsContainer.attr('className', classes.numColsContainer + ' ' + currNumCols);						
						}
						else {
							var currColString = currNumCols + strings.numCols_curr_prefix + tabIndex + strings.numCols_curr_suffix;
							colControl_numColsContainer.attr('className', classes.numColsContainer + ' ' + currNumCols + ' ' + currColString);
						}
					}
				});		
				
			});
			
		},
		/*
		 * remove extraneous classes being applied to tab links
		 * 
		 * What it does:
		 * 		gather all tab components. if it doesn't have one of the reserved style names, gather all the tab links and remove the extraneous tab classes
		 */						
		removeTabLinkClasses: function () {
			$('div.tabsComponent').each(function () {
				var tabsComponent = $(this);	
				if (!tabsComponent.hasClass(classes.conversationTabs_top) && !tabsComponent.hasClass(classes.contentTabs_top) && !tabsComponent.hasClass(classes.contentTabs_bottom)) {
					tabsComponent.find('a.tabLink').each(function () {
						$(this).removeClass(COMMON_globalConstants.tabClass_close);
						$(this).removeClass(COMMON_globalConstants.tabClass_expand);
						$(this).removeClass(COMMON_globalConstants.tabClass_link);
						$(this).removeClass(COMMON_globalConstants.tabClass_tab);									
					});
				}
			});
		}
	};
}();	/*
 * program_filter JS
 * @author Danny
 * 
 * Javascript functions for program_filter component
 *
 */

var defaultResultContent = '<li class="current"><div class="componentTitle"><h3><a class="tabLink" href="#" name="programFilter_notFound">Not Found</a></h3></div>'
	+ '<div class="resultTab accordionContent"><div class="noPrograms">No programs are found based on your search criteria</div></div></li>';
var progFinderErrorCssClass = 'inputError';

var programFilterObjects = new Array();

function getLocation()
{
  var strLoc = null;

  strLoc = defaultCampus;
  
  if ((!strLoc) || (strLoc == ""))
    strLoc = "state_default-online";
    
  return strLoc;
}

function updateProgAreaList(progFilterObj, bForZip)
{
  $.getJSON(progFilterObj.currentProgramFinderNodePath + ".program_area_list.json/f/location_id/" 
      + (bForZip ? "zip_" + progFilterObj.progFilterZipCodeSpan.html() : getLocation()) + "/f/program_type/degree-program", {},
	  function(resp) {
	    var options = '';
	    options += "<option value=''>Area of Interest</option>";
	    $.each(resp.program_areas, function(i,pa) {
	      options += "<option value='" + pa.id + "'";
	      if (pa.id == progFilterObj.g_selProgArea)
	        options += " selected='true'";
	      options += " class='filter_option_list'>" + pa.title + "</option>";
	    });
	    progFilterObj.programAreaSel.html(options);
	    
	    
	    if(progFilterObj.g_selProgType.length == 0){
	      //Pre-populate area of interest from cookies if the filter doesn't exists
        var progAreaOfInterest = returnCookieAttributeValue(rfiCookie, "program_type2");
        if(progAreaOfInterest && progAreaOfInterest.length > 0){
          progFilterObj.programAreaSel.children("[value=" + 
              rfiProgramValueIDMap[progAreaOfInterest] + "]").attr("selected", "selected");
        }
	    } else if(progFilterObj.g_selProgType.length > 0 && progFilterObj.g_Location != "online"){
	      //Trigger the click event of the degree program ok button if the filter for degree program exists
        //This is triggered here or else there's a good chance that the button click event is triggered before 
        //the degree program area list has finished loading
	      processDegProgInputs(progFilterObj);
	      
	      //Removing the values so that the button click event does not get triggered again
	  	  progFilterObj.g_selProgArea = "";
	  	  progFilterObj.g_selProgType = "";
	    }
    }
  )
}

function updateCertProgAreaList(progFilterObj, bForZip)
{
  $.getJSON(progFilterObj.currentProgramFinderNodePath + ".program_area_list.json/f/location_id/" + (bForZip ? "zip_" + progFilterObj.progFilterZipCodeSpan.html() : getLocation()) + "/f/program_type/certifications", {},
    function(resp) {
      var options = '';
      options += "<option value=''>Area of Interest</option>";
      $.each(resp.program_areas, function(i,pa) {
        options += "<option value='" + pa.id + "'";
        if (pa.id == progFilterObj.g_selProgArea)
          options += " selected='true'";
        options += " class='filter_option_list'>" + pa.title + "</option>";
      });
      progFilterObj.contEduCertProgSel.html(options);

      //Trigger the click event of the continuing education ok button if the filter for cert program exists
      //This is triggered here or else there's a good chance that the button click event is triggered before 
      //the cert program area list has finished loading
      if(progFilterObj.g_selCourseType.length > 0 && progFilterObj.g_selCourseType == "certificate-programs" && progFilterObj.g_Location != "online"){
        processContEduInputs(progFilterObj)
      	//Removing the values so that the button click event does not get triggered again
    	  progFilterObj.g_selProgArea = "";
    	  progFilterObj.g_selCourseType = "";
      }
    }
  )
}

function hideAllContEduSelects(progFilterObj){
	progFilterObj.contEduLevelSel.removeClass('showComponent');
	progFilterObj.contEduIndCourseSel.removeClass('showComponent');
	progFilterObj.contEduTeacherEduSel.removeClass('showComponent');
	progFilterObj.contEduEduIndCourseSel.removeClass('showComponent');
	progFilterObj.contEduProfDevSel.removeClass('showComponent');
	progFilterObj.contEduCertProgSel.removeClass('showComponent');
	progFilterObj.certProgramIntLink.removeClass('showComponent');
	
	progFilterObj.contEduLevelSel.addClass('hideComponent');
	progFilterObj.contEduIndCourseSel.addClass('hideComponent');
	progFilterObj.contEduTeacherEduSel.addClass('hideComponent');
	progFilterObj.contEduEduIndCourseSel.addClass('hideComponent');
	progFilterObj.contEduProfDevSel.addClass('hideComponent');
	progFilterObj.contEduCertProgSel.addClass('hideComponent');
	progFilterObj.certProgramIntLink.addClass('hideComponent');
}


/**** Functions for the full format ****/

function updateDegreeAndCertProgramResults(resp, progFilterObj, showAll, bCertification){
  var noResult = false;
  var defaultOpenTabId = "arts-and-sciences";
  var cookieProgId = returnCookieAttributeValue(rfiCookie, "program_type2");
  if(cookieProgId && cookieProgId.length > 0){
    defaultOpenTabId = rfiProgramValueIDMap[cookieProgId];
  }
  var resultULContent = "";
    if(resp.results.length == 0){
      noResult = true;
    } else {
      var totalProgramsDisplayed = 0;
      $.each(resp.results, function(iPA, progArea) {
        var listItemHtml;
        if(bCertification){
          //Open the first tab if it's a certificate program
          if(iPA == 0){
            listItemHtml = '<li class="current">';
          } else {
            listItemHtml = '<li>';
          }
        } else {
          //Open the selected program area tab if it's degree program
          if(progArea.id == defaultOpenTabId){
            listItemHtml = '<li class="current">';
          } else {
            listItemHtml = '<li>';
          }
        }
        listItemHtml += '<div class="componentTitle">'
            + '<div class="campusIconWrapper"><a href="#" name="programFilter_campusIcon"><div class="campusIcon">&nbsp;</div>'
            + '<div class="programFinderToolTip campusTooltip">Campus</div>'
            + '<div class="programFinderToolTipBot campusToolTipBot">&nbsp;</div></a><img class="print" src="/etc/designs/ac/img/icon_campus.png" alt="Online"></div>'
            + '<div class="onlineIconWrapper"><a href="#" name="programFilter_onlineIcon"><div class="onlineIcon">&nbsp;</div>'
            + '<div class="programFinderToolTip onlineTooltip">Online</div>'
            + '<div class="programFinderToolTipBot onlineToolTipBot">&nbsp;</div></a><img class="print" src="/etc/designs/ac/img/icon_online.png" alt="Online"></div>'
            + '<h3><a class="tabLink" href="#" name="programFilter_' + progArea.title + '">' + progArea.title + '</a></h3>'
            + '</div>';
        listItemHtml += '<div class="resultTab accordionContent"><table class="degreesList">';
        $.each(progArea.program_levels, function(iPL, progLevel) {
          //Filter by the program level if not showAll or if not cert program 
          if(showAll || bCertification || 
               progFilterObj.programLevelSel.val().length == 0 || progLevel.id == progFilterObj.programLevelSel.val()){
            if(!bCertification){
              listItemHtml += '<tr><td><h4>' + progLevel.title + '</h4></td><td class="locationCell"></td><td class="locationCell"></td></tr>';
            }
            $.each(progLevel.program_vers, function(iPV, progVer) {
              var liClass = "";
              if(progVer.campus == "true"){
                liClass += "campus";
              }
              if(progVer.online == "true"){
                liClass += "online";
              } 
              listItemHtml += '<tr>';
              listItemHtml += '<td><a href="' + progVer.ref + '.html">' + progVer.title + '&nbsp;&#187;</a></td>';
              listItemHtml += '<td class="locationCell">';
              if(progVer.online == "true"){
                listItemHtml += '<img class="print" alt="Online Program Exists" src="/etc/designs/ac/img/bg_program_finder_bullet.png">';
              }
              listItemHtml += '</td>';
              listItemHtml += '<td class="locationCell">';
              if(progVer.campus == "true"){
                listItemHtml += '<img class="print" alt="Campus Program Exists" src="/etc/designs/ac/img/bg_program_finder_bullet.png">';
              }
              listItemHtml += '</td>';
              listItemHtml += '</tr>';
            });
            totalProgramsDisplayed++;
          }
        });
        listItemHtml += '</table></div></li>';
        resultULContent += listItemHtml;
      });
      if(totalProgramsDisplayed == 0){
        noResult = true;
      }
    }
    searchTitlelink.html('SEARCH AGAIN');
    toggleSearchLink(progFilterObj);
    resultTabsDiv.show();
    
    if(noResult){
      resultUL.html(defaultResultContent);
    } else {
      resultUL.html(resultULContent);
    }
    
    //Update the accordion so that they behave like accordion
  COMMON_accordion.init(resultTabsDiv);
}
	
function updateDegreeProgramResults(progFilterObj, showAll, bForZip){
  var filterStr = "/f/location_id/" + (bForZip ? "zip_" + progFilterObj.progFilterZipCodeSpan.html() : getLocation());
  if(progFilterObj.programAreaSel.val().length == 0 || showAll ){
    filterStr += "/f/" + progFilterObj.programAreaSel.attr('name') + "/all";
  } else {
    filterStr += "/f/" + progFilterObj.programAreaSel.attr('name') + "/" + progFilterObj.programAreaSel.val();
  }
  filterStr += "/f/program_type/degree-program";
	$.getJSON(progFilterObj.currentProgramFinderNodePath + ".query.json" + filterStr, {},
	  function(resp) {
	    updateDegreeAndCertProgramResults(resp, progFilterObj, showAll, false);
	  }
	);
}

function updateContEduResults(progFilterObj, showAll, bForZip){
	var selectedCourse = progFilterObj.contEduCourseTypeSel.val();
	var noResult = false;
	
	if(selectedCourse == 'certificate-programs'){
		//Cert programs should use the same query json as the degree program
		var jsonUrl = progFilterObj.currentProgramFinderNodePath + ".query.json/f/location_id/" + (bForZip ? "zip_" + progFilterObj.progFilterZipCodeSpan.html() : getLocation())
		$.each(progFilterObj.courseTypeSelects[selectedCourse], function(){
			if($(this).attr('name')){
			  if(showAll){
			    jsonUrl += "/f/" + $(this).attr('name') + "/all";
			  } else if(this.val().length > 0){
			    jsonUrl += "/f/" + $(this).attr('name') + "/" +  $(this).val();
			  }
			}
		});
		jsonUrl += "/f/program_type/certifications";
		
		$.getJSON(jsonUrl, {}, function(resp) {
		    updateDegreeAndCertProgramResults(resp, progFilterObj, showAll, true);
		  }
		);
	} else {
		//Use the cont-edu query json for others
		var displayDegrees = false;
		var jsonUrl = progFilterObj.currentProgramFinderNodePath + ".cont_edu_filter.json/f/continuing_ed/" + selectedCourse;
		$.each(progFilterObj.courseTypeSelects[selectedCourse], function(){
			if(!showAll && $(this).attr('name') && $(this).val().length > 0){
				jsonUrl += "/f/" + $(this).attr('name') + "/" + $(this).val();
			}
			if($(this).attr('name') == "degree"){
				displayDegrees = true;
			}
		});
		
		$.getJSON(jsonUrl, {}, function(resp) {
		    var resultULContent = "";
		    if(resp.continuing_eds.length == 0){
		    	noResult = true;
		    } else {
		    	var totalProgramsDisplayed = 0;
			    $.each(resp.continuing_eds, function(iPA, progArea) {
			    	var listItemHtml;
				    if(iPA == 0){
				    	listItemHtml = '<li class="current">';
				    } else {
				    	listItemHtml = '<li>';
				    }
				    listItemHtml += '<div class="componentTitle"><h3><a class="tabLink" href="#" name="programFilter_' + progArea.title + '">' + progArea.title + '</a></h3></div>';
					listItemHtml += '<div class="resultTab accordionContent"><table class="degreesList">';
					$.each(progArea.degrees, function(iPL, progLevel) {
						if(progLevel.courses.length > 0){
							if(displayDegrees){
								listItemHtml += '<tr><td><h4>' + progLevel.title + '</h4></td></tr>';
							}
								
							$.each(progLevel.courses, function(iPV, progCourse) {
								listItemHtml += '<tr><td><a href="' + progCourse.course_ref + '.html">' + progCourse.title + '&nbsp;&#187;</a></td></tr>';
								totalProgramsDisplayed++;
							});
						}
					});
				    listItemHtml += '</table></div></li>';
				    resultULContent += listItemHtml;
			    });
			    if(totalProgramsDisplayed == 0){
				    noResult = true;
			    }
		    }

		    searchTitlelink.html('SEARCH AGAIN');
		    toggleSearchLink(progFilterObj);
		    resultTabsDiv.show();

		    if(noResult){
		    	resultUL.html(defaultResultContent);
		    } else {
		    	resultUL.html(resultULContent);
		    }
		    
		    //Update the result accordion so that they behave like accordion
			COMMON_accordion.init(resultTabsDiv);
		});
	}
}

function toggleSearchLink(progFilterObj){
  progFilterObj.progFilterSearchContent.toggle();
  searchTitlelink.toggleClass('tabLinkOn');
  searchTitlelink.toggleClass('tabLinkOff');
}

/* Hide the zipcode and the change link and then display the zip input box and the cancel link*/
function progFilterChangeZipLinkClicked(progFilterObj){
  progFilterObj.progFilterZipCodeSpan.addClass("hideComponent");
  progFilterObj.progFilterZipInput.removeClass("hideComponent");
  progFilterObj.progFilterChangeZipLink.addClass("hideComponent");
  progFilterObj.progFilterCancelZipLink.removeClass("hideComponent");
  if(progFilterObj.progFilterZipCodeChange.hasClass("zipCodeChangeMoreMargin")){
    progFilterObj.progFilterZipCodeChange.addClass("zipCodeChangeLessMargin");
    progFilterObj.progFilterZipCodeChange.removeClass("zipCodeChangeMoreMargin");
  }
}

/* Hide the zip input box and the cancel link and then display the zipcode and the change link*/
function progFilterCancelZipLinkClicked(progFilterObj){
  progFilterObj.progFilterZipCodeSpan.removeClass("hideComponent");
  progFilterObj.progFilterZipInput.addClass("hideComponent");
  progFilterObj.progFilterChangeZipLink.removeClass("hideComponent");
  progFilterObj.progFilterCancelZipLink.addClass("hideComponent");
  if(progFilterObj.progFilterZipCodeChange.hasClass("zipCodeChangeLessMargin")){
    progFilterObj.progFilterZipCodeChange.addClass("zipCodeChangeMoreMargin");
    progFilterObj.progFilterZipCodeChange.removeClass("zipCodeChangeLessMargin");
  }
}

/* Validate the degree program inputs and update the degree program result if no error is found*/
function processDegProgInputs(progFilterObj){
  if(progFilterObj.programAreaSel.val().length > 0){
    setRfiCookieVal("program_type2", progFilterObj.programAreaSel.val(), rfiCookie);
  }
  
  if(progFilterObj.progFilterZipCodeSpan.html().length != 5){
      progFilterChangeZipLinkClicked(progFilterObj);
      progFilterObj.progFilterZipInput.addClass(progFinderErrorCssClass);
  } 
  else {
    updateDegreeProgramResults(progFilterObj, false, true);
  }
}

/* Validate the continuing education inputs and update the degree program result if no error is found*/
function processContEduInputs(progFilterObj){
  var selectedCourse = progFilterObj.contEduCourseTypeSel.val();
  var isProcessResult = true;
  if(selectedCourse.length > 0){
    //Check for the zip code if the selected course type is certificate programs
    if(selectedCourse == 'certificate-programs' && progFilterObj.progFilterZipCodeSpan.html().length == 0){
      isProcessResult = false;
      progFilterChangeZipLinkClicked(progFilterObj);
      progFilterObj.progFilterZipInput.addClass(progFinderErrorCssClass);
    }
    
    if(isProcessResult){
      updateContEduResults(progFilterObj, false, true);
    }
  } else {
    progFilterObj.contEduCourseTypeSel.addClass(progFinderErrorCssClass);
  }
}
/*
 * tuitioninfo JS
 * @author Danny
 * 
 * Javascript functions for tuition info component
 *
 */

var tuitionInfoErrorCssClass = 'errorInput';
var tuitionInfoObjects = new Array();
var g_selFldOfStudy;
var g_selDegree;
var g_selFormat;
var g_selCountry;
var rfiCookie;
var tuitionUrl;
var tuitionFilterUrl;

/*
 * Get the program areas for a particular location (zipcode) and update the area interest select
 */
/*function updateTuitionAreaList(progFilterObj, bForZip){
  $.getJSON(progFilterObj.currentProgramFinderNodePath + ".area_list.json/f/location_id/" + (bForZip ? "zip_" + progFilterObj.zipCodeSpan.html() : "state_default-online")
		  + "/f/program_type/degree-program", {},
    function(resp) {
      var options = '';
      options += "<option value=''>Area of Interest</option>";
      $.each(resp.tuition_groups, function(i,pa) {
        options += "<option value='" + pa.id + "'";
        if (pa.id == g_selFldOfStudy)
          options += " selected='true'";
        options += ">" + pa.title + "</option>";
      });
      progFilterObj.areaInterestSelect.html(options);
      progFilterObj.areaInterestSelect.change();
  })
}*/

/*
 * Select an item in the drop down menus based on the filter
 */
function updateSelectsFromFilter(progFilterObj){
  if(g_selFldOfStudy.length > 0){
    progFilterObj.areaInterestSelect.children("[value=" + g_selFldOfStudy + "]").attr("selected", "selected");
  }
  if(g_selDegree.length > 0){
		progFilterObj.degreeLevelSelect.children("[value=" + g_selDegree + "]").attr("selected", "selected");
	}
	if(g_selFormat.length > 0){
		progFilterObj.formatSelect.children("[value=" + g_selFormat + "]").attr("selected", "selected");
	}
	if(g_selCountry.length > 0){
    progFilterObj.countrySelect.children("[value=" + g_selCountry + "]").attr("selected", "selected");
  }
}

/* Hide the zipcode and the change link and then display the zip input box and the cancel link*/
function changeZipLinkClicked(tuitionObject){
  tuitionObject.zipCodeSpan.addClass("hideObject");
  tuitionObject.zipInput.removeClass("hideObject");
  tuitionObject.changeZipLink.addClass("hideObject");
  tuitionObject.cancelZipLink.removeClass("hideObject");
}

/* Hide the zip input box and the cancel link and then display the zipcode and the change link*/
function cancelZipLinkClicked(tuitionObject){
  tuitionObject.zipCodeSpan.removeClass("hideObject");
  tuitionObject.zipInput.addClass("hideObject");
  tuitionObject.changeZipLink.removeClass("hideObject");
  tuitionObject.cancelZipLink.addClass("hideObject");
}
/*
 * quick links JS
 * @author Engineering
 * @fileoverview
 * 
 * Javascript for column component under altcloud
 *
 */

 
/*
 * quickLinks code
 * @class quickLinks
 */ 
var quickLinks = function () {
	return {					
		init: function () {
			quickLinks.addClasses();
			quickLinks.addContainers();
		},
		addClasses: function () {
	      $('div.quicklinks, div.quickLinksColumn').each (function () {
	        var thisQuicklinksComponent = $(this);
	    
	        thisQuicklinksComponent.find('ul li:first').addClass(COMMON_globalConstants.firstChild);
	        thisQuicklinksComponent.find('ul li:last').addClass(COMMON_globalConstants.lastChild);  
	      });		
		},
		addContainers: function () {		
			$('div.shadowedQuicklinks').each(function () {
				var thisQuicklinks = $(this);
				thisQuicklinks.find('div.quickLinksColContainer').wrapAll('<div class="shadowBottom"><div class="shadowLeft"><div class="shadowRight"></div></div></div>');
				thisQuicklinks.append('<div class="corner leftCorner">&nbsp;</div>');
				thisQuicklinks.append('<div class="corner rightCorner">&nbsp;</div>');				
			});
		}
	};
}();/*
 * campusFinder JS
 * @author Danny
 * 
 * Javascript functions for campus finder component
 *
 */

var campusFinderObjects = new Array();

/*
 * pv_course_list JS
 * @author Engineering
 * @fileoverview
 * 
 * Javascript for program version course list component
 *
 */
 
/*
 * site search code
 * @class pvCourseList
 */ 

var pvCourseList = function () {
  /*
   * local variables
   */     
  return {
    init: function () {
      pvCourseList.bindEvents();
    },
    /*
     * adds events to various search form elements
     * 
     * What it does:
     *    bind 'focus' event to search field -- removes failure class if currently applied and sets value of field to blank. bind 'blur' event to search field -- if 
     *    the search field doesn't contain a value, replace the default input text. bind 'keydown' event to search field -- if there is error messaging behind displayed,
     *    clear the field, remove failure class if currently applied and set messaging flag to false. bind 'mouseover/out' events to submit button -- if the submit button 
     *    src contains '_off', replace with '_on' and vice versa. bind 'submit' event to form -- catch the submit event and check to see if the search field has a valid 
     *    entry (ie, not blank, not the default text, not error messaging). If not, display error messaging. If so, perform the submit actions
     * 
     */         
    bindEvents: function () {
      $('a.toggleDivLink').click(function (e) {
        e = e || window.event; 
        if (e.preventDefault) {
          e.preventDefault();
        } else {
          e.returnValue = false;
        }
        // "targ" points to the heading (h4) element.
        $(this).toggleClass('course_list_link_open');
		// we can't use toggle('normal') here because it messes up the td colspan. 
        $(this).parents('tr').next().find('td.courseInfoDescription').toggle();		
        $(this).parents('tr').toggleClass('open');
      });
    },
    /*
     * Returns indices of all "opened" course description div 
     */
    getOpenedDivIndices: function(){
      var openedIndices = new Array();
      $('a.toggleDivLink').each(function(i){
        if($(this).hasClass("course_list_link_open")){
          openedIndices.push(i);
        }
      });
      return openedIndices;
    }
  };
}();  

/*
 * pv_similar_progs_list JS
 * @author Engineering
 * @fileoverview
 * 
 * Javascript for program version similar programs list component
 *
 */
 
/*
 * Similar program list code.
 * @class pvSimilarProgsList
 */ 

var pvSimilarProgsList = function () {
  /*
   * local variables
   */
  var g_strUserLocPath = "/public/bin/servlet/altcloud/UserServlet.location.json?";
  // This is only the default...it should be set via the init function
  var g_strProgFilterPath = "/content/altcloud/en/programs/jcr:content/centerparsys/parsys/program_filter.query.json";
   
   
  return {
    init: function (strPagePath, strProgRoot) {
      // Need to load up the similar programs via Javascript since the list of available
      // programs depends on the location of the user.
  
  
      if (strProgRoot != null)
        g_strProgFilterPath = strProgRoot + "/jcr:content/centerparsys/parsys/program_filter.query.json";
      
      // We need to identify the program area.  Work backwards up the tree.
      // .../program area/<degree>/<program>/<version>
      var astrPath = strPagePath.split("/");
      
      if (astrPath.length > 4)
      {
        var strProgArea = astrPath[astrPath.length - 4];
        var strTypePath = astrPath[astrPath.length - 5];
        var strType = "degree";
        
        if (strTypePath != "degree-programs")
        {
          strType = "certifications";
          strProgArea = astrPath[astrPath.length - 3];
        }
        pvSimilarProgsList.loadSimilarProgs(strProgArea, strType);
      }
    },
    loadSimilarProgs: function(strProgArea, strType)
    {
      // Start by getting the user location      
      $.getJSON(g_strUserLocPath, {},
        function(resp) {
          if (resp) 
          {
            var strLocFilter = null;
            
            if (resp.orga)
              strLocFilter = "campus_" + resp.orga;
            else if (resp.state)
              strLocFilter = "state_" + resp.state;
            else if (resp.postal_code)
              strLocFilter = "zip_" + resp.postal_code;
            
            if (strLocFilter == null)
              strLocFilter = "state_default-online";
              
            pvSimilarProgsList.runProgramQuery(strProgArea, strLocFilter, strType);
          }
        }
      );
    },
    runProgramQuery: function(strProgArea, strLocFilter, strType)
    {
      var strReq = g_strProgFilterPath;
      
      strReq += "/f/location_id/" + strLocFilter;
      strReq += "/f/program_type/" + strType;
      strReq += "/f/program_area/" + strProgArea;
      strReq += ".json";
      
      // Start by getting the user location      
      $.getJSON(strReq, {},
        function(resp) {
          if (resp) 
          {
            var divList = $("div#similar_progs_list");
            
            if (divList && resp.results)
            {
              var strHTML = '<div class="componentTitle">'
                + '<div class="campusIconWrapper"><a href="#" name="similarProgList_campusIcon"><div class="campusIcon">&nbsp;</div>'
                + '<div class="programFinderToolTip campusTooltip">Campus</div>'
                + '<div class="programFinderToolTipBot campusToolTipBot">&nbsp;</div></a></div>'
                + '<div class="onlineIconWrapper"><a href="#" name="similarProgList_onlineIcon"><div class="onlineIcon">&nbsp;</div>'
                + '<div class="programFinderToolTip onlineTooltip">Online</div>'
                + '<div class="programFinderToolTipBot onlineToolTipBot">&nbsp;</div></a></div>'
                + '<h3>Programs</h3>'
                + '</div>\n';
              
              strHTML += "<table class='programLists'>";
              var iArea;
              
              for (iArea = 0; iArea < resp.results.length; iArea++)
              {
                var area = resp.results[iArea];
                var iLevel;
                
                if (!area.program_levels)
                  continue;
                
                for (iLevel = 0; iLevel < area.program_levels.length; iLevel++)
                {
                  var level = area.program_levels[iLevel];
                  var iProg;
                  
                  if (!level.program_vers)
                    continue;
                
                  for (iProg = 0; iProg < level.program_vers.length; iProg++)
                  {
                    var prog = level.program_vers[iProg];
                    var liClass = "";
                    
                    // Figure out the class                    
                    if (prog.campus == "true") 
                      liClass += "campus";
                    if (prog.online == "true") 
                      liClass += "online";

                    strHTML += '<tr><td><a href="' + prog.ref + '.html">' + prog.title + '&nbsp;&#187;</a></td>';
                    strHTML += '<td class="locationCell';
                    if (prog.online == "true")
                      strHTML += ' locationExistCell';
                    strHTML += '"></td><td class="locationCell';
                    if (prog.campus == "true") 
                      strHTML += ' locationExistCell';
                    strHTML += '"></td></tr>\n';
                  }
                }
              }
              strHTML += "</table>";
              divList.html(strHTML);
        // call again to pick up similar programs table for adding CSS hook classes
        COMMON_table.init();
            }
          }
        }
      );
    }
  };
}();  

/*
 * component_program_version_page JS
 * @author Engineering
 * @fileoverview
 * 
 * Javascript for program version page component
 *
 */
 
/*
 * program version javascript code
 * @class pvCourseList
 */ 

var programVersionPage = function () {
  /*
   * local variables
   */     
  return {
    init: function () {
    }
  };
}();  

/*
 * site_search JS
 * @author Engineering
 * @fileoverview
 * 
 * Javascript for site_search component
 *
 */

 
/*
 * site search code
 * @class siteSearch
 */ 
var strSearchMetaPath;
var aCategoryOpts = [];


var searchResults = function () {
  /*
   * local variables
   */
  var cachedElements = {
      resultsContainer: null,
      resultsPaginator: null
    };

    var defaultInputValue;
    var messagingDisplayed = false;
    var strSolrSearchUrl;
    var strSolrSuggestUrl;
    var aCategoryDefs;
    var iNumResPerPage = 10;
    var iMaxNumPages = 20;
    var mDialogProps;
    var aPrevTerms = new Array();
    var strUserOrga = "";
    var strUserState = "";
    var strUserPostalCode = "";
    var submitClicked = false;
    var bSortPopularity = false;
    var reQry = /\&q\=([^\&]*)\&?/;
  

  return {
    init: function (numResPerPage, numPages, solrSearchUrl, categoryDefs, strQuery, sortPopularity) {
      iNumResPerPage = numResPerPage;
      iMaxNumPages = numPages;
      strSolrSearchUrl = solrSearchUrl;
      aCategoryDefs = categoryDefs;
      bSortPopularity = sortPopularity;
      
      searchResults.cacheFormElements();
      searchResults.bindEvents();
      searchResults.runQuery(strQuery, 0);
    },
    /*
     * adds events to various search form elements
     * 
     * What it does:
     *    bind 'focus' event to search field -- removes failure class if currently applied and sets value of field to blank. bind 'blur' event to search field -- if 
     *    the search field doesn't contain a value, replace the default input text. bind 'keydown' event to search field -- if there is error messaging behind displayed,
     *    clear the field, remove failure class if currently applied and set messaging flag to false. bind 'mouseover/out' events to submit button -- if the submit button 
     *    src contains '_off', replace with '_on' and vice versa. bind 'submit' event to form -- catch the submit event and check to see if the search field has a valid 
     *    entry (ie, not blank, not the default text, not error messaging). If not, display error messaging. If so, perform the submit actions
     * 
     */         
    bindEvents: function () {
    },
    /*
     * store DOM elements in local variables
     * 
     * What it does:
     *    gather various form elements in local variables
     * 
     */       
    cacheFormElements: function () {
      cachedElements.resultsContainer = $('div#apts_search_page_frame');
      cachedElements.resultsPaginator = $('div#apts_search_page_paginator');
    },
    /*
     * performs the query
     * 
     * What it does:
     *    calls the solr search and formats the results 
     * 
     */         
    runQuery: function (strSearchQry, iCurrPage) {
      var strRequest = strSolrSearchUrl + "/?wt=json&json.wrf=?&jsoncallback=?&" + strSearchQry;
      
      if (bSortPopularity)
        strRequest += "&sort=page_views desc";
      
      if (!iNumResPerPage)
        iNumResPerPage = 0;
        
      var iAdjNumResPerPage = iNumResPerPage;
      var iStartRow = (iCurrPage*iNumResPerPage);
      
      if (iCurrPage == 0)
        iAdjNumResPerPage += 3;
      else
        iStartRow += 3;
      
      strRequest += "&rows=" + iAdjNumResPerPage + "&start=" + iStartRow;
      
      $.getJSON(strRequest, {},
        function(resp) {
          var iDoc;
          var iStartDoc = 0;
          var docs = resp.response.docs;

          // Start with the top results -- only do this if it's the first page.
          if (iCurrPage == 0)
          {
            if (docs.length > 0)
              searchResults.addTopResult(docs[0], "apts_res_top_1");
            if (docs.length > 1)
              searchResults.addTopResult(docs[1], "apts_res_top_2");
            if (docs.length > 2)
              searchResults.addTopResult(docs[2], "apts_res_top_3");
         
            iStartDoc = 3;
          }
          // Set the text for the result count
          var totalCount = $("#apts_total_count");
          
          
          // Parse out the query term
          var matchQry = reQry.exec(strSearchQry);
          var strQryTerm = null;
          
          if ((matchQry != null) && (matchQry.length == 2))
            strQryTerm = matchQry[1];
          var strCountHtml = resp.response.numFound + " Results";
          
          if (strQryTerm != null)
            strCountHtml += " for " + strQryTerm;
            
          totalCount.html(strCountHtml);

          var strHtml = "<ul>";
          
          // Clean up the old query      
          strSearchQry = strSearchQry.replace(/\"/g, "%22");
          
          for (iDoc = iStartDoc; iDoc < docs.length; iDoc++)
          {
            var doc = docs[iDoc];
            var strBlurb = doc.blurb;
            
            if (strBlurb.length > 128)
              strBlurb = strBlurb.substring(0, 128) + "...";

            // Figure out the similar link
            var strSimilarQry = strSearchQry;
            var strSimilarText = null;
            
            if (strSearchQry.indexOf("fq=category") < 0)
            {
              strSimilarQry += "&fq=category:%22" + escape(escape(doc.category)) + "%22";
              strSimilarText = "Similar " + doc.category + "&nbsp;&#187;";
            }
            /*else if (strSearchQry.indexOf("fq=subcategory") < 0)
            {
              strSimilarQry += "&fq=subcategory:%22" + doc.subcategory + "%22";
              strSimilarText = "Similar " + doc.subcategory + "&nbsp;&#187;";
            }*/
            
            strHtml += '<li>';
            if (strSimilarText != null)
              strHtml += "<div class='similarLink'><a href=\"javascript: searchResults.runQuery('" + strSimilarQry + "',0)\">" + strSimilarText + "</a></div>";
            strHtml += "<div class='resultContent'><a href='" + doc.url + ".html'>" + doc.title + "&nbsp;&#187;</a><p>" + strBlurb + "</p></div>";
            strHtml += "</li>";
          }        
          cachedElements.resultsContainer.html(strHtml);
          
          // Do pagination
          var iNumPages = Math.floor(parseInt(resp.response.numFound - 3) / iNumResPerPage);
          var iPage = 0;
          var strPageHtml = "<ul>";

          if (iCurrPage > 0)
            strPageHtml += "<li><a href=\"javascript: searchResults.runQuery('" + strSearchQry + "'," + (iCurrPage - 1) + ")\">Previous</a></li>";
          else
            strPageHtml += "<li class='apts_paginate_item_disabled'>Previous</li>";

          var iHalfNumPages = iMaxNumPages / 2;
          var iBottomLimit = iCurrPage - iHalfNumPages;

          if (iBottomLimit < 0)
            iBottomLimit = 0;

          var iUpperLimit = iBottomLimit + iMaxNumPages;

          if (iUpperLimit > iNumPages)
            iUpperLimit = iNumPages;

          for (iPage = iBottomLimit; iPage <= iUpperLimit; iPage++)
          {
            if (iPage != iCurrPage)
              strPageHtml += "<li><a href=\"javascript: searchResults.runQuery('" + strSearchQry + "'," + iPage + ")\">" + (iPage + 1) + "</a></li>";
            else          
              strPageHtml += "<li class='current'>" + (iPage + 1) + "</li>";
          }
          if (iCurrPage < iNumPages)
            strPageHtml += "<li><a href=\"javascript: searchResults.runQuery('" + strSearchQry + "'," + (iCurrPage + 1) + ")\">Next</a></li>";
           
          strPageHtml += "</ul>";
          cachedElements.resultsPaginator.html(strPageHtml);
          // Need to do this to fix layout issues in IE6-7
          $('.footerTab_1').css('display', 'none');
          $('.footerTab_1').css('display', 'block');
          
        }
      );
    },
    /*
     * Populates one of the top results items
     * 
     * What it does:
     *    fills one of the top results divs with content from doc
     * 
     */         
    addTopResult: function (doc, div) {
      var strBlurb = doc.blurb;

      if (strBlurb.length > 128)
        strBlurb = strBlurb.substring(0, 128) + "...";

      var strHtml = "<h4><a href='" + doc.url + ".html'>" + doc.title + "&nbsp;&#187;</a></h4><p>" + strBlurb + "</p>";

      $("#" + div).html(strHtml);
    }
  };
}();  

/* 
 * flowplayer.js 3.1.4. The Flowplayer API
 * 
 * Copyright 2009 Flowplayer Oy
 * 
 * This file is part of Flowplayer.
 * 
 * Flowplayer 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 3 of the License, or
 * (at your option) any later version.
 * 
 * Flowplayer is distributed in the hope that it will be useful,
 * but 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 Flowplayer.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Date: 2009-02-25 21:24:29 +0000 (Wed, 25 Feb 2009)
 * Revision: 166 
 */
(function(){function g(o){console.log("$f.fireEvent",[].slice.call(o))}function k(q){if(!q||typeof q!="object"){return q}var o=new q.constructor();for(var p in q){if(q.hasOwnProperty(p)){o[p]=k(q[p])}}return o}function m(t,q){if(!t){return}var o,p=0,r=t.length;if(r===undefined){for(o in t){if(q.call(t[o],o,t[o])===false){break}}}else{for(var s=t[0];p<r&&q.call(s,p,s)!==false;s=t[++p]){}}return t}function c(o){return document.getElementById(o)}function i(q,p,o){if(typeof p!="object"){return q}if(q&&p){m(p,function(r,s){if(!o||typeof s!="function"){q[r]=s}})}return q}function n(s){var q=s.indexOf(".");if(q!=-1){var p=s.substring(0,q)||"*";var o=s.substring(q+1,s.length);var r=[];m(document.getElementsByTagName(p),function(){if(this.className&&this.className.indexOf(o)!=-1){r.push(this)}});return r}}function f(o){o=o||window.event;if(o.preventDefault){o.stopPropagation();o.preventDefault()}else{o.returnValue=false;o.cancelBubble=true}return false}function j(q,o,p){q[o]=q[o]||[];q[o].push(p)}function e(){return"_"+(""+Math.random()).substring(2,10)}var h=function(t,r,s){var q=this;var p={};var u={};q.index=r;if(typeof t=="string"){t={url:t}}i(this,t,true);m(("Begin*,Start,Pause*,Resume*,Seek*,Stop*,Finish*,LastSecond,Update,BufferFull,BufferEmpty,BufferStop").split(","),function(){var v="on"+this;if(v.indexOf("*")!=-1){v=v.substring(0,v.length-1);var w="onBefore"+v.substring(2);q[w]=function(x){j(u,w,x);return q}}q[v]=function(x){j(u,v,x);return q};if(r==-1){if(q[w]){s[w]=q[w]}if(q[v]){s[v]=q[v]}}});i(this,{onCuepoint:function(x,w){if(arguments.length==1){p.embedded=[null,x];return q}if(typeof x=="number"){x=[x]}var v=e();p[v]=[x,w];if(s.isLoaded()){s._api().fp_addCuepoints(x,r,v)}return q},update:function(w){i(q,w);if(s.isLoaded()){s._api().fp_updateClip(w,r)}var v=s.getConfig();var x=(r==-1)?v.clip:v.playlist[r];i(x,w,true)},_fireEvent:function(v,y,w,A){if(v=="onLoad"){m(p,function(B,C){if(C[0]){s._api().fp_addCuepoints(C[0],r,B)}});return false}A=A||q;if(v=="onCuepoint"){var z=p[y];if(z){return z[1].call(s,A,w)}}if(y&&"onBeforeBegin,onMetaData,onStart,onUpdate,onResume".indexOf(v)!=-1){i(A,y);if(y.metaData){if(!A.duration){A.duration=y.metaData.duration}else{A.fullDuration=y.metaData.duration}}}var x=true;m(u[v],function(){x=this.call(s,A,y,w)});return x}});if(t.onCuepoint){var o=t.onCuepoint;q.onCuepoint.apply(q,typeof o=="function"?[o]:o);delete t.onCuepoint}m(t,function(v,w){if(typeof w=="function"){j(u,v,w);delete t[v]}});if(r==-1){s.onCuepoint=this.onCuepoint}};var l=function(p,r,q,t){var s={};var o=this;var u=false;if(t){i(s,t)}m(r,function(v,w){if(typeof w=="function"){s[v]=w;delete r[v]}});i(this,{animate:function(y,z,x){if(!y){return o}if(typeof z=="function"){x=z;z=500}if(typeof y=="string"){var w=y;y={};y[w]=z;z=500}if(x){var v=e();s[v]=x}if(z===undefined){z=500}r=q._api().fp_animate(p,y,z,v);return o},css:function(w,x){if(x!==undefined){var v={};v[w]=x;w=v}r=q._api().fp_css(p,w);i(o,r);return o},show:function(){this.display="block";q._api().fp_showPlugin(p);return o},hide:function(){this.display="none";q._api().fp_hidePlugin(p);return o},toggle:function(){this.display=q._api().fp_togglePlugin(p);return o},fadeTo:function(y,x,w){if(typeof x=="function"){w=x;x=500}if(w){var v=e();s[v]=w}this.display=q._api().fp_fadeTo(p,y,x,v);this.opacity=y;return o},fadeIn:function(w,v){return o.fadeTo(1,w,v)},fadeOut:function(w,v){return o.fadeTo(0,w,v)},getName:function(){return p},getPlayer:function(){return q},_fireEvent:function(w,v,x){if(w=="onUpdate"){var y=q._api().fp_getPlugin(p);if(!y){return}i(o,y);delete o.methods;if(!u){m(y.methods,function(){var A=""+this;o[A]=function(){var B=[].slice.call(arguments);var C=q._api().fp_invoke(p,A,B);return C==="undefined"||C===undefined?o:C}});u=true}}var z=s[w];if(z){z.apply(o,v);if(w.substring(0,1)=="_"){delete s[w]}}}})};function b(o,t,z){var E=this,y=null,x,u,p=[],s={},B={},r,v,w,D,A,q;i(E,{id:function(){return r},isLoaded:function(){return(y!==null)},getParent:function(){return o},hide:function(F){if(F){o.style.height="0px"}if(y){y.style.height="0px"}return E},show:function(){o.style.height=q+"px";if(y){y.style.height=A+"px"}return E},isHidden:function(){return y&&parseInt(y.style.height,10)===0},load:function(F){if(!y&&E._fireEvent("onBeforeLoad")!==false){m(a,function(){this.unload()});x=o.innerHTML;if(x&&!flashembed.isSupported(t.version)){o.innerHTML=""}flashembed(o,t,{config:z});if(F){F.cached=true;j(B,"onLoad",F)}}return E},unload:function(){if(x.replace(/\s/g,"")!==""){if(E._fireEvent("onBeforeUnload")===false){return E}try{if(y){y.fp_close();E._fireEvent("onUnload")}}catch(F){}y=null;o.innerHTML=x}return E},getClip:function(F){if(F===undefined){F=D}return p[F]},getCommonClip:function(){return u},getPlaylist:function(){return p},getPlugin:function(F){var H=s[F];if(!H&&E.isLoaded()){var G=E._api().fp_getPlugin(F);if(G){H=new l(F,G,E);s[F]=H}}return H},getScreen:function(){return E.getPlugin("screen")},getControls:function(){return E.getPlugin("controls")},getConfig:function(F){return F?k(z):z},getFlashParams:function(){return t},loadPlugin:function(I,H,K,J){if(typeof K=="function"){J=K;K={}}var G=J?e():"_";E._api().fp_loadPlugin(I,H,K,G);var F={};F[G]=J;var L=new l(I,null,E,F);s[I]=L;return L},getState:function(){return y?y.fp_getState():-1},play:function(G,F){function H(){if(G!==undefined){E._api().fp_play(G,F)}else{E._api().fp_play()}}if(y){H()}else{E.load(function(){H()})}return E},getVersion:function(){var G="flowplayer.js 3.1.4";if(y){var F=y.fp_getVersion();F.push(G);return F}return G},_api:function(){if(!y){throw"Flowplayer "+E.id()+" not loaded when calling an API method"}return y},setClip:function(F){E.setPlaylist([F]);return E},getIndex:function(){return w}});m(("Click*,Load*,Unload*,Keypress*,Volume*,Mute*,Unmute*,PlaylistReplace,ClipAdd,Fullscreen*,FullscreenExit,Error,MouseOver,MouseOut").split(","),function(){var F="on"+this;if(F.indexOf("*")!=-1){F=F.substring(0,F.length-1);var G="onBefore"+F.substring(2);E[G]=function(H){j(B,G,H);return E}}E[F]=function(H){j(B,F,H);return E}});m(("pause,resume,mute,unmute,stop,toggle,seek,getStatus,getVolume,setVolume,getTime,isPaused,isPlaying,startBuffering,stopBuffering,isFullscreen,toggleFullscreen,reset,close,setPlaylist,addClip,playFeed").split(","),function(){var F=this;E[F]=function(H,G){if(!y){return E}var I=null;if(H!==undefined&&G!==undefined){I=y["fp_"+F](H,G)}else{I=(H===undefined)?y["fp_"+F]():y["fp_"+F](H)}return I==="undefined"||I===undefined?E:I}});E._fireEvent=function(O){if(typeof O=="string"){O=[O]}var P=O[0],M=O[1],K=O[2],J=O[3],I=0;if(z.debug){g(O)}if(!y&&P=="onLoad"&&M=="player"){y=y||c(v);A=y.clientHeight;m(p,function(){this._fireEvent("onLoad")});m(s,function(Q,R){R._fireEvent("onUpdate")});u._fireEvent("onLoad")}if(P=="onLoad"&&M!="player"){return}if(P=="onError"){if(typeof M=="string"||(typeof M=="number"&&typeof K=="number")){M=K;K=J}}if(P=="onContextMenu"){m(z.contextMenu[M],function(Q,R){R.call(E)});return}if(P=="onPluginEvent"){var F=M.name||M;var G=s[F];if(G){G._fireEvent("onUpdate",M);G._fireEvent(K,O.slice(3))}return}if(P=="onPlaylistReplace"){p=[];var L=0;m(M,function(){p.push(new h(this,L++,E))})}if(P=="onClipAdd"){if(M.isInStream){return}M=new h(M,K,E);p.splice(K,0,M);for(I=K+1;I<p.length;I++){p[I].index++}}var N=true;if(typeof M=="number"&&M<p.length){D=M;var H=p[M];if(H){N=H._fireEvent(P,K,J)}if(!H||N!==false){N=u._fireEvent(P,K,J,H)}}m(B[P],function(){N=this.call(E,M,K);if(this.cached){B[P].splice(I,1)}if(N===false){return false}I++});return N};function C(){if($f(o)){$f(o).getParent().innerHTML="";w=$f(o).getIndex();a[w]=E}else{a.push(E);w=a.length-1}q=parseInt(o.style.height,10)||o.clientHeight;if(typeof t=="string"){t={src:t}}r=o.id||"fp"+e();v=t.id||r+"_api";t.id=v;z.playerId=r;if(typeof z=="string"){z={clip:{url:z}}}if(typeof z.clip=="string"){z.clip={url:z.clip}}z.clip=z.clip||{};if(o.getAttribute("href",2)&&!z.clip.url){z.clip.url=o.getAttribute("href",2)}u=new h(z.clip,-1,E);z.playlist=z.playlist||[z.clip];var F=0;m(z.playlist,function(){var H=this;if(typeof H=="object"&&H.length){H={url:""+H}}m(z.clip,function(I,J){if(J!==undefined&&H[I]===undefined&&typeof J!="function"){H[I]=J}});z.playlist[F]=H;H=new h(H,F,E);p.push(H);F++});m(z,function(H,I){if(typeof I=="function"){if(u[H]){u[H](I)}else{j(B,H,I)}delete z[H]}});m(z.plugins,function(H,I){if(I){s[H]=new l(H,I,E)}});if(!z.plugins||z.plugins.controls===undefined){s.controls=new l("controls",null,E)}s.canvas=new l("canvas",null,E);t.bgcolor=t.bgcolor||"#000000";t.version=t.version||[9,0];t.expressInstall="http://www.flowplayer.org/swf/expressinstall.swf";function G(H){if(!E.isLoaded()&&E._fireEvent("onBeforeClick")!==false){E.load()}return f(H)}x=o.innerHTML;if(x.replace(/\s/g,"")!==""){if(o.addEventListener){o.addEventListener("click",G,false)}else{if(o.attachEvent){o.attachEvent("onclick",G)}}}else{if(o.addEventListener){o.addEventListener("click",f,false)}E.load()}}if(typeof o=="string"){flashembed.domReady(function(){var F=c(o);if(!F){throw"Flowplayer cannot access element: "+o}else{o=F;C()}})}else{C()}}var a=[];function d(o){this.length=o.length;this.each=function(p){m(o,p)};this.size=function(){return o.length}}window.flowplayer=window.$f=function(){var p=null;var o=arguments[0];if(!arguments.length){m(a,function(){if(this.isLoaded()){p=this;return false}});return p||a[0]}if(arguments.length==1){if(typeof o=="number"){return a[o]}else{if(o=="*"){return new d(a)}m(a,function(){if(this.id()==o.id||this.id()==o||this.getParent()==o){p=this;return false}});return p}}if(arguments.length>1){var r=arguments[1];var q=(arguments.length==3)?arguments[2]:{};if(typeof o=="string"){if(o.indexOf(".")!=-1){var t=[];m(n(o),function(){t.push(new b(this,k(r),k(q)))});return new d(t)}else{var s=c(o);return new b(s!==null?s:o,r,q)}}else{if(o){return new b(o,r,q)}}}return null};i(window.$f,{fireEvent:function(){var o=[].slice.call(arguments);var q=$f(o[0]);return q?q._fireEvent(o.slice(1)):null},addPlugin:function(o,p){b.prototype[o]=p;return $f},each:m,extend:i});if(typeof jQuery=="function"){jQuery.prototype.flowplayer=function(q,p){if(!arguments.length||typeof arguments[0]=="number"){var o=[];this.each(function(){var r=$f(this);if(r){o.push(r)}});return arguments.length?o[arguments[0]]:new d(o)}return this.each(function(){$f(this,k(q),p?k(p):{})})}}})();(function(){var e=typeof jQuery=="function";var i={width:"100%",height:"100%",allowfullscreen:true,allowscriptaccess:"always",quality:"high",version:null,onFail:null,expressInstall:null,w3c:false,cachebusting:false};if(e){jQuery.tools=jQuery.tools||{};jQuery.tools.flashembed={version:"1.0.4",conf:i}}function j(){if(c.done){return false}var l=document;if(l&&l.getElementsByTagName&&l.getElementById&&l.body){clearInterval(c.timer);c.timer=null;for(var k=0;k<c.ready.length;k++){c.ready[k].call()}c.ready=null;c.done=true}}var c=e?jQuery:function(k){if(c.done){return k()}if(c.timer){c.ready.push(k)}else{c.ready=[k];c.timer=setInterval(j,13)}};function f(l,k){if(k){for(key in k){if(k.hasOwnProperty(key)){l[key]=k[key]}}}return l}function g(k){switch(h(k)){case"string":k=k.replace(new RegExp('(["\\\\])',"g"),"\\$1");k=k.replace(/^\s?(\d+)%/,"$1pct");return'"'+k+'"';case"array":return"["+b(k,function(n){return g(n)}).join(",")+"]";case"function":return'"function()"';case"object":var l=[];for(var m in k){if(k.hasOwnProperty(m)){l.push('"'+m+'":'+g(k[m]))}}return"{"+l.join(",")+"}"}return String(k).replace(/\s/g," ").replace(/\'/g,'"')}function h(l){if(l===null||l===undefined){return false}var k=typeof l;return(k=="object"&&l.push)?"array":k}if(window.attachEvent){window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){}})}function b(k,n){var m=[];for(var l in k){if(k.hasOwnProperty(l)){m[l]=n(k[l])}}return m}function a(r,t){var q=f({},r);var s=document.all;var n='<object width="'+q.width+'" height="'+q.height+'"';if(s&&!q.id){q.id="_"+(""+Math.random()).substring(9)}if(q.id){n+=' id="'+q.id+'"'}if(q.cachebusting){q.src+=((q.src.indexOf("?")!=-1?"&":"?")+Math.random())}if(q.w3c||!s){n+=' data="'+q.src+'" type="application/x-shockwave-flash"'}else{n+=' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'}n+=">";if(q.w3c||s){n+='<param name="movie" value="'+q.src+'" />'}q.width=q.height=q.id=q.w3c=q.src=null;for(var l in q){if(q[l]!==null){n+='<param name="'+l+'" value="'+q[l]+'" />'}}var o="";if(t){for(var m in t){if(t[m]!==null){o+=m+"="+(typeof t[m]=="object"?g(t[m]):t[m])+"&"}}o=o.substring(0,o.length-1);n+='<param name="flashvars" value=\''+o+"' />"}n+="</object>";return n}function d(m,p,l){var k=flashembed.getVersion();f(this,{getContainer:function(){return m},getConf:function(){return p},getVersion:function(){return k},getFlashvars:function(){return l},getApi:function(){return m.firstChild},getHTML:function(){return a(p,l)}});var q=p.version;var r=p.expressInstall;var o=!q||flashembed.isSupported(q);if(o){p.onFail=p.version=p.expressInstall=null;m.innerHTML=a(p,l)}else{if(q&&r&&flashembed.isSupported([6,65])){f(p,{src:r});l={MMredirectURL:location.href,MMplayerType:"PlugIn",MMdoctitle:document.title};m.innerHTML=a(p,l)}else{if(m.innerHTML.replace(/\s/g,"")!==""){}else{
	
	m.innerHTML="<p>Flash version " + q + " or greater is required. " +
	(k[0]>0 ? "Your version is " + k + "<br>" : "You have no flash plugin installed.<br>") 
	+ (m.tagName=="A" ? "Click here to download the latest version.</p>" : "Download latest version from <a href='http://www.adobe.com/go/getflashplayer'>here.</a></p>");
	
	
	if(m.tagName=="A"){m.onclick=function(){window.open('http://www.adobe.com/go/getflashplayer')}
	
	}}}}if(!o&&p.onFail){var n=p.onFail.call(this);if(typeof n=="string"){m.innerHTML=n}}if(document.all){window[p.id]=document.getElementById(p.id)}}window.flashembed=function(l,m,k){if(typeof l=="string"){var n=document.getElementById(l);if(n){l=n}else{c(function(){flashembed(l,m,k)});return}}if(!l){return}if(typeof m=="string"){m={src:m}}var o=f({},i);f(o,m);return new d(l,o,k)};f(window.flashembed,{getVersion:function(){var m=[0,0];if(navigator.plugins&&typeof navigator.plugins["Shockwave Flash"]=="object"){var l=navigator.plugins["Shockwave Flash"].description;if(typeof l!="undefined"){l=l.replace(/^.*\s+(\S+\s+\S+$)/,"$1");var n=parseInt(l.replace(/^(.*)\..*$/,"$1"),10);var r=/r/.test(l)?parseInt(l.replace(/^.*r(.*)$/,"$1"),10):0;m=[n,r]}}else{if(window.ActiveXObject){try{var p=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7")}catch(q){try{p=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");m=[6,0];p.AllowScriptAccess="always"}catch(k){if(m[0]==6){return m}}try{p=new ActiveXObject("ShockwaveFlash.ShockwaveFlash")}catch(o){}}if(typeof p=="object"){l=p.GetVariable("$version");if(typeof l!="undefined"){l=l.replace(/^\S+\s+(.*)$/,"$1").split(",");m=[parseInt(l[0],10),parseInt(l[2],10)]}}}}return m},isSupported:function(k){var m=flashembed.getVersion();var l=(m[0]>k[0])||(m[0]==k[0]&&m[1]>=k[1]);return l},domReady:c,asString:g,getHTML:a});if(e){jQuery.fn.flashembed=function(l,k){var m=null;this.each(function(){m=flashembed(this,l,k)});return l.api===false?this:m}}})();// ===================================================================
// Author: Matt Kruse <matt@mattkruse.com>
// WWW: http://www.mattkruse.com/
//
// NOTICE: You may use this code for any purpose, commercial or
// private, without any further permission from the author. You may
// remove this notice from your final code if you wish, however it is
// appreciated by the author if at least my web site address is kept.
//
// You may *NOT* re-distribute this code in any way except through its
// use. That means, you can include it in your product, or your web
// site, or any other form where the code is actually being used. You
// may not put the plain javascript up on your site for download or
// include it in your javascript libraries for download. 
// If you wish to share this code with others, please just point them
// to the URL instead.
// Please DO NOT link directly to my .js files from your site. Copy
// the files to your server and use them there. Thank you.
// ===================================================================

// HISTORY
// ------------------------------------------------------------------
// May 17, 2003: Fixed bug in parseDate() for dates <1970
// March 11, 2003: Added parseDate() function
// March 11, 2003: Added "NNN" formatting option. Doesn't match up
//                 perfectly with SimpleDateFormat formats, but 
//                 backwards-compatability was required.

// ------------------------------------------------------------------
// These functions use the same 'format' strings as the 
// java.text.SimpleDateFormat class, with minor exceptions.
// The format string consists of the following abbreviations:
// 
// Field        | Full Form          | Short Form
// -------------+--------------------+-----------------------
// Year         | yyyy (4 digits)    | yy (2 digits), y (2 or 4 digits)
// Month        | MMM (name or abbr.)| MM (2 digits), M (1 or 2 digits)
//              | NNN (abbr.)        |
// Day of Month | dd (2 digits)      | d (1 or 2 digits)
// Day of Week  | EE (name)          | E (abbr)
// Hour (1-12)  | hh (2 digits)      | h (1 or 2 digits)
// Hour (0-23)  | HH (2 digits)      | H (1 or 2 digits)
// Hour (0-11)  | KK (2 digits)      | K (1 or 2 digits)
// Hour (1-24)  | kk (2 digits)      | k (1 or 2 digits)
// Minute       | mm (2 digits)      | m (1 or 2 digits)
// Second       | ss (2 digits)      | s (1 or 2 digits)
// AM/PM        | a                  |
//
// NOTE THE DIFFERENCE BETWEEN MM and mm! Month=MM, not mm!
// Examples:
//  "MMM d, y" matches: January 01, 2000
//                      Dec 1, 1900
//                      Nov 20, 00
//  "M/d/yy"   matches: 01/20/00
//                      9/2/00
//  "MMM dd, yyyy hh:mm:ssa" matches: "January 01, 2000 12:30:45AM"
// ------------------------------------------------------------------

var MONTH_NAMES=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
var DAY_NAMES=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat');
function LZ(x) {return(x<0||x>9?"":"0")+x}

// ------------------------------------------------------------------
// isDate ( date_string, format_string )
// Returns true if date string matches format of format string and
// is a valid date. Else returns false.
// It is recommended that you trim whitespace around the value before
// passing it to this function, as whitespace is NOT ignored!
// ------------------------------------------------------------------
function isDate(val,format) {
	var date=getDateFromFormat(val,format);
	if (date==0) { return false; }
	return true;
	}

// -------------------------------------------------------------------
// compareDates(date1,date1format,date2,date2format)
//   Compare two date strings to see which is greater.
//   Returns:
//   1 if date1 is greater than date2
//   0 if date2 is greater than date1 of if they are the same
//  -1 if either of the dates is in an invalid format
// -------------------------------------------------------------------
function compareDates(date1,dateformat1,date2,dateformat2) {
	var d1=getDateFromFormat(date1,dateformat1);
	var d2=getDateFromFormat(date2,dateformat2);
	if (d1==0 || d2==0) {
		return -1;
		}
	else if (d1 > d2) {
		return 1;
		}
	return 0;
	}

// ------------------------------------------------------------------
// formatDate (date_object, format)
// Returns a date in the output format specified.
// The format string uses the same abbreviations as in getDateFromFormat()
// ------------------------------------------------------------------
function formatDate(date,format) {
	format=format+"";
	var result="";
	var i_format=0;
	var c="";
	var token="";
	var y=date.getYear()+"";
	var M=date.getMonth()+1;
	var d=date.getDate();
	var E=date.getDay();
	var H=date.getHours();
	var m=date.getMinutes();
	var s=date.getSeconds();
	var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;
	// Convert real date parts into formatted versions
	var value=new Object();
	if (y.length < 4) {y=""+(y-0+1900);}
	value["y"]=""+y;
	value["yyyy"]=y;
	value["yy"]=y.substring(2,4);
	value["M"]=M;
	value["MM"]=LZ(M);
	value["MMM"]=MONTH_NAMES[M-1];
	value["NNN"]=MONTH_NAMES[M+11];
	value["d"]=d;
	value["dd"]=LZ(d);
	value["E"]=DAY_NAMES[E+7];
	value["EE"]=DAY_NAMES[E];
	value["H"]=H;
	value["HH"]=LZ(H);
	if (H==0){value["h"]=12;}
	else if (H>12){value["h"]=H-12;}
	else {value["h"]=H;}
	value["hh"]=LZ(value["h"]);
	if (H>11){value["K"]=H-12;} else {value["K"]=H;}
	value["k"]=H+1;
	value["KK"]=LZ(value["K"]);
	value["kk"]=LZ(value["k"]);
	if (H > 11) { value["a"]="PM"; }
	else { value["a"]="AM"; }
	value["m"]=m;
	value["mm"]=LZ(m);
	value["s"]=s;
	value["ss"]=LZ(s);
	while (i_format < format.length) {
		c=format.charAt(i_format);
		token="";
		while ((format.charAt(i_format)==c) && (i_format < format.length)) {
			token += format.charAt(i_format++);
			}
		if (value[token] != null) { result=result + value[token]; }
		else { result=result + token; }
		}
	return result;
	}
	
// ------------------------------------------------------------------
// Utility functions for parsing in getDateFromFormat()
// ------------------------------------------------------------------
function _isInteger(val) {
	var digits="1234567890";
	for (var i=0; i < val.length; i++) {
		if (digits.indexOf(val.charAt(i))==-1) { return false; }
		}
	return true;
	}
function _getInt(str,i,minlength,maxlength) {
	for (var x=maxlength; x>=minlength; x--) {
		var token=str.substring(i,i+x);
		if (token.length < minlength) { return null; }
		if (_isInteger(token)) { return token; }
		}
	return null;
	}
	
// ------------------------------------------------------------------
// getDateFromFormat( date_string , format_string )
//
// This function takes a date string and a format string. It matches
// If the date string matches the format string, it returns the 
// getTime() of the date. If it does not match, it returns 0.
// ------------------------------------------------------------------
function getDateFromFormat(val,format) {
	val=val+"";
	format=format+"";
	var i_val=0;
	var i_format=0;
	var c="";
	var token="";
	var token2="";
	var x,y;
	var now=new Date();
	var year=now.getYear();
	var month=now.getMonth()+1;
	var date=1;
	var hh=now.getHours();
	var mm=now.getMinutes();
	var ss=now.getSeconds();
	var ampm="";
	
	while (i_format < format.length) {
		// Get next token from format string
		c=format.charAt(i_format);
		token="";
		while ((format.charAt(i_format)==c) && (i_format < format.length)) {
			token += format.charAt(i_format++);
			}
		// Extract contents of value based on format token
		if (token=="yyyy" || token=="yy" || token=="y") {
			if (token=="yyyy") { x=4;y=4; }
			if (token=="yy")   { x=2;y=2; }
			if (token=="y")    { x=2;y=4; }
			year=_getInt(val,i_val,x,y);
			if (year==null) { return 0; }
			i_val += year.length;
			if (year.length==2) {
				if (year > 70) { year=1900+(year-0); }
				else { year=2000+(year-0); }
				}
			}
		else if (token=="MMM"||token=="NNN"){
			month=0;
			for (var i=0; i<MONTH_NAMES.length; i++) {
				var month_name=MONTH_NAMES[i];
				if (val.substring(i_val,i_val+month_name.length).toLowerCase()==month_name.toLowerCase()) {
					if (token=="MMM"||(token=="NNN"&&i>11)) {
						month=i+1;
						if (month>12) { month -= 12; }
						i_val += month_name.length;
						break;
						}
					}
				}
			if ((month < 1)||(month>12)){return 0;}
			}
		else if (token=="EE"||token=="E"){
			for (var i=0; i<DAY_NAMES.length; i++) {
				var day_name=DAY_NAMES[i];
				if (val.substring(i_val,i_val+day_name.length).toLowerCase()==day_name.toLowerCase()) {
					i_val += day_name.length;
					break;
					}
				}
			}
		else if (token=="MM"||token=="M") {
			month=_getInt(val,i_val,token.length,2);
			if(month==null||(month<1)||(month>12)){return 0;}
			i_val+=month.length;}
		else if (token=="dd"||token=="d") {
			date=_getInt(val,i_val,token.length,2);
			if(date==null||(date<1)||(date>31)){return 0;}
			i_val+=date.length;}
		else if (token=="hh"||token=="h") {
			hh=_getInt(val,i_val,token.length,2);
			if(hh==null||(hh<1)||(hh>12)){return 0;}
			i_val+=hh.length;}
		else if (token=="HH"||token=="H") {
			hh=_getInt(val,i_val,token.length,2);
			if(hh==null||(hh<0)||(hh>23)){return 0;}
			i_val+=hh.length;}
		else if (token=="KK"||token=="K") {
			hh=_getInt(val,i_val,token.length,2);
			if(hh==null||(hh<0)||(hh>11)){return 0;}
			i_val+=hh.length;}
		else if (token=="kk"||token=="k") {
			hh=_getInt(val,i_val,token.length,2);
			if(hh==null||(hh<1)||(hh>24)){return 0;}
			i_val+=hh.length;hh--;}
		else if (token=="mm"||token=="m") {
			mm=_getInt(val,i_val,token.length,2);
			if(mm==null||(mm<0)||(mm>59)){return 0;}
			i_val+=mm.length;}
		else if (token=="ss"||token=="s") {
			ss=_getInt(val,i_val,token.length,2);
			if(ss==null||(ss<0)||(ss>59)){return 0;}
			i_val+=ss.length;}
		else if (token=="a") {
			if (val.substring(i_val,i_val+2).toLowerCase()=="am") {ampm="AM";}
			else if (val.substring(i_val,i_val+2).toLowerCase()=="pm") {ampm="PM";}
			else {return 0;}
			i_val+=2;}
		else {
			if (val.substring(i_val,i_val+token.length)!=token) {return 0;}
			else {i_val+=token.length;}
			}
		}
	// If there are any trailing characters left in the value, it doesn't match
	if (i_val != val.length) { return 0; }
	// Is date valid for month?
	if (month==2) {
		// Check for leap year
		if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
			if (date > 29){ return 0; }
			}
		else { if (date > 28) { return 0; } }
		}
	if ((month==4)||(month==6)||(month==9)||(month==11)) {
		if (date > 30) { return 0; }
		}
	// Correct hours value
	if (hh<12 && ampm=="PM") { hh=hh-0+12; }
	else if (hh>11 && ampm=="AM") { hh-=12; }
	var newdate=new Date(year,month-1,date,hh,mm,ss);
	return newdate.getTime();
	}

// ------------------------------------------------------------------
// parseDate( date_string [, prefer_euro_format] )
//
// This function takes a date string and tries to match it to a
// number of possible date formats to get the value. It will try to
// match against the following international formats, in this order:
// y-M-d   MMM d, y   MMM d,y   y-MMM-d   d-MMM-y  MMM d
// M/d/y   M-d-y      M.d.y     MMM-d     M/d      M-d
// d/M/y   d-M-y      d.M.y     d-MMM     d/M      d-M
// A second argument may be passed to instruct the method to search
// for formats like d/M/y (european format) before M/d/y (American).
// Returns a Date object or null if no patterns match.
// ------------------------------------------------------------------
function parseDate(val) {
	var preferEuro=(arguments.length==2)?arguments[1]:false;
	generalFormats=new Array('y-M-d','MMM d, y','MMM d,y','y-MMM-d','d-MMM-y','MMM d');
	monthFirst=new Array('M/d/y','M-d-y','M.d.y','MMM-d','M/d','M-d');
	dateFirst =new Array('d/M/y','d-M-y','d.M.y','d-MMM','d/M','d-M');
	var checkList=new Array('generalFormats',preferEuro?'dateFirst':'monthFirst',preferEuro?'monthFirst':'dateFirst');
	var d=null;
	for (var i=0; i<checkList.length; i++) {
		var l=window[checkList[i]];
		for (var j=0; j<l.length; j++) {
			d=getDateFromFormat(val,l[j]);
			if (d!=0) { return new Date(d); }
			}
		}
	return null;
	}
/** 
 * @fileoverview
 * These functions handle interactions with the ProfileServlet.  In most cases, the function will
 * return either a Profile, Article, Comment object or an error object.
 * <br/>
 * A Profile object consists of:<br/>
 *   <code>{<br/>
 *      email<br/>
 *      alt_email<br/>
 *      first_name<br/>
 *      last_name<br/>
 *      middle_name<br/>
 *      profile_group<br/>
 *      photo_ref<br/>
 *      self_desc<br/>
 *   }</code><br>
 * An Article object consists of:<br/>
 *   <code>{<br/>
 *      header_image_ref<br/>
 *      title<br/>
 *      text<br/>
 *      lead_in_text<br/>
 *      co_author_ref [] </br>
 *      categories [] </br>
 *      campus_ref [] </br>
 *      tags [] </br>
 *   }</code><br>
 * A Comment object consists of:<br/>
 *   <code>{<br/>
 *      title<br/>
 *      text<br/>
 *      commentor_ref<br/>
 *      timestamp<br/>
 *   }</code><br>
 * An Error object consists of:<br/>
 *   <code>{<br/>
 *      error<br/>
 *   }</code><br/>
 * The error will be one of:<ul>
 * <li>"articleNotFound"</li>
 * <li>"invalidPassword"</li>
 * <li>"invalidParameters"</li>
 * <li>"javaException"</li>
 * <li>"profileNotFound"</li>
 * <li>"profileAlreadyExists"</li>
 * <li>"userNotAuthenticated"</li>
 * </ul>
 * If the error is "javaException", another member of the returned JSON will be available that 
 * describes the exception.  It is identified by the Exception member and consists of:<code><ul>
 * <li>Exception
 * <ul>
 *    <li>Message</li>
 *    <li>stack_trace
 *    <ul>
 *      <li>file</li>
 *      <li>line</li>
 *      <li>class</li>
 *      <li>method</li>
 *    </ul></li>
 * </ul></li>
 **/
/**
 * This function checks to see if a user is currently logged in.
 * 
 * @return                      Returns true if the user has been authenticated; 
 *                              false if they weren't or there was an error.
 **/
function isAuthenticated()
{
  var ret = false;
  var json = runProfileRequest("authenticated", null, null);

  if (json.error == null)
  {
    if (json.authenticated == "true")
      ret = true;
  }

  return ret;
}
/**
 * This function checks to see if a profile exists.
 * 
 * @param strEmail              Email of user to check.
 * @return                      Returns true if the user exists; false if they don't or there was an error.
 **/
function profileExistsByEmail(strEmail)
{
  var ret = false;
  var json = runProfileRequest("exists_by_email", "email=" + strEmail, null);

  if (json.error == null)
  {
    if (json.exists == "true")
      ret = true;
  }
  return ret;
}
/**
 * This function checks to see if a profile exists by screen name.
 * 
 * @param strScreenName         Screen name of user to check.
 * @return                      Returns true if the user exists; false if they don't or there was an error.
 **/
function profileExistsByScreenName(strScreenName)
{
  var ret = false;
  var json = runProfileRequest("exists_by_screen_name", "screen_name=" + strScreenName, null);

  if (json.error == null)
  {
    if (json.exists == "true")
      ret = true;
  }
  return ret;
}
/**
 * This function checks to see if a profile exists by screen name and email address.
 * 
 * @param strScreenName         Screen name of user to check.
 * @param strEmail              Email of user to check.
 * @return                      Returns true if the user exists; false if they don't or there was an error.
 **/
function profileExists(strScreenName, strEmail)
{
  var ret = false;
  var json = runProfileRequest("exists", "screen_name=" + strScreenName + "&email=" + strEmail, null);

  if (json.error == null)
  {
    if (json.exists == "true")
      ret = true;
  }
  return ret;
}
/**
 * This function attempts to log the user in using the supplied credentials.
 * 
 * @param strEmail              Email of user.
 * @param strPassword           User password.
 * @param fnCallback            Function to call when the request completes.  If null, the request
 *                              is run synchronously.  Callback function should take 1 parameter; the parsed
 *                              JSON result.  It will either be a profile object or an error object.
 * @return                      Returns either a profile object or an error object.
 **/
function authenticateUser(strEmail, strPassword, fnCallback)
{
  var json = runProfileRequest("login", "email=" + strEmail + "&pw=" + strPassword, fnCallback);

  return json;  
}
/**
 * This function creates a "public" (non-faculty/non-student/non-alumni) profile and starts the 
 * workflow approval process.  Note that when a profile is added, the user is automatically logged in.
 * 
 * @param strScreenName         Screen name of user.
 * @param strEmail              Email of user.
 * @param strPassword           User password.
 * @param strPostalCode         Postal code (zip) of the new user.
 * @param strProfileGroup       Profile group (public, faculty, student, or alumni)
 * @param strAlternateEmail   Alternative email address.
 * @param strFirstName          First name.
 * @param strLastName           Last name.
 * @param strMiddleName         Middle name.
 * @param strPhotoRef           Reference (path) to photo.
 * @param strSelfDescription    Description of self.
 * @param fnCallback            Function to call when the request completes.  If null, the request
 *                              is run synchronously.  Callback function should take 1 parameter; the parsed
 *                              JSON result.  It will either be a profile object or an error object.
 * @return                      Returns either a profile object or an error object.
 **/
function addProfile(strScreenName,
                    strEmail, 
                    strPassword, 
                    strPostalCode, 
                    strProfileGroup, 
                    strAlternateEmail,
                    strFirstName,
                    strLastName,
                    strMiddleName,
                    strPhotoRef,
                    strSelfDescription,
                    fnCallback)
{
  var params =  "screen_name=" + strScreenName +
  "&email=" + strEmail 
              + "&pw=" + strPassword 
              + "&postal_code=" + strPostalCode 
              + "&profile_group=" + strProfileGroup;
              
  if (strAlternateEmail != null)
    params += "&alt_email=" + strAlternateEmail;
  if (strFirstName != null)
    params += "&first_name=" + strFirstName;
  if (strLastName != null)
    params += "&last_name=" + strLastName;
  if (strMiddleName != null)
    params += "&middle_name=" + strMiddleName;
  if (strPhotoRef != null)
    params += "&photo_ref=" + strPhotoRef;
  if (strSelfDescription != null)
    params += "&self_desc=" + strSelfDescription;
              
  var json = runProfileRequest("add", params, fnCallback);

  return json;  
}
/**
 * This function creates a "public" (non-faculty/non-student/non-alumni) profile and starts the 
 * workflow approval process.
 * 
 * @param strScreenName         Screen name of user.
 * @param strEmail              Email of user.
 * @param strPassword           User password.
 * @param strPostalCode         Postal code (zip) of the new user.
 * @param fnCallback            Function to call when the request completes.  If null, the request
 *                              is run synchronously.  Callback function should take 1 parameter; the parsed
 *                              JSON result.  It will either be a profile object or an error object.
 * @return                      Returns either a profile object or an error object.
 **/
function addPublicProfile(strScreenName, strEmail, strPassword, strPostalCode, fnCallback)
{
  var json = addProfile(strScreenName, strEmail, strPassword, strPostalCode, "public", 
                         null, null, null, null,
                         null, null, fnCallback);

  return json;  
}
/**
 * This function creates a "faculty" profile and starts the workflow approval process.
 * 
 * @param strScreenName         Screen name of user.
 * @param strEmail              Email of user.
 * @param strPassword           User password.
 * @param strPostalCode         Postal code (zip) of the new user.
 * @param fnCallback            Function to call when the request completes.  If null, the request
 *                              is run synchronously.  Callback function should take 1 parameter; the parsed
 *                              JSON result.  It will either be a profile object or an error object.
 * @return                      Returns either a profile object or an error object.
 **/
function addFacultyProfile(strScreenName, strEmail, strPassword, strPostalCode, fnCallback)
{
  var json = addProfile(strScreenName, strEmail, strPassword, strPostalCode, "faculty", 
                         null, null, null, null,
                         null, null, fnCallback);

  return json;  
}
/**
 * This function creates a "student" profile and starts the workflow approval process.
 * 
 * @param strScreenName         Screen name of user.
 * @param strEmail              Email of user.
 * @param strPassword           User password.
 * @param strPostalCode         Postal code (zip) of the new user.
 * @param fnCallback            Function to call when the request completes.  If null, the request
 *                              is run synchronously.  Callback function should take 1 parameter; the parsed
 *                              JSON result.  It will either be a profile object or an error object.
 * @return                      Returns either a profile object or an error object.
 **/
function addStudentProfile(strScreenName, strEmail, strPassword, strPostalCode, fnCallback)
{
  var json = addProfile(strScreenName, strEmail, strPassword, strPostalCode, "students", 
                         null, null, null, null,
                         null, null, fnCallback);


  return json;  
}
/**
 * This function creates an "alumni" profile and starts the workflow approval process.
 * 
 * @param strScreenName         Screen name of user.
 * @param strEmail              Email of user.
 * @param strPassword           User password.
 * @param strPostalCode         Postal code (zip) of the new user.
 * @param fnCallback            Function to call when the request completes.  If null, the request
 *                              is run synchronously.  Callback function should take 1 parameter; the parsed
 *                              JSON result.  It will either be a profile object or an error object.
 * @return                      Returns either a profile object or an error object.
 **/
function addAlumniProfile(strScreenName, strEmail, strPassword, strPostalCode, fnCallback)
{
  var json = addProfile(strScreenName, strEmail, strPassword, strPostalCode, "alumni", 
                         null, null, null, null,
                         null, null, fnCallback);

  return json;  
}
/**
 * This function returns the currently logged in user.
 * 
 * @param fnCallback            Function to call when the request completes.  If null, the request
 *                              is run synchronously.
 * @return                      Returns either a profile object or an error object.
 **/
function getProfile(fnCallback)
{
  var json = runProfileRequest("get", null, fnCallback);

  return json;  
}
/**
 * This function creates an article.
 * 
 * @param strHeaderImageRef     Path to the header image.
 * @param strTitle              Title of the article.
 * @param strText               Text of the article.
 * @param strLeadInText         Lead in text for the article.
 * @param fnCallback            Function to call when the request completes.  If null, the request
 *                              is run synchronously.  Callback function should take 1 parameter; the parsed
 *                              JSON result.  It will either be an article object or an error object.
 * @return                      Returns either a article object or an error object.
 **/
function addArticle(strHeaderImageRef, strTitle, strText, strLeadInText, fnCallback)
{
  var json = runProfileRequest("add_article", 
                "header_image_ref=" + escape(strHeaderImageRef) 
                + "&title=" + escape(strTitle)
                + "&text=" + escape(strText)
                + "&lead_in_text" + escape(strLeadInText), 
                fnCallback)
  return json;  
}
/**
 * This function creates a comment attributed to the currently authenticated user.  If the user is not
 * authenticated, the servlet will reject this request.
 * 
 * @param strArticleRef         Path to the article.
 * @param strTitle              Title of the comment.
 * @param strText               Text of the comment.
 * @param fnCallback            Function to call when the request completes.  If null, the request
 *                              is run synchronously.  Callback function should take 1 parameter; the parsed
 *                              JSON result.  It will either be a comment object or an error object.
 * @return                      Returns either a comment object or an error object.
 **/
function addComment(strArticleRef, strTitle, strText, fnCallback)
{
  var json = runProfileRequest("add_comment", 
                "article_ref=" + escape(strArticleRef) 
                + "&title=" + escape(strTitle) 
                + "&text=" + escape(strText), 
                fnCallback)
  return json;  
}
/**
 * Gets the articles authored by the specified user.
 * 
 * @param strEmail              Email of the author.  If null, articles authored by the currently 
 *                              authenticated user are returned.
 * @param fnCallback            Function to call when the request completes.  If null, the request
 *                              is run synchronously.  Callback function should take 1 parameter; the parsed
 *                              JSON result.  It will either be an array of article objects or an error object.
 * @return                      Returns either an array of article objects or an error object.
 **/
function getArticles(strEmail, fnCallback)
{
  var json = runProfileRequest("get_articles", 
                (strEmail ? ("email=" + strEmail) : null),
                fnCallback)
  return json;  
}
/**
 * Gets the articles using the specified query parameters.
 * 
 * @param strEmail              Email of the author.  If null, articles authored by the currently 
 *                              authenticated user are returned.
 * @param fnCallback            Function to call when the request completes.  If null, the request
 *                              is run synchronously.  Callback function should take 1 parameter; the parsed
 *                              JSON result.  It will either be an array of article objects or an error object.
 * @return                      Returns either an array of article objects or an error object.
 **/
function getArticlesByCriteria(strEmail, astrCategories, astrCampuses, astrTags, fnCallback)
{
  var strParams = "";

  strParams += addArrayParams("category", astrCategories);

  if (strParams.length > 0)
    strParams += "&";
  strParams += addArrayParams("campus", astrCampuses);

  if (strParams.length > 0)
    strParams += "&";
  strParams += addArrayParams("tag", astrTags);
  
  if (strEmail != null)
  {
    if (strParams.length > 0)
      strParams += "&";
    strParams += "email=" + strEmail;
  }
  var json = runProfileRequest("get_articles", strParams, fnCallback);
  return json;  
}
/**
 * Gets the comments for the specified article .
 * 
 * @param strArticleRef         Path to the article whose comments are being requestd.
 * @param fnCallback            Function to call when the request completes.  If null, the request
 *                              is run synchronously.  Callback function should take 1 parameter; the parsed
 *                              JSON result.  It will either be an array of comment objects or an error object.
 * @return                      Returns either an array of comment objects or an error object.
 **/
function getComments(strArticleRef, fnCallback)
{
  var json = runProfileRequest("get_comments", 
                "article_ref=" + strArticleRef,
                fnCallback)
  return json;  
}
/**
 * Adds criteria (categories, campus refs, and/or tags) to an article.  
 * 
 * @param strArticleRef         Path to the article where the criteria will be added.
 * @param straCategories        Array of categories to add or null if none are to be added.
 * @param straCampusRefs        Array of campuses (campii) to add or null if none are to be added.
 * @param straTags              Array of tags to add or null if none are to be added.
 * @param fnCallback            Function to call when the request completes.  If null, the request
 *                              is run synchronously.  Callback function should take 1 parameter; the parsed
 *                              JSON result.  It will either be an article object or an error object.
 * @return                      Returns either an artilce object or an error object.
 **/
function addArticleCriteria(strArticleRef, astrCategories, astrCampusRefs, astrTags, fnCallback)
{
  var strParams = "";
  
  strParams += addArrayParams("category", astrCategories);

  if (strParams.length > 0)
    strParams += "&";
  strParams += addArrayParams("campus", astrCampusRefs);

  if (strParams.length > 0)
    strParams += "&";
  strParams += addArrayParams("tag", astrTags);

  if (strParams.length > 0)
    strParams += "&";
  strParams += "article_ref=" + strArticleRef;
  
  var json = runProfileRequest("add_article_criteria", strParams, fnCallback);
  return json;  
}
/**
 * Executes the comment approval process.  This process will mark "approved" for the list
 * of approved comments and <b>delete</b> the comments in the "disapproval" list.
 * 
 * @param astrApprovals         Array of paths to comments that should be approved.
 * @param astrDisapprovals      Array of paths to comments that should be disapproved (deleted).
 * @param fnCallback            Function to call when the request completes.  If null, the request
 *                              is run synchronously.  Callback function should take 1 parameter; the parsed
 *                              JSON result.  It will either be an array of approved comments or an error object.
 * @return                      Returns either an array of approved comments or an error object.
 **/
function executeCommentApproval(astrApprovals, astrDisapprovals, fnCallback)
{
  var strParams = "";
  
  strParams += addArrayParams("approval", astrApprovals);

  if (strParams.length > 0)
    strParams += "&";
  strParams += addArrayParams("disapproval", astrDisapprovals);

  var json = runProfileRequest("exec_comment_approval", strParams, fnCallback);
  
  return json;
}

/**
 * Internal function to add an array to a list of params.
 * 
 * @param strParamName          Name of the param to add. 
 * @param astrValues            Array of values to add to the request parameters.
 * @return                      Returns a string of parameters or an empty string if the array was empty.
 **/
function addArrayParams(strParamName, astrValues)
{
  var strParams = "";
  
  if (astrValues != null)
  {
    for (idx = 0; idx < astrValues.length; idx++)
    {
      if (strParams.length > 0)
        strParams += "&";
      strParams += strParamName + "=" + astrValues[idx];
    }
  }
  return strParams;
}
/**
 * Internal function used to send a request to the profile servlet.
 * 
 * @param strReqName            Name of the request.
 * @param strParams             String list of parameters in the form: "<name>=<value>&<name1>=<value1>...
 * @param fnCallback            Function to call when the request completes.  If null, the request
 *                              is run synchronously.
 * @return                      Returns true if the user exists; false if they don't or there was an error.
 **/
function runProfileRequest(strReqName, strParams, fnCallback)
{
  var strUrl = "/bin/ac/servlet/ProfileServlet." + strReqName + ".json";
  var xhr = createXHR();
  var bAsync = (fnCallback != null);
  var resp = null;

  if (!strParams)  
    strParams = "";
  xhr.open("POST", strUrl, bAsync);

  //Send the proper header information along with the request
  xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  xhr.setRequestHeader("Content-length", strParams.length);
  xhr.setRequestHeader("Connection", "close");

  if (bAsync)
  {
    xhr.onreadystatechange = function() 
    {
      //Call a function when the state changes.
      if(xhr.readyState == 4) 
      {
        try 
        {
          resp = eval("(" + xhr.responseText + ")");
        }
        catch (error)
        {
          resp = eval("(" + {"error": error} + ")");
        }
    fnCallback(resp);
      }
    }
    xhr.send(strParams);
  }
  else
  {
    xhr.send(strParams);
    
    try 
    {
      resp = eval("(" + xhr.responseText + ")");
    
    }
    catch (error)
    {
      resp = {"error": error};
    }
  }
  return resp;
}

/*
 * default JS
 * @author Engineering
 * @fileoverview
 * 
 * Javascript that is either global or not specific to a component 
 *
 */
 
 
/*
 * default UPX code
 * @class UPX_default
 */ 
 var UPX_default = function () {
	var classes = {
		clearfix: 'clearFix',
		ctaTop: 'cta_top',
		emptyNode: 'emptyNode',
		pullText: 'pullText',
		sansSerifFontStack: 'Calibri, "Trebuchet MS", Helvetica, sans-serif',
		section: 'section', 
		staticMap: 'staticMap'		
	};
	
	return {
		init: function () {
			UPX_default.addClasses();
			UPX_default.transformOLs();
		},
		/*
		 * add any miscellaneous classes needed site-wide
		 * 
		 * What it does:
		 * 		add empty node class to div.section without associated component and parents with class of only "section"
		 * 
		 */			
		addClasses: function () {
			$('div.col_right').find('div:empty').each(function () {
				if ($(this).hasClass(classes.section)) {
					$(this).addClass(classes.emptyNode);
				}

				// exclude elements that are intentionally empty
				if (!$(this).hasClass(classes.clearfix) && !$(this).hasClass(classes.staticMap)) {
					$(this).parents('div[class="section"]').addClass(classes.emptyNode);
				}
			});
			
			$('div[class="colctrl section"]').each(function () {
				$(this).addClass(classes.emptyNode);
			});
			
			//Setting the css to indicate which font is being used
			$('body').fontunstack(classes.sansSerifFontStack);
		},
		/*
		 * update OL list markup for site-wide styling
		 * 
		 * What it does:
		 * 		gather all OLs. For each, append a new empty UL with orderedList class directly after. Iterate through all LI children of OL and
		 *		insert a span with the list item index. Take updated LI and append to new UL. When OL has no children left afterwards, remove the old OL.
		 * 
		 */				
		transformOLs: function () {
			$('ol').each (function () {
				var ol = $(this);
				var result = ol.after('<ul class="orderedList"></ul>');
				if (result) {
					var ul = ol.next();
					var index = 1;
					(ol.children()).each(function () {
						var obj = $(this);
						if(this.tagName.toLowerCase() == "li"){
						  obj.prepend('<span class="listNum">' + index + '</span>');
						  index++;
						}
						ul.append(obj);
					});
					
					ol.remove();					
				}
											
			});
		}
	};
}();
 

$(document).ready(function () {
	/* call altcloud functions */
	UPX_default.init();	
	topNav.init();	
	newsfeed.init();	
	articleSetting.init();	
	UPX_colCtrl.init();		
	UPX_tabsDisplay.init();		
	UPX_contentPager.init();		
	quickLinks.init();	
	socialLinks.init();
	socialFeeds.init();	
	
	/* call common functions */
	COMMON_form.init();	
	COMMON_links.init();	
	COMMON_imageMouseover.init();
	COMMON_table.init();
	COMMON_tabs_display.init();
	COMMON_breadcrumb.init();
	COMMON_accordion.init();
	COMMON_contentPager.init();	
	COMMON_scroller.init();
	COMMON_flowPlayer.init();	

});

/***** BEGIN: LEGACY *****/

 // Begin Aptimus

// Cookie code
// To get a cookie value by name use function:
// returnPopulatedValue(cookieName,attributeName);
// @returns query string and if none the value from the specified cookie (if avialable)
// Note cookie functions other than set and get are expecting name = value pairs and are "&" delimited

var theCookieName = "rf_prepop";
function setCookie(cookieName,cookieValue,expires,path,domain,secure)
{
  if (!domain) {
		var thisLocation = window.location.hostname;
		var thisHost = thisLocation.substring(thisLocation.indexOf("://") + 3);
		if (thisHost.indexOf(".") != thisHost.lastIndexOf(".")) {
			var domain = thisHost.substring(thisHost.indexOf("."));
		}
  }
  if (!path) {
  	var path = "/";
  }
  var curCookie = cookieName + "=" + escape(cookieValue) +
      ((expires) ? "; expires=" + expires.toGMTString() : "") +
      ((path) ? "; path=" + path : "") +
      ((domain) ? "; domain=" + domain : "") +
      ((secure) ? "; secure" : "");
  document.cookie = curCookie;
}
function getCookie(cookieName)
{
  var dc = document.cookie;
  var prefix = cookieName + "=";
  var begin = dc.indexOf("; " + prefix);
  if (begin == -1)
  {
    begin = dc.indexOf(prefix);
    if (begin != 0) return null;
  }
  else begin += 2;

  var end = dc.indexOf(";", begin);
  if (end == -1) end = dc.length;

  var returnVal = unescape( dc.substring( begin + prefix.length, end ) );
  return returnVal;
}
function deleteCookie(cookieName, path, domain)
{
  var now = new Date();
  fixDate( now ); // fix the bug in Navigator 2.0, Macintosh
  var expired = new Date(now.getTime() - 28 * 24 * 60 * 60 * 1000); // 28 days ago

  if ( getCookie( cookieName ) )
  {
    document.cookie = cookieName + "=" + ((path) ? "; path=" + path : "") + ((domain) ? "; domain=" + domain : "") + "; expires=" + expired.toGMTString();
  }
}
function fixDate(date)
{
  var base = new Date(0);
  var skew = base.getTime();
  if (skew > 0) date.setTime(date.getTime() - skew);
}

function returnUrlAttributeValue(attributeName) {
  var pageURL = document.location.href;
  if (pageURL.indexOf('?') != -1) {
    var queryString = pageURL.substring(pageURL.indexOf('?') + 1,pageURL.length);
    var queryStringArray = queryString.split("&");
    for ( var i=0, v=queryStringArray.length; i<v; i++) {
      curItem = queryStringArray[i];
      if (curItem.substring(0,curItem.indexOf("=")).toLowerCase() == attributeName.toLowerCase()) {
        return curItem.substring(curItem.indexOf("=") + 1,curItem.length);
        break;
      }
    }
    return "";
  } else {
    return "";
  }
}
function returnCookieAttributeValue(cookieName,attributeName) {
  var cookieValue = getCookie(cookieName);
  var cookieValueArray = ( cookieValue ) ? cookieValue.split("&") : "";
  for (var i=0, v=cookieValueArray.length; i<v; i++) {
    curItem = cookieValueArray[i];
    if (curItem.substring(0,curItem.indexOf("=")).toLowerCase() == attributeName.toLowerCase()) {
      return curItem.substring(curItem.indexOf("=") + 1,curItem.length);
      break;
    }
  }
  return "";
}
function setCookieValue(cookieName,nameValuePair) {
  var thisCookie = getCookie(cookieName);
  var thisDelimiter = (thisCookie) ? "&" : "";
  var cookieFound = false;
  if ( thisCookie != null ) {
    var thisName = nameValuePair.substring(0,nameValuePair.indexOf("="));
    var arrCookiePairs = thisCookie.split("&");
    if ( arrCookiePairs.length > 0 ) {
      for (var i=0, j=arrCookiePairs.length; i<j; i++) {
        var strCurName = arrCookiePairs[i].split("=")[0];
        if ( strCurName === thisName ) {
          cookieFound = true;
        }
      }
    }
    
    if(!cookieFound){
      setCookie(cookieName,thisCookie + thisDelimiter + nameValuePair,'','/');
      return;
    } else {    
      //The cookie exists, updating the value
      if ( arrCookiePairs.length > 0 ) {
    	  var strNameToMatch = nameValuePair.split("=")[0];
    	  var strNewValue = nameValuePair.split("=")[1];
    	  var strNewCookie = "";
    	  for (var i=0, j=arrCookiePairs.length; i<j; i++) {
      		if ( arrCookiePairs[i].split("=").length > 1 ) {
      			strCurName = arrCookiePairs[i].split("=")[0];
      			if ( strCurName == strNameToMatch ) {
      				strNewCookie = strNewCookie + strCurName + "=" + strNewValue;
      			} else {
      				strNewCookie = strNewCookie + arrCookiePairs[i];
      			}
      			if (i+1 != j) strNewCookie = strNewCookie + "&";
      		}
    	  }
    	  if ( strNewCookie != "" ) {
    	    setCookie(cookieName,strNewCookie,'','/');
        }
      }
    }
  }else {
    setCookie(cookieName,nameValuePair,'','/');
  }
}
function returnPopulatedValue(cookieName,attributeName,defaultValue) {
  var urlAttributeValue = returnUrlAttributeValue(attributeName);
  if (urlAttributeValue != "") {
    // Get Value From URL
    // Phone Check
    if (attributeName == "CLPhone" && !returnSimplePhoneCheck(urlAttributeValue)) {
      return defaultValue;
    }
    return urlAttributeValue;
  } else {
    // Get Value From Cookie
    strCookieVal = returnCookieAttributeValue(cookieName,attributeName);
    if (strCookieVal == "" && defaultValue) {
      return defaultValue;
    } else {
      return strCookieVal;
    }
  }
}
function returnSimplePhoneCheck(phoneNumber) {
  var phoneRegex0 = /^\d\d\d\.\d\d\d\.\d\d\d\d$/;
  var phoneRegex1 = /^\d\d\d\-\d\d\d\-\d\d\d\d$/;
  var phoneRegex2 = /^\d-\d\d\d\-\d\d\d\-\d\d\d\d$/;
  if (phoneNumber.match(phoneRegex0) || phoneNumber.match(phoneRegex1) || phoneNumber.match(phoneRegex2)) {
    return true;
  } else {
    return false;
  }
}
function addQueryParamsToCookie(cookieName) {
  var pageURL = document.location.href;
  if (pageURL.indexOf('?') != -1) {
    var queryString = pageURL.substring(pageURL.indexOf('?') + 1,pageURL.length);
    var queryStringArray = queryString.split("&");
    for ( var i=0, v=queryStringArray.length; i<v; i++) {
      curItem = queryStringArray[i];
      setCookieValue(cookieName,curItem);
    }
  }
}
function cookieArgSpooler(cookieName,args) {
  var arrArgs = args.split(",");
  for (var i=0, n=arrArgs.length; i<n; i++) {
    thisValue = returnUrlAttributeValue(arrArgs[i]);
    if (thisValue == "" && arrArgs[i].indexOf("=") != -1) {
      thisValue = arrArgs[i].substring(arrArgs[i].indexOf("=") + 1, arrArgs[i].length);
    }
    if (returnUrlAttributeValue(arrArgs[i]) != "") {
      setCookieValue(cookieName,arrArgs[i] + "=" + thisValue);
    }
  }
}
function popup(strUrl, iWidth, iHeight, iLeft, iTop, blnCenter, strName, strScroll, strMenus, strTools, strResize, strLocate)
{
  if ( blnCenter )
  {
    iLeft = (screen.width - iWidth) / 2;
    iTop = (screen.height - iHeight) / 2;
  }
  
  var winprops =  "location=" + strLocate + ",scrollbars=" + strScroll + ",menubar=" + strMenus + ",toolbar=" + strTools + ",resizable=" + strResize + ",left=" + iLeft + ",top=" + iTop + ",width=" + iWidth + ",height=" + iHeight;   

  var popup = window.open(strUrl,strName,winprops);
  popup.focus();
}
 
/***** END: LEGACY *****/

/*
 * Retain the "this" object for a call back method that belongs to a class since the "this" object in a call back function
 * will be a reference to the link not the class that the method belongs to  
 */
function retainThisObject(thisObject, callBackMethod){
  return function(){
    return callBackMethod.apply(thisObject, arguments);
  }
}
