/*
 * 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")}})})();;
/**
 * Cookie plugin
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 */

/**
 * Create a cookie with the given name and value and other optional parameters.
 *
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Set the value of a cookie.
 * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
 * @desc Create a cookie with all available options.
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Create a session cookie.
 * @example $.cookie('the_cookie', null);
 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
 *       used when the cookie was set.
 *
 * @param String name The name of the cookie.
 * @param String value The value of the cookie.
 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
 *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
 *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
 *                             when the the browser exits.
 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
 *                        require a secure protocol (like HTTPS).
 * @type undefined
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */

/**
 * Get the value of a cookie with the given name.
 *
 * @example $.cookie('the_cookie');
 * @desc Get the value of a cookie.
 *
 * @param String name The name of the cookie.
 * @return The value of the cookie.
 * @type String
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */
jQuery.cookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
        options = options || {};
        if (value === null) {
            value = '';
            options = $.extend({}, options); // clone object since it's unexpected behavior if the expired property were changed
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        }
        // NOTE Needed to parenthesize options.path and options.domain
        // in the following expressions, otherwise they evaluate to undefined
        // in the packed version for some reason...
        var path = options.path ? '; path=' + (options.path) : '';
        var domain = options.domain ? '; domain=' + (options.domain) : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};;
(function(){
  var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

  // The base Class implementation (does nothing)
  this.Class = function(){};
 
  // Create a new Class that inherits from this class
  Class.extend = function(prop) {
    var _super = this.prototype;
   
    // Instantiate a base class (but only create the instance,
    // do not run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;
   
    // Copy the properties over onto the new prototype
    for (var name in prop) {
      // Check if we are overwriting an existing function
      prototype[name] = typeof prop[name] == "function" &&
        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
        (function(name, fn){
          return function() {
            var tmp = this._super;
           
            // Add a new ._super() method that is the same method
            // but on the super-class
            this._super = _super[name];
           
            // The method only need to be bound temporarily, so we
            // remove it when we are done executing
            var ret = fn.apply(this, arguments);       
            this._super = tmp;
           
            return ret;
          };
        })(name, prop[name]) :
        prop[name];
    }
   
    // The dummy class constructor
    function Class() {
      // All construction is actually done in the init method
      if ( !initializing && this.init )
        this.init.apply(this, arguments);
    }
   
    // Populate our constructed prototype object
    Class.prototype = prototype;
   
    // Enforce the constructor to be what we expect
    Class.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;
   
    return Class;
  };
})();
;
/*** $Id$ ***/
function json(){}
function json_init()
{
  var m = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\' };
  var s = new Object();

  s['boolean'] = function (x) { return String(x); };
  s['null'   ] = function (x) { return "null";    };
  s['number' ] = function (x) { return isFinite(x) ? String(x) : 'null'; };
  s['array'  ] = function (x)
  {
    var a = ['['], b, f, i, l = x.length, v;
    for (i = 0; i < l; i += 1) {
      v = x[i];
      f = s[typeof v];
      if (f) {
        v = f(v);
        if (typeof v == 'string') {
         if (b) {
            a[a.length] = ',';
          }
          a[a.length] = v;
          b = true;
        }
      }
    }
    a[a.length] = ']';
    return a.join('');
  };

  s['object'] = function (x) {
    if (x) {
      if (x instanceof Array) return s.array(x);
      var a = ['{'], b, f, i, v;
      for (i in x) {
        v = x[i];
        f = s[typeof v];
        if (f) {
          v = f(v);
          if (typeof v == 'string') {
            if (b) a[a.length] = ',';
            a.push(s.string(i), ':', v);
            b = true;
          }
        }
      }
      a[a.length] = '}';
      return a.join('');
    }
    return 'null';
  };

  s['string'] = function (x) {
    if (/[\"\\\x00-\x1f]/.test(x)) {
      x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
        var c = m[b];
        if (c) return c;
        c = b.charCodeAt();
        return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
      });
    }
    return '"' + x + '"';
  };

  json.serialize = function (obj)
  {
    obj = obj || false;
    return s[ typeof(obj) ](obj);
  };

  json.deserialize = json.unserialize = function (str)
  {
    try
    {
      return (/^(\"(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(str)) && eval('(' + str + ')');
    }
    catch (e)
    {
      return false;
    }
  };
}

json_init();
;
jQuery.fn.extend(
{
	/**
	 * Wrapper over bind that enables you to connect events to objects, not just callbacks
	 *
	 * @param type {String} Event type (click,focus,etc)
	 * @param obj {Object} The object you want to bind the event to
	 * @param method {String|Function} Either a string method name or function reference to call on obj
	 * @param args {Array} Optional arguments to pass to the callback (instead of the default ones)
	 */
	connect: function( type, obj, method, args )
	{
		return this.each( function()
		{
			var f = function()
			{
				var a = args || [this].concat(jQuery.makeArray(arguments));
				var r = (typeof method == 'string' ? obj[method].apply(obj, a ) : method.apply(obj, a ));
				return typeof r == 'boolean' ? r : false;
			};

			var ccache = jQuery.data(this,'connect:'+type) || [];
			ccache.push([obj,method,f]);
			jQuery.data(this,'connect:'+type,ccache);
			$(this).bind(type,f);
		});
	},

	/**
	 * Disconnect your connected events from the target object
	 *
	 * @param type {String} Event type (click,focus,etc)
	 * @param obj {Object} The object you want to disconnect the event from
	 * @param method {String|Function} Either a string method name or function that you used in your connect
	 */
	disconnect: function( type, obj, method )
	{
		return this.each(function()
		{
			var ccache = jQuery.data(this,'connect:'+type) || [];
			var hdlrs  = [];
			var ncache = [];
			var elmt   = this;

			jQuery.each(ccache, function(i,rec)
			{
				if (rec[0]==obj && rec[1]==method)
				{
					hdlrs.push(rec[2]);
				}
				else
				{
					ncache.push(rec);
				}
			});

			jQuery.each(hdlrs, function(i,hdlr)
			{
				$(elmt).unbind(type,hdlr);
			});

			jQuery.data(this,'connect:'+type,ncache.length ? ncache : false);

		});
	},

	/**
	 * Wrapper over live that enables you to connect events to objects, not just callbacks
	 *
	 * @param type {String} Event type (click,focus,etc)
	 * @param obj {Object} The object you want to bind the event to
	 * @param method {String|Function} Either a string method name or function reference to call on obj
	 * @param args {Array} Optional arguments to pass to the callback (instead of the default ones)
	 */
	liveConnect: function( type, obj, method, args )
	{
		var f = function()
		{
			var a = args || [this].concat(jQuery.makeArray(arguments)); 
			var r = (typeof method == 'string' ? obj[method].apply(obj, a ) : method.apply(obj, a ));
			return typeof r == 'boolean' ? r : false; 
		};

		var cacheid = 'liveconnect:'+type+':'+this.selector;
		var ccache  = jQuery.data(window,cacheid) || [];
		ccache.push([obj,method,f]);
		jQuery.data(window,cacheid,ccache);
		$(this.selector).live(type, f);
		return this;
	},

	/**
	 * Disconnect your live connected events from the target object
	 *
	 * @param type {String} Event type (click,focus,etc)
	 * @param obj {Object} The object you want to disconnect the event from
	 * @param method {String|Function} Either a string method name or function that you used in your connect
	 */
	liveDisconnect: function ( type, obj, method )
	{
		var cacheid= 'liveconnect:'+type+':'+this.selector;
		var ccache = jQuery.data(window,cacheid) || [];
		var hdlrs  = [];
		var ncache = [];
		var elmt   = this;

		jQuery.each(ccache, function(i,rec) 
		{ 
			if (rec[0]==obj && rec[1]==method)
			{
				hdlrs.push(rec[2]);
			}
			else
			{
				//Dont kill it, add it back to the cache for later
				ncache.push(rec);
			}
		});

		jQuery.each( hdlrs, function(i,hdlr) 
		{ 
			$(elmt).die(type,hdlr); 
		});

		jQuery.data(window,cacheid, ncache.length ? ncache : false);
		return this;
	},

	/**
	 * Test whether x and y are on this jquery element
	 *
	 * @param x {Number} The x position
	 * @param y {Number} The y position
	 * @return {Boolean} True if it hits, false if it doesn't
	 */
	hitTest: function (x,y)
	{
		var o  = this.getPosition();
		var ox = o.left;
		var oy = o.top;
		var w  = this[0].offsetWidth;
		var h  = this[0].offsetHeight;
		var ex = ox+w;
		var ey = oy+h;

		return ( x >= ox && y >= oy && x <= ex && y <= ey ) ? true : false;
	},

	/**
	 * Get the left and top positions for this element, essentially the x,y coordinates
	 *
	 * @return {Object} Left and Top coordinates
	 */
	getPosition: function ()
	{
		return this.eq(0).position();
	},

	/**
	 * Replace this dom element with html content
	 *
	 * @param value {String} The content you want to replace this dom element with
	 */
	replaceWith: function( value )
	{
		return this.each( function ()
		{
				var e = $(this);
				var p = e.parent();
				var s = e.prev();
				e.remove();

				if (s[0])
				{
					s.after(value);
				}
				else
				{
					p.prepend(value);
				}
		});
	},

	/**
	 * Search for html elements inside this selector and make image tags with png's transparent using IE filter hack
	 */
	fixPngImage: function()
	{
		if (!$.browser.msie || parseInt($.browser.version) >= 7.0 )
		{
			return this;
		}

		this.filter('[src$=png]').each( function ()
		{
			var i = $(this);
			i.after( '<div style="display:block; width: '+i.width()+'px; height: '+ i.height() +'px; padding: 0px; margin: 0px; filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + i.attr('src') + '\', sizingMethod=\'image\');" ></div>').hide();
		});

		return this;
	},

	/**
	 * Search for html elements inside this selector and fix background png's using IE filter hack
	 */
	fixPngBackground: function()
	{
		if (!$.browser.msie || parseInt($.browser.version) >= 7.0 )
		{
			return this;
		}

		return this.each( function()
		{
			this.style.backgroundImage = '';
			var m = this.currentStyle.backgroundImage.match(/^url\("([^"]+)"\)/);

			if (!m || !m[1])
			{
				return;
			}

			var sz = this.currentStyle.backgroundRepeat == 'no-repeat' ? 'crop' : 'scale';
			this.style.backgroundImage = 'none';
			this.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="'+m[1]+'", sizingMethod="'+sz+'")';
		});
	},

	/**
	 * Fixes the png background images on hover for IE6.  Will add a "hover" class to the element on mouseover.
	 * @return {Object} returns itself so it can be chainable
	 */
	fixHoverPngBackground: function()
	{
		if ($.browser.msie && $.browser.version < 7)
		{
			var fn = function()
			{
				this.style.backgroundImage = "";
				$(this).toggleClass("hover").fixPngBackground();
			};

			return this.each(function()
			{
				$(this).mouseover(fn).mouseout(fn).fixPngBackground();
			});
		}
		return this;
	},

	/**
	 * Sits idle before returning control.  Works well in chain.
	 */
	idle: function(time, callback)
	{
		return this.animate({delay: 1}, time, callback);
	}
});

jQuery.extend({
	/**
	 * Dynamically loads a stylesheet
	 * @param {String} url
	 */
	getStyle: function(url)
	{
		if (url && typeof jQuery._syn.loaded_ui[url] == "undefined")
		{
			jQuery._syn.loaded_ui[url] = true;
			var ts = (new Date()).getTime();
			url += ((url.match(/\?/)) ? '&' : '?')+'_='+ts;
			$("head").eq(0).append('<link href="'+url+'" rel="stylesheet" type="text/css" />');
		}
	},

	/**
	 * Dynamically loads an array of stylesheets optionally prepending a prefix
	 * @param {Array} urls
	 * @param {String} prefix
	 */
	getStyles: function(urls, prefix)
	{
		urls_array = $.makeArray(urls);
		$.each(urls_array, function(i, url)
		{
			$.getStyle(prefix+url);
		});
	},

	/**
	 * Dynamically removes a stylesheet
	 * @param {String} url
	 */
	removeStyle: function(url)
	{
		if (url)
		{
			var ts_url = $("head").find("link[href^="+url+"?_]").attr('href');
			$("head").find("link[href="+ts_url+"]").remove();
			if (url && typeof jQuery._syn.loaded_ui[url] != "undefined")
			{
				jQuery._syn.loaded_ui[url] = null;
				delete jQuery._syn.loaded_ui[url];
			}
		}
	},

	/**
	 * Dynamically removes an array of stylesheets optionally prepending a prefix
	 * @param {Array} urls
	 * @param {String} prefix
	 */
	removeStyles: function(urls, prefix)
	{
		urls_array = $.makeArray(urls);
		$.each(urls_array, function(i, url)
		{
			$.removeStyle(prefix+url);
		});
	},

	/**
	 * Dynamically loads a number of scripts, optionally calling the callback once all scripts have been loaded (or failed)
	 * @param {Array} urls
	 * @param {Function} callback
	 * @param {String} prefix
	 */
	getScripts: function(urls, callback, prefix)
	{
		if (urls.length == 0)
		{
			callback();
			return;
		}

		var prefix = (prefix) ? prefix : "";
		urls = $.makeArray(urls);

		if (jQuery._syn.loaded_ui[prefix+urls[0]])
		{
			$.getScripts(urls.slice(1), callback, prefix);
		}
		else
		{
			$.getScript(prefix+urls[0], function()
			{
				jQuery._syn.loaded_ui[prefix+urls[0]] = true;
				$.getScripts(urls.slice(1), callback, prefix);
			});
		}
	}
});

(function(){

	var ajax_original = jQuery.ajax;

	jQuery.extend({

		ajax: function(options)
		{
			if (!options.jsCache)
			{
				ajax_original(options);
				return;
			}
		
			var param_key = (typeof(options.data) == 'string') ? options.data : json.serialize(options.data || {});
			var cacheid = options.url + '|' + param_key;
			var cache   = jQuery.data(window, cacheid);
			var success_orig = options.success;

			if ( cache )
			{
				success_orig.apply(options,cache);
				return;
			}

			options.success = function(req,status)
			{
				jQuery.data( window, cacheid, [req,status] );
				this.success = success_orig;
				success_orig.call(this,req,status);
			}

			ajax_original(options);
		}

	});

})();


jQuery._syn = {
	loaded_ui: []
};
;
Syn.UIFileMgr = 
{
	addLoadedJavaScripts: function(scripts)
	{
		$(scripts).each( function (){ Syn.Config.Framework.Javascripts[this]=true; } );
	},

	addLoadedStyleSheets: function(styles)
	{
		$(styles).each( function (){ Syn.Config.Framework.Stylesheets[this]=true; } );
	},

	loadJavaScripts: function(scripts,callback)
	{
		var nl_scripts = [];
		callback = callback ? callback : function(){};

		for ( var i=0; i<scripts.length; i++ )
		{
			var s = scripts[i];
			if ( !Syn.Config.Framework.Javascripts[s] )
			{
				if ( s.indexOf('http://') == 0 )
				{
					scripts.splice(i,1);
					// recursion here is necessary because the callback must execute after all scripts 
					// are sequentially loaded.  
					$.getScript(s,function()
					{ 
						Syn.UIFileMgr.addLoadedJavaScripts([s]);
						Syn.UIFileMgr.loadJavaScripts(scripts,callback); 
					});
					return;	
				}
				else 
				{
					nl_scripts.push(s);  
				}
			}

		};

		if (nl_scripts.length==0)
		{
			callback();
			return;
		}

		var qs  = $.param( { 't':'javascripts', 'c':Syn.Config.Framework.Client, 's':Syn.Config.Framework.Site, 'f':nl_scripts.join(',') } );
		var url = Syn.Config.Framework.ConsolidatorUrl+'?'+qs;

		$.getScript(url,function(){ Syn.UIFileMgr.addLoadedJavaScripts(nl_scripts); callback(); } );
	},

	loadStyleSheets: function(styles,callback)
	{
		var nl_styles = [];
		callback = callback ? callback : function(){};

		$.each(styles,function(i)
		{
			var s = this;
			if ( !Syn.Config.Framework.Stylesheets[s] )
			{
				if ( s.indexOf('http://') == 0 )
				{
					$.getStyle(s);
				}
				else 
				{
					nl_styles.push(s);  
				}
			}
		});

		if (nl_styles.length==0)
		{
			callback();
			return;
		}

		var qs  = $.param( { 't':'stylesheets', 'c':Syn.Config.Framework.Client, 's':Syn.Config.Framework.Site, 'f':nl_styles.join(',') } );
		var url = Syn.Config.Framework.ConsolidatorUrl+'?'+qs;
		$.getStyle(url);
		Syn.UIFileMgr.addLoadedStyleSheets(nl_styles);
		callback();
	}

};
;
/**
 * Create a component instance.
 * @constructor
 */
Syn.Component = Class.extend(
{
	/**
	 * Initialize the component class. This is called automatically by the default constructor.
	 * In the config object, the following attributes are generally supplied
	 *   - {String} type The type of this component, eg (horoscope,movies,etc)
	 *   - {String} uid (v1) The unique identifier for this component instance
	 *   - {String} event_id (v2) The unique identifier for this component instance
	 *   - {String} ajaxtoken A data packet needed to reconstruct the component via webservices
	 * @member Syn.Component
	 * @param {Object} config
	 */
	init: function (config)
	{
		this.type      = config['type'] || '';
		this.uid       = config['uid'];
		this.config    = config;
		this.uid_esc   = this.uid.replace(/(:|\|)/g,'\\$1');
		this.ajaxtoken = config['ajaxtoken'];
		this.comp      = $('#'+this.uniqueKey());
	},

	/**
	 * Get the instance uid
	 * @member Syn.Component
	 * @return {String} The uid
	 */
	getUid: function ()
	{
		return this.uid;
	},

	/**
	 * Get the dom identifier for this simple 'key'. The key value gets expanded to the id of this unique instance of the component.
	 * @member Syn.Component
	 * @param {String} key A simple identifier that appears in your component
	 * @param {bool} no_escape Whether or not to escape the : in the key
	 * @return {String} The expanded per-instance identifier
	 */
	uniqueKey: function (key, no_escape)
	{
		var prefix = this.type ? this.type+'_' : '';

		if (no_escape)
		{
			return prefix+(key!=null ? key+'_' : '')+this.uid;
		}

		return prefix+(key!=null ? key+'_' : '')+this.uid_esc;
	},

	/**
	 * Return the jquery object for this component instance for this simple key
	 * @member Syn.Component
	 * @param {String} key A simple identifier that appears in your component
	 * @return {Object} The jquery object
	 */
	uniqueElmt: function (key)
	{
		return $('#'+this.uniqueKey(key));
	},

	/**
	 * Returns the jquery object for the entire component
	 * @return {Object} The component jquery object
	 */
	container: function ()
	{
		return this.uniqueElmt();
	},

	/**
	 * Submit some form elements via ajax to the component webservice. Will result in the component reloading with new settings.
	 * @param {Array} vals An array of form values to submit
	 * @param {Array} extra_opts
	 */
	submit: function (vals, extra_opts)
	{
		extra_opts = extra_opts||{};
		// Framework request
		if (this.config['uri'])
		{
			var self = this;
			var data = {};
			for (i in vals)
			{
				data[i] = vals[i];
			}

			data['_uri']        = data['_uri'] || this.config['uri'];
			data['_parent_uri'] = data['_parent_uri'] || this.config['parent_uri'];
			data['_root_url']   = Syn.Config.Framework.PortalRoot;
			data['_client_uri'] = 'client://client_config/'+Syn.Config.Framework.Client+'/';
			data['_site_uri']   = 'site://site_config/'+Syn.Config.Framework.Site+'/';

			if (extra_opts['render_wrapper'])
			{
				data['_render_wrapper'] = 1;
			}

			if (extra_opts['app_server'])
			{
				data._is_jsonp = 1;

				rq = {
					'url':         Syn.Config.Framework.AppServer + '_/',
					'contentType': 'application/json',
					'success':     function (x){ self.result(x); },
					'dataType':    'jsonp',
					'data':        data
				};
			}
			else
			{
				 rq = {
					'url':         Syn.Config.Framework.PortalRoot + '_/',
					'type':        'post',
					'contentType': 'application/json',
					'success':     function (x){ self.result(x); },
					'dataType':    'json',
					'data':        json.serialize(data)
				};
			}

			if (extra_opts.cache)
			{
				rq.jsCache = true;
			}

			$.ajax(rq);
			return;
		}

		// Perform the Troy ajax request
		if (!this.ajaxtoken)
		{
			return;
		}

		var packet = {'type':this.type, 'uid':this.uid, 'ajaxtoken':this.ajaxtoken, 'prefs':vals };

		if (extra_opts && extra_opts['norender'])
		{
			packet['norender'] = true;
		}

		this.comm = new Syn.Comm(Syn.Config.WebservicesUrl);
		this.comm.call('ComponentService', 'submit', packet, this, 'result');
	},

	/**
	 * Gets a component given a uri, parent uri and vals.
	 * @member Syn.Component
	 * @param {String} component_uri A uri of the component to render
	 * @param {String} parent_uri A uri of the parent uri for the component to render
	 * @param {Object} vals The values you wish to submit to the component
	 * @param obj {Object} The object that holds callback method.
	 * @param method {String|Function} Either a string method name or function used for callback.  (Optional)
	 * @param args {Array} Optional args for the callback.  (Optional)
	*/
	getComponent: function(component_uri, parent_uri, vals, obj, method)
	{
		return Syn.ComponentUtils.getComponent(component_uri, parent_uri, vals, obj, method);
	},

	loadUxAssets: function(res, callback)
	{
		return Syn.ComponentUtils.loadUxAssets(res, callback);
	},

	/**
	 * The target of the ajax component webservice. Replaces the component content.
	 * @param {mixed} res The content returned from the webservice
	 */
	result: function (res)
	{
		this.hideLoading();

		/**
		 * In case a Troy AJAX call has 'norender' set to true the response will be an empty string.
		 */
		if (!res)
		{
			return;
		}

		if (typeof res == 'string' && res)
		{
			this.container().replaceWith(res);
			return;
		}

		var self = this;
		var callback = function ()
		{
			if ( res['data'] )
			{
				self.onAjaxUpdate(res['data']);
			}
			else
			{
				var repl_target = res['has_wrapper'] ? self.wrapper() : self.container();
				repl_target.replaceWith(res['content']);
				var instance = Syn.ComponentMgr.getInstanceByUid(res.init.event_id);

				if (instance && instance != self)
				{
					Syn.ComponentMgr.remove(self);
				}
			}
		};

		this.loadUxAssets(res, callback);
	},

	/**
	 * Default ajax update handler, override this in subclasses to recieve the ajax update event
	 * @param {Object} config An associative array of config params
	 */
	onAjaxUpdate: function(config)
	{
		return;
	},

	/**
	 * Find a jquery element inside the component container
	 * @param {String} selector The jquery selector to execute inside the component container
	 * @return {Object} The jquery response object
	 */
	find: function(selector)
	{
		return $( '#'+this.uniqueKey()+ ( selector ? ' '+selector : '') );
	},

	/**
	 * Show the loading indicator.
	 * Options can be specified in the opts parameter.  The following opts are accepted:
	 *    target: {Object} A jQuery object where the loading layer will reside inside. [optional]
	 *    class: {String} An additional class name to use on the loading layer. [optional]
	 *
	 * @param {Object} opts Options for the loading layer
	 */
	showLoading: function(opts)
	{
		opts = opts || {};
		var loading = this.uniqueElmt("loading");
		var target  = opts["target"] || this.container();

		if (!loading.size())
		{
			loading = $("<div>").attr("id", this.uniqueKey("loading", true))
			                    .addClass("loading");

			// If the user specified an additional class, add it as well.
			if (opts["class"])
			{
				loading.addClass(opts["class"]);
			}
		}

		loading.css({
			width: target.outerWidth(),
			height: target.outerHeight()
		}).show();

		target.prepend(loading);

		return true;
	},

	/**
	 * Hide the loading indicator
	 */
	hideLoading: function()
	{
		this.uniqueElmt('loading').hide();
	},

	/**
	 * Loads scripts asynchronously and calls a callback when all scripts are done loading.
	 *
	 * @param scripts {Array|String} Array  of javascripts to load or String (for 1 js file to load)
	 * @param obj {Object} The object that holds callback method.
	 * @param method {String|Function} Either a string method name or function used for callback.
	 * @param number {int} The script index to start loading (Not required; defaults to 0)
	 * @member Syn.Component
	 */
	loadJs: function(scripts, obj, method, args, number)
	{
		var that = this;
		scripts = (typeof scripts == "string") ? [scripts] : scripts;
		number = number || 0;
		args = args || [];

		$.getScript(Syn.Config.PortalRoot+'js/'+scripts[number], function()
		{
			//Load the next one if we can
			if ((number+1) < scripts.length)
			{
				that.loadJs(scripts, obj, method,args, number+1);
			}
			else
			{
				//Do our callback now that we are done!
				(typeof method == 'string') ? obj[method].apply(obj, args ) : method.apply(obj, args );
			}
		});
	},

	/**
	 * Get the jquery handle to the component wrapper
	 * @return {Object} The wrapper container jquery object or the component container if no wrapper exists.
	 */
	wrapper: function()
	{
		// The Framework wrapper
		if (this.uniqueElmt('wrapper').length)
		{
			return this.uniqueElmt('wrapper');
		}

		/* Note: the wrap_sel selector has to iterate sub-nodes bcs the id's are not actually
			 unique for wrappers. :( Bad Troy, Bad.
		*/
		var res = this.uid.match(/^(\d+)[\w\:]*_([\w\d]+)$/);
		var wrap_sel = '#body_col_'+ res[1] +' div.comp_container[id=syn_comp_' + res[2] + ']';
		return $(wrap_sel).length ? $(wrap_sel) : this.container();
	},

	/**
	 * Remove the component and wrapper from the page.
	 */
	remove: function(options)
	{
		options = options || [];

		if ( Syn.ComponentMgr )
		{
			Syn.ComponentMgr.remove(this);
		}

		var target = options['target'] == 'wrapper' ? this.wrapper() : this.container();

		if (options['fade_out'])
		{
			target.fadeOut(options['fade_out'], function(){ $(this).remove(); } );
		}
		else
		{
			target.remove();
		}
	},

	/**
	 * Popup a component
	 * @param options {Object} Options
	 {
		 * component {Object | String} (Uri/avs if string)(Optional)
		 * - uri {String} Component Uri To Popup
		 * - params {Object} parameters passed to the component
		 * title {String} Title of component (Optional, overrides popup component title)
		 * layout {String} Layout of popup component, ie controls width (Optional, single|double|triple) 300px,612px, 960px) If not provided, defaults to single)
		 * css_class {String} CSS Class of popup component (Optional, If not provided, uses name of popup component)
		 * show_loading {String} true|false (Optional)
		 * draggable: true|false (Optional)
		 * closeable: true|false (Optional)
		 * resizable: true|false (Optional)
		 * modal: true|false (Optional)
		 * close_on_blur: true|false (Optional)
		 * show_title: true|false (Optional)
		 * center: "screen"|"component"| "#element_id" (Optional)
		 * max_popups: 1,2,3... (Optional) Defaults to 1)
		 * top: xxx (Optional)
		 * left: xxx (Optional)
		 * width: xxx (Optional)
		 * height: xxx (Optional)
	 }
	 *
	 * @param obj {Object} The object that holds callback method.
	 * @param method {String|Function} Either a string method name or function used for callback.  (Optional)
	 * @param args {Array} Optional args for the callback.  (Optional)
	 *
	 */
	popup: function(options, obj, method, args)
	{
		var that = this;
		var load_fn = function()
		{
			if (!that.syn_popup)
			{
				that.syn_popup = new Syn.Popup();
			}

			//If we want to center the popup over the component OR we have not specified a center + left + top
			if (options && options['center'] && options['center'] == 'component'
			 || (options && !options['center'] && !options['left'] && !options['top']))
			{
				options['center'] = '#'+that.uniqueKey();
			}

			that.syn_popup.popup(options, obj, method, args);
		};


		if (this.config['uri'])
		{
			//Load in Syn.Popup framework version
			$.getScripts(["en_US/globals/javascripts/framework/synpopup.js"], load_fn, Syn.Config.Framework.AssetsRoot);
		}
		else
		{
			//Load in Syn.Popup legacy
			$.getScripts(["framework/synpopup.packed.js"], load_fn, Syn.Config.PortalRoot+"js/");
		}
	},

	/**
	 * Live connects a tags for link submissions via ajax.
	 * @param {String|Object} sel
	 * @param {String|Function} method
	 */
	hrefToAjax: function(sel, method, extra_opts)
	{
		var obj = sel;
		if (typeof(obj) == "string")
		{
			obj = this.container().find(sel);
		}

		var self = this;
		obj.live("click", function()
		{
			if (method)
			{
				var a = [this];
				(typeof(method) == "string") ? self[method].apply(self, a) : method.apply(self, a);
			}

			var params = self.queryStrToObject($(this).attr("href"));
			self.submit(params,extra_opts);

			return false;
		});
	},

	/**
	 * Converts a query string to an object.
	 * @param {String} query_string
	 * @return {Array}
	 */
	queryStrToObject: function(query_string)
	{
		// query_string can be just a query string, or it can be a URL.  If it's a URL
		// with no query string, return an empty object.
		if (query_string.match(/^https?:\/\//) && query_string.indexOf("?") === -1)
		{
			return {};
		}

		var qs = query_string.match(/(?:^|\?)([^?]+)#?(?=#|$)/);
		qs = (qs) ? qs[1] : '';

		var params = qs.split(/&/);

		var arr = {};
		for (i = 0; i < params.length; ++i)
		{
			// PHP and JavaScript encode spaces differently.  Actually, PHP encodes spaces differently
			// as well.  http_build_query() in PHP encodes spaces as + (whereas rawurlencode() does %20).
			// JavaScript on the other hand encodes spaces a %20 only and doesn't encode the plus.  To fix this
			// we'll manually decode the plus as a space and then decode the rest.
			var keyvalue = params[i].split(/=/);
			var key = keyvalue[0];
			key = key.replace(/\+/g, ' ');
			key = decodeURIComponent(key);

			var value = keyvalue[1];
			if (value)
			{
				value = value.replace(/\+/g, ' ');
				value = decodeURIComponent(value);
			}
			arr[key] = (value) ? value : '';
		}

		return arr;
	},

	encodeDomId: function(str)
	{
	  return str.replace(/\W/g, function (char)
	  {
		return '-'+char.charCodeAt(0).toString(16);
	  });
	},

	decodeDomId: function(str)
	{
	  return str.replace(/\-([0-9a-f]{2})/ig, function (str,hex)
	  {
		return String.fromCharCode(parseInt(hex,16));
	  });
	}
});
;
Syn.ComponentUtils = 
{
	/**
	 * Gets a component given a uri, parent uri and vals.
	 * @member Syn.ComponentUtils
	 * @param {String} component_uri A uri of the component to render
	 * @param {String} parent_uri A uri of the parent uri for the component to render
	 * @param {Object} vals The values you wish to submit to the component
	 * @param obj {Object} The object that holds callback method.
	 * @param method {String|Function} Either a string method name or function used for callback.  (Optional)
	 * @param args {Array} Optional args for the callback.  (Optional)
	 */
	getComponent: function(component_uri, parent_uri, vals, obj, method)
	{
		vals['_uri']        = component_uri;
		vals['_parent_uri'] = parent_uri;
		vals['_root_url']   = Syn.Config.Framework.PortalRoot;
		vals['_client_uri'] = 'client://client_config/'+Syn.Config.Framework.Client+'/';
		vals['_site_uri']   = 'site://site_config/'+Syn.Config.Framework.Site+'/';

		$.ajax({
			'url':         Syn.Config.Framework.PortalRoot + '_/',
			'type':        'post',
			'contentType': 'application/json',
			'success':     function(res)
			{
				Syn.ComponentUtils.loadUxAssets(res, function()
				{
					(typeof method == 'string') ? obj[method].apply(obj, [res] ) : method.apply(obj, [res]  );
				});
			},
			'dataType':    'json',
			'data':        json.serialize(vals)
		});
	},

	loadUxAssets: function(res, callback)
	{
		if (res['stylesheets'] && res['javascripts'])
		{
			Syn.UIFileMgr.loadStyleSheets(res['stylesheets'], function()
			{
				Syn.UIFileMgr.loadJavaScripts(res['javascripts'], callback);
			});
		}
		else if (res['stylesheets'])
		{
			Syn.UIFileMgr.loadStyleSheets(res['stylesheets'], callback);
		}
		else if (res['javascripts'])
		{
			Syn.UIFileMgr.loadJavaScripts(res['javascripts'], callback);
		}
		else
		{
			callback();
		}
	}
};;
/**
 * The Syn.ComponentMgr Static Class
 * @class Syn.ComponentMgr
 */
Syn.ComponentMgr =
{
	/**
	 * Map of component instances by class
	 * @member Syn.ComponentMgr
	 */
	instancesByClass: {},

	/**
	 * Map of instances by uid
	 * @member Syn.ComponentMgr
	 */
	instancesByUid: {},

	/**
	 * Instantiate a component instance
	 * @member Syn.ComponentMgr
	 */
	instantiate: function(config)
	{
		config['uid'] = config['uid'] || config['event_id'];

		var exists = Syn.ComponentMgr.instancesByUid[config['uid']];

		if (exists && exists.config['class_name'] == config['class_name'])
		{
			exists.onAjaxUpdate(config);
			return exists;
		}

		if (config["class_name"])
		{
			var instance = new (window["eval"](config['class_name']))(config);
			var inst_class_cache = Syn.ComponentMgr.instancesByClass[config['class_name']] || [];
			Syn.ComponentMgr.instancesByClass[config['class_name']] = inst_class_cache;

			inst_class_cache.push(instance);
			Syn.ComponentMgr.instancesByUid[instance.uid] = instance;
			return instance;
		}

		return false;
	},

	/**
	 * Get an array of instances of a particular component class
	 * @param {String} class The class of component to
	 * @return {Array} An array of instances
	 */
	getInstancesByClass: function(cclass)
	{
		return Syn.ComponentMgr.instancesByClass[cclass] || [];
	},

	/**
	 * Get an instance of a component based on uid
	 * @param {String} uid The uid of the component
	 * @return {Object} The component instance
	 */
	getInstanceByUid: function(uid)
	{
		return Syn.ComponentMgr.instancesByUid[uid];
	},

	/**
	 * Remove a component instance from the component manager
	 * @param {Object} instance The instance to be removed from the page
	 */
	remove: function(instance)
	{
		var class_arr;
		class_arr = Syn.ComponentMgr.instancesByClass[instance.config['class_name']];

		if (!class_arr)
		{
			return;
		}

		for (var i=0; i<class_arr.length; i++ )
		{
			if (class_arr[i] == instance)
			{
				class_arr.splice(i,1);
				break;
			}
		}

		if ( Syn.ComponentMgr.instancesByUid[instance.uid] == instance )
		{
			delete Syn.ComponentMgr.instancesByUid[instance.uid];
		}

		if (window['dd_writeCookie'])
		{
			dd_writeCookie();
		}
	}
};
;
/**
 * Tracking metrics namespace. 
 */
Syn.Tracking = {};

/**
 * Tracking module for images
 */
Syn.Tracking.Image =
{
	/**
	 * Record parameters to the tracking system
	 * @member Syn.Tracking.Image 
	 * @param {Object} params
	 */
	record: function(params)
	{
		var args = params['args'];
		var dt   = new Date();
		args['ts'] = dt.getTime();
		var img = document.createElement('img');
		var url = Syn.Config.PortalRoot + 'images/track/track.gif?' + jQuery.param( args );
		img.src = url;
		$(document.body).append(img);
	}
};

/**
 * Tracking Module for Omniture
 */
Syn.Tracking.Omniture =
{
	/**
	 * Record parameters to the tracking system
	 * @member Syn.Tracking.Image 
	 * @param {Object} params
	 */
	record: function(params)
	{
		var om = Syn.Config.Omniture;
		var args = params['args'];
		var s=s_gi(om['account']);

		if (!s)
		{
			return;
		}

		s.pageName = om['page_name'];
		s.server   = om['server'];
		s.channel  = om['context'];

		var track_vars = [];

		for ( k in om['omniture_variable_mappings'] )
		{
			var om_key = om['omniture_variable_mappings'][k] || k;
			s[ om_key ] = args[k]; 			
			track_vars.push( om_key );
		}

		s.linkTrackVars = track_vars.join(',');

		var s_code= params['event'] == 'load' ||  params['event'] == 'ready' ? s.t() : s.tl();

		if (s_code)
		{
			$('head').append(s_code);
		}
	}
};


jQuery.fn.extend( 
{
	/**
	 * Wrapper over bind that enables you to connect events to objects, not just callbacks
	 *
	 * @param type {String} Event type (click,focus,etc)
	 * @param obj {Object} The object you want to bind the event to
	 * @param method {String|Function} Either a string method name or function reference to call on obj
	 * @param args {Array} Optional arguments to pass to the callback (instead of the default ones) 
	 */
	track: function( params ) 
	{
		var module = params['module'];
		var args   = params['args'];
		var ev_t   = params['event'];
		var live   = params['live'];
		var defer  = params['defer'];

		if ( !Syn.Tracking[module] )
		{
			return this;
		}

		return this[ live ? 'live' : 'bind' ]( ev_t, function (ev) 
		{
			if (params['defer'] == 'unload')
			{
				$(window).unload(  function(){ Syn.Tracking[module].record(params); } );
			}

			else if (typeof( params['defer'] ) == 'number' )
			{
				setTimeout( function(){ Syn.Tracking[module].record(params); }, params['defer']  ); 
			}

			else
			{
				Syn.Tracking[module].record(params);
			}

			return true;
		}); 
	}
});
;
Number.prototype.NaN0 = function()
{ 
	return isNaN(this) ? 0 : this;
};;
/**
 * The Syn.HeaderBar Component Class
 */

/**
 * Create a Syn.HeaderBar component instance
 * @constructor
 */
Syn.HeaderBar = Syn.Component.extend(
{
	/**
	 * Initialize the component class.
	 * @param {array} config The config array for this component
	 */
	init: function(config)
	{
		//Init parent class
		this._super(config);
		this.uniqueElmt('makeHome').liveConnect('click', this, 'makeHome');
	},

	/**
	 * Method to make passed in url the homepage for the user
	 * @param {object} target The targeted dom object
	 * @param {object} event The event dom object
	 */
	makeHome: function(target, event)
	{
		// Handle IE
		if (document.all)
		{
			document.body.style.behavior = 'url(#default#homepage)';
			document.body.setHomePage($(target).attr('href'));
			return false;
		}
		// Fall back to Firefox
		alert('To make ' + $(target).attr('rel') + ' your homepage - \nGo to "Options" in the "Tools" Menu. Choose the "Main" Tab from the list on the top. Click on the "Use Current Page(s)" button.');
		return false;
	}
});
;
/**
 * The Syn.SearchBar Component Class 
 */

/**
 * Create a Syn.SearchBar component instance 
 * @constructor
 */
Syn.SearchBar = Syn.Component.extend(
{	
	/**
	 * Initialize the component class. This is called automatically by the default constructor.
	 * @member Syn.SearchBar
	 * @param {Object} config The configuration data structure
	 */
	init: function(config)
	{
		//Init parent class
		this._super(config);
		this.uniqueElmt('search_tabs').find('li > a').liveConnect('click', this, 'changeTab');
		this.getContext();
	},
	
	/**
	 * Called on ajax update.
	 * @member Syn.SearchBar
	 * @param {Object} config The configuration data structure
	 */
	changeTab: function(dom, event)
	{
		this.submit({type: $(dom).text(), q:this.config.query});
	},

	/**
	 * Function to get the context and add it to an input element.
	 * This is used to bucket search revenue.
	 * @member Syn.SearchBar
	 */
	getContext: function()
	{
		// Default behavior to determine source context for Google searches.
		var path = new String(window.location);
		var words = path.split("/");
		var context = words[words.length - 2];
		var channel = context.split("_channel");
		if (channel[0])
		{
			context = channel[0];
		}

		// Alternate behavior for tracking source context for Google searches.
		var path = new String(window.location);
		var words = path.split("?")[1];
		if (words != undefined)
		{
			words = words.split("&");
			for (var param in words)
			{
				key_value_pair = words[param].split("=");
				if (key_value_pair[0] == "context" || key_value_pair[0] == "src")
				{
					context = key_value_pair[1];
				}
			}
		}
		$('#search_header_input_context').attr('value', context);
	}
});
;
/**
 * The Syn.Nav Component Class 
 */
/**
 * Create a Syn.Nav component instance 
 * @constructor
 */
Syn.Nav = Syn.Component.extend(
{
	/**
	 * Initialize the component class. This is called automatically by the default constructor.
	 * @member Syn.Nav
	 * @param {Object} config The configuration data structure
	 */
	init: function(config)
	{
		this._super(config);
		this.find('.sub_nav > li').connect("mouseover", this, "overSecondaryNav");
		this.find('.sub_nav > li').connect("mouseout", this, "outSecondaryNav");
		this.find('.ter_nav').connect("mouseover", this, "overTerNav");
		this.find('.ter_nav').connect("mouseout", this, "outTerNav");
		this.uniqueElmt('morelabel').connect("mouseover", this, "moreLabelOver");
		this.uniqueElmt('morelabel').find('a').connect("click", this, function(){return false;});
		this.uniqueElmt('morelabel').connect("mouseout", this, "moreLabelOut");
		this.uniqueElmt('morecontainer').connect("mouseover", this, "overMoreContainer");
		this.uniqueElmt('morecontainer').connect("mouseout", this, "outMoreContainer");
		this.find('.noaction').click(function()
		{
			return false;
		});
	},
	
	overSecondaryNav: function(dom, event)
	{
		this.showTerNav($(dom).find('>a').next());
	},
	
	outSecondaryNav: function(dom, event)
	{
		this.hideTerNav($(dom).find('>a').next());
	},
	
	overTerNav: function(dom, event)
	{
		this.showTerNav(dom);
	},
	
	outTerNav: function(dom, event)
	{
		this.hideTerNav(dom);
	},
	
	moreLabelOver: function(dom, event)
	{
		this.showMoreNav();
	},
	
	moreLabelOut: function(dom, event)
	{
		this.hideMoreNav();
	},

	overMoreContainer: function(dom, event)
	{
		this.showMoreNav();
	},
	
	outMoreContainer: function(dom, event)
	{
		this.hideMoreNav();
	},
	
	showTerNav: function(dom)
	{
		if (this.terNavTimer)
		{
			clearTimeout(this.terNavTimer);
		}
		this.find('.sub_nav .ter_nav').hide();
		$(dom).show();
	},

	hideTerNav: function(dom)
	{
		this.terNavTimer = setTimeout(function()
		{
			$(dom).hide();
		}, 200);		
	},

	showMoreNav: function()
	{
		if (this.moreNavTimer)
		{
			clearTimeout(this.moreNavTimer);
		}
		this.uniqueElmt("morelabel").addClass('on');
		this.uniqueElmt('morecontainer').show();		
	},

	hideMoreNav: function()
	{
		var self = this;
		this.moreNavTimer = setTimeout(function()
		{
			self.uniqueElmt("morelabel").removeClass('on');
			self.uniqueElmt('morecontainer').hide();
		}, 200);	
	}
});
;
/**
 * The Syn.ComponentDiscoveryReveal Component Class
 */

/**
 * Create a Syn.ComponentDiscoveryReveal component instance
 * @constructor
 */
Syn.ComponentDiscoveryReveal = Syn.Component.extend(
{
	/**
	 * Initialize the component class. This is called automatically by the default constructor.
	 * @member Syn.ComponentDiscoveryReveal
	 * @param {Object} config The configuration data structure
	 */
	init: function(config)
	{
		//Init parent class
		this._super(config);
		this.browse_loading = false;
		var self = this;
		if (Syn.Config.Framework.LoggedIn || this.config.logged_out_customization)
		{
			$(window).load(function()
			{	
				var options = {
					  connectWith: '.customizable_zone',
					  handle: 'h2',
					  placeholder: 'customizable_placeholder',
					  forcePlaceholderSize: true,
					  tolerance: 'pointer',
					  stop: function(event, ui) { self.sortStop(event, ui);}
				};

				if ($('.drag_container').size() == 1)
				{
					  options['containment'] = '.drag_container';
				}

				$('.customizable_zone').sortable(options);	
				self.initCustomizableZones();
			});
		}
		this.uniqueElmt('reveal').connect('click', this, "showComponentDiscovery");

		if ($.cookie)
		{
			if ($.cookie('show_discovery_browse') == '1')
			{
				//Delete cookie
				$.cookie('show_discovery_browse', null);
				this.showComponentDiscovery();
			}

			if ($.cookie('show_post_personalize') == '1')
			{
				//Delete cookie
				$.cookie('show_post_personalize', null);

				this.uniqueElmt('personalize').show();
				setTimeout(function(){self.uniqueElmt('personalize').fadeOut('slow');}, 5000);
			}
		}
	},

	/**
	 * Inits the customizables zones by showing close, adding a class to h2 and making it closeable
	 */
	initCustomizableZones: function()
	{
		var customizable_zones = $('.customizable_zone');	
		customizable_zones.find('a.comp_header_close').show();
		customizable_zones.find('a.comp_header_close').connect('click', this, "removeComponent");
		customizable_zones.find('.comp_header h2').addClass('customizable');

		var farthest_to_bottom = 0;
		var zone_data = {};
		customizable_zones.css('position', 'relative');

		customizable_zones.each(function(i, n)
		{
			// Set height to auto so size can be calculated properly
			// Later on the height will get set to a specific value
			// This is needed here to that value is right
			$(n).css('height', 'auto');

			zone_data[i] =
			{
				'top_of_zone':parseInt($(n).offset().top, 10),
				'bottom_of_zone': parseInt($(n).offset().top, 10) + $(n).height()
			};

			if (zone_data[i].bottom_of_zone > zone_data[farthest_to_bottom].bottom_of_zone)
			{
				farthest_to_bottom = i;
			}

		});
		customizable_zones.each(function(i, n)
		{
			var z_lowest_top = zone_data[farthest_to_bottom].top_of_zone;
			var cur_zone_top = parseInt($(n).offset().top, 10);
			var z_lowest_height = zone_data[farthest_to_bottom].bottom_of_zone - zone_data[farthest_to_bottom].top_of_zone ;
			$(n).css('height', z_lowest_top - cur_zone_top + z_lowest_height);
		});
		
		$('.customizable_zone').css('position', 'static');

		//fix height of overall page

	},

	/**
	 * Shows the component discovery browse area
	 * @param {dom} Dom element
	 * @param {event} Event element
	 */
	showComponentDiscovery: function(dom, event)
	{
		if (!Syn.Config.Framework.LoggedIn && !this.config.logged_out_customization)
		{
			//Let href go to login page!
			return true;
		}

		if (Syn.ComponentMgr.getInstancesByClass("Syn.ComponentDiscoveryBrowse").length === 0)
		{
			if (!this.browse_loading)
			{
				this.browse_loading = true;
				this.getComponent('component://Synacor/Portal/Components/ComponentDiscovery/Browse/', '',
				{'customizable_zones': this.config.customizable_zones}, this, function(result)
				{
					if (Syn.ComponentMgr.getInstancesByClass("Syn.ComponentDiscoveryBrowsePlace").length == 1)
					{
						//Load after a slight delay to give css time to be available
						setTimeout(function()
						{
							Syn.ComponentMgr.getInstancesByClass("Syn.ComponentDiscoveryBrowsePlace")[0].uniqueElmt().append(result.content);
							Syn.ComponentMgr.getInstancesByClass("Syn.ComponentDiscoveryBrowse")[0].uniqueElmt().hide();
							Syn.ComponentMgr.getInstancesByClass("Syn.ComponentDiscoveryBrowse")[0].open();
						},100);
					}

				});
			}
		}
		else
		{
			Syn.ComponentMgr.getInstancesByClass("Syn.ComponentDiscoveryBrowse")[0].open();
		}
	},

	/**
	 * Called when sorting is stopped
	 * @param {event} Event element
	 * @param {ui} Ui element
	 */
	sortStop: function(event, ui)
	{
		var self = this;
		var zone = this.getZoneForComponent(ui.item);
		this.saveComps(this.getComps(), function()
		{
			self.getComponent('component://Synacor/Portal/Components/ComponentDiscovery/RezoneComponent/', '',
			{'event_id': ui.item.attr('id').substring('wrapper_'.length) , 'zone_uri': zone.uri}, self, function(result)
			{
				var instance = Syn.ComponentMgr.getInstanceByUid(ui.item.attr('id').substring('wrapper_'.length));
				if (instance)
				{
					Syn.ComponentMgr.remove(instance);
				}
				ui.item.replaceWith($(result.content).find('.comp_container').parent().html());

				self.initCustomizableZones();
			});
		});

	},

	/**
	 * Gets the comps in each zone
	 */
	getComps: function()
	{
		var comps = {};
		var that = this;
		$.each(this.config.customizable_zones, function(k,v)
		{
			comps[v.uri] = that.getCompsInZone(v.id);
		});

		return comps;
	},

	/**
	 * Saves the comps passed in, with an optional callback
	 * @param {comps} Components to save
	 * @param {callback} Callback after saving
	 */
	saveComps: function(comps, callback)
	{
		callback = callback ? callback : function(){};
		this.getComponent('component://Synacor/Portal/Components/ComponentDiscovery/Reveal/', '',
		{'action': 'saveComponents' , 'response_type':'data', 'components': comps}, this, callback);
	},

	/**
	 * Gets comps in zone
	 * @param {zone_id} Zone id to get comps for a zone
	 */
	getCompsInZone: function(zone_id)
	{
		var self = this;
		var comps = [];
		$('#'+zone_id).children('div').each(function()
		{
			//Return the id without the wrapper_ at the start and then decode resulting id
			comps.push($(this).attr('id').substring('wrapper_'.length));
		});
		return comps;
	},
	/**
	 * Gets a zone for a component
	 * @param {id} Zone dom id for component
	 */
	getZoneForComponent: function(item)
	{
		for (var k in this.config.customizable_zones)
		{
			if ($("#"+this.config.customizable_zones[k].id).find('#'+$(item[0]).attr('id')).length == 1)
			{
				return this.config.customizable_zones[k];
			}
		}
		return false;
	},

	/**
	 * Removes component
	 * @param {dom} Dom object
	 * @param {event} Event object
	 */
	removeComponent: function(dom, event)
	{
		var that = this;
		$(dom).parents('.comp_container').fadeOut('fast',function()
		{
			//Return the instance
			var instance = Syn.ComponentMgr.getInstanceByUid($(this).attr('id').substring('wrapper_'.length));
			if (instance)
			{
				Syn.ComponentMgr.remove(instance);
			}

			$(this).remove();
			that.saveComps(that.getComps());
		});
	}
});
;
/**
 * The Syn.ComponentDiscoveryPersonalize Component Class 
 */

/**
 * Create a Syn.ComponentDiscoveryPersonalize component instance 
 * @constructor
 */
Syn.ComponentDiscoveryPersonalize = Syn.Component.extend(
{	
	/**
	 * Initialize the component class. This is called automatically by the default constructor.
	 * @member Syn.ComponentDiscoveryPersonalize
	 * @param {Object} config The configuration data structure
	 */
	init: function(config)
	{
		//Init parent class
		this._super(config);
		this.initialSetup();
	},
	
	/**
	 * Initial setup of events
	 */
	initialSetup: function()
	{
		this.uniqueElmt('close_form').connect('click', this, 'submit', [{'action': 'personalizeClose'}]);
		this.uniqueElmt('form').connect('submit', this, 'submitForm');
		this.uniqueElmt('submit').connect('click',this, 'submitForm');	
	},

	/**
	 * Called on ajax update.
	 * @member Syn.ComponentDiscoveryPersonalize
	 * @param {Object} config The configuration data structure
	 */
	onAjaxUpdate: function(config)
	{
		this.initialSetup();
		if (config.rebuild)
		{
			window.location.reload();		
		}
	},
	
	/**
	 * Submits the form to the backend.
	 * @member Syn.ComponentDiscoveryPersonalize
	 * @param {Object} config The configuration data structure
	 */
	submitForm: function(dom, event)
	{
		var fields = this.uniqueElmt("form").serializeArray();
		var field_name=null;
		var data = {};
		$.each(fields, function(i, field)
		{
			// If a form element is an array (e.g. name="interests[]") we
			// have to manually build the array.
			if (field_name = field.name.match(/^(.*)\[\]$/))
			{
				field_name = field_name[1];
				if (!data[field_name])
				{
					data[field_name] = [];
				}
				data[field_name].push(field.value);
			}
			else
			{
				data[field.name] = field.value;
			}
		});

		var self = this;
		this.uniqueElmt().slideUp("normal", function()
		{
			self.submit({'response_type': 'data', 'data': data, 'action':'personalizeFormSubmit', 'customizable_zones': self.config.customizable_zones});
		});
		
		$.cookie('show_post_personalize', '1');
	}
});;
/**
 * The Syn.ComponentDiscoveryBrowsePlace Component Class 
 * This class only exists so it is possible to find a javascript 
 * instance of this component in order to determine where to place
 * the component discovery browse component.
 */

/**
 * Create a Syn.ComponentDiscoveryBrowsePlace component instance 
 * @constructor
 */
Syn.ComponentDiscoveryBrowsePlace = Syn.Component.extend(
{
	/**
	 * Initialize the component class. This is called automatically by the default constructor.
	 * @member Syn.ComponentDiscoveryBrowsePlace
	 * @param {Object} config The configuration data structure
	 */
	init: function(config)
	{
		//Init parent class
		this._super(config);
	}
});;
/**
 * Slideshow.js: Slideshow class for performing content transitions
 *
 * @fileoverview
 * @author Garth Henson
 * @version 1.0
 */

/**
 * Slideshow class constructor method
 *
 * @version 1.0
 * @constructor
 * @param {String} slideshowId The HTML ID of the element which is to become the slideshow container
 * @param {Object} config Configuration object to control the behavior of the slideshow. 
 *	Options:
 *		String transition fade|slide|shutter - Defines the transition type between slides
 *		int timeout - Defines the time (in milliseconds) between transitions
 * @return Slideshow object
 * @type Slideshow
 */

Syn.Slideshow = Class.extend(
{
	init: function(slideshow_id, config)
	{
		this.listeners = {
			beforetransition : [],
			ontransition     : [],
			beforeplay       : [],
			onplay           : [],
			beforestop       : [],
			onstop           : [],
			beforeprev       : [],
			onprev           : [],
			beforenext       : [],
			onnext           : [],
			beforeplaypause  : [],
			onplaypause      : []
		};

		// Constructor variable assignment
		this.id     = slideshow_id;

		var defaults = {
			transition : 0,
			timeout : 5000,
			hover_stop : true,
			direction : 'n',
			play : true,
			fade_speed : 'slow'
		};
		this.config = $.extend(defaults, config);
		
		// Object variables referencing display settings
		this.container = null;
		this.controls  = null;
		this.slides    = [];
		this.current   = 0;
		
		// Object variables to control rotation
		this.setTransitionType(this.config.transition);
		this.timeout    = this.config.timeout;
		this.timeout_id = null;
		this.hover_stop = this.config.hover_stop;
		
		// Slide settings
		this.slide_direction = this.config.direction;
		this.z_index         = 999;
		
		var ele = $('#' + this.id);
		this.container = ele.find('div.ss-container');
		this.controls  = ele.find('div.ss-controls');
		
		this.width  = this.container.width();
		this.height = this.container.height();

		//Set animation and trigger values
		this.running = false;
		this.transitioning = false;

		// Now for the actual setup of the configuration variables
		var show = this;

		// Find and assign all slides to their holders
		this.container.find('div.slide').each(function(i)
		{
			var i = $(this);
			var h_offset = parseInt(i.css('padding-top'), 10) + parseInt(i.css('padding-bottom'), 10);
			var w_offset = parseInt(i.css('padding-left'), 10) + parseInt(i.css('padding-right'), 10);
			
			i.hide();
			i.css({
				width: show.width - h_offset + 'px',
				height: show.height - w_offset + 'px',
				overflow: 'hidden'
			});
			
			show.slides.push(i);
		});

		// Set up the controls, if any
		this.setControls();
		
		// Prime the first slide to be displayed
		if (this.slides.length > 0)
		{
			this.slides[0].css('left', 'auto');
			this.slides[0].show();
		}

		// Assign actions to hover, if specified
		if (this.hover_stop == true)
		{
			this.container.hover(
				function()
				{
					show.stop();
				},
				function()
				{
					show.play();
				}
			);
		}

		if (this.config.play || false)
		{
			this.play();
		}

		// Add this Slideshow to the registry
		Syn.Slideshow.registry.push(this);
	},
	
	setControls: function()
	{
		if (this.controls)
		{
			if (this.slides.length < 2)
			{
				this.controls.hide();
			}
			else
			{
				this.controls.find('a.ss-previous').connect('click', this, 'showPrevious');
				this.controls.find('a.ss-next').connect('click', this, 'showNext');
				this.controls.find('a.ss-pause').connect('click', this, 'stop');
				this.controls.find('a.ss-stop').connect('click', this, 'stop');
				this.controls.find('a.ss-pause-play').connect('click', this, 'pausePlay');
			}
		}
	},
	
	/**
	 * Toggles the action of the current slide show
	 * @member Syn.Slideshow
	 * @type void
	 */
	pausePlay: function()
	{
		this.trigger('beforeplaypause');
		if (this.timeout_id != null)
		{
			this.stop();
		}
		else
		{
			this.play();
		}
		this.trigger('onplaypause');
	},
	
	/**
	 * Shows the next slide in the series. If we are on the last slide, it loops back to the first.
	 * @member Syn.Slideshow
	 * @type void
	 */
	showNext: function()
	{
		this.trigger('beforenext');

		var x = this.current + 1;
		if (x == this.slides.length)
		{
			x = 0;
		}
		
		var o = this;
		this.change(x, function()
		{
			o.trigger('onnext');
		});
	},
	
	/**
	 * Shows the previous slide in the series. If we are on the first slide, it loops to the last.
	 * @member Syn.Slideshow
	 * @type void
	 */
	showPrevious: function()
	{
		this.trigger('beforeprev');

		var x = this.current - 1;
		if (x < 0)
		{
			x = this.slides.length - 1;
		}
		
		var o = this;
		this.change(x, function()
		{
			o.trigger('onprev');
		});
	},
	
	/**
	 * Processes the transition from the requested slide to the slide at the requested index
	 * @member Syn.Slideshow
	 * @param {int} index The index of the loaded slide which is to be shown
	 * @param {function} callback An optional callback to execute upon completion
	 * @type void
	 */
	change: function(index, callback)
	{
		if (this.slides.length > 1 && !this.transitioning)
		{
			// Kill Timeout, since we don't know if it was manually triggered
			clearTimeout(this.timeout_id);
			this.timeout_id = null;


			var o = this;
			this.transitioning = true;

			var fn = function()
			{
				// Transition is completed, so reset the timeout
				if (o.running || false)
				{
					o.timeout_id = setTimeout(function(){ o.showNext(); }, o.timeout);
				}

				if (callback || false)
				{
					callback();
				}

				// Transition finished
				o.transitioning = false;
				o.trigger('ontransition');
			}

			this.trigger('beforetransition');
			switch (this.transition)
			{
				case Syn.Slideshow.TRANSITION_TYPE_FADE:
					this.fade(index, fn);
					break;
	
				case Syn.Slideshow.TRANSITION_TYPE_SHUTTER:
					this.shutter(index, fn);
					break;
	
				case Syn.Slideshow.TRANSITION_TYPE_SLIDE:
					this.slide(index, fn);
					break;
			}
		}
	},
	
	/**
	 * Fades visibility from the currently visible slide to the slide at the provided index
	 * @member Syn.Slideshow
	 * @param {int} index The index of the slide to which to fade
	 * @param {function} callback Optional callback function to execute upon completion
	 * @type void
	 */
	fade: function(index, callback)
	{
		var slide1 = this.slides[this.current];
		var slide2 = this.slides[index];
		
		var show = this;
		slide1.fadeOut(show.config.fade_speed, function()
		{
			$(this).css('left', '-999em');
			show.current = index;
			if (callback || false)
			{
				callback();
			}
		});
		
		slide2.css('left', 'auto');
		slide2.fadeIn(show.config.fade_speed);
	},
	
	/**
	 * Immediately transitions from the currently visible slide to the slide at the provided index
	 * @member Syn.Slideshow
	 * @param {int} index The index of the slide to which to transition
	 * @param {function} callback Optional callback function to execute upon completion
	 * @type void
	 */
	shutter: function(index, callback)
	{
		var slide1 = this.slides[this.current];
		var slide2 = this.slides[index];

		slide1.hide();
		slide1.css('left', '-999em');
		slide2.css('left', 'auto');
		slide2.show();

		this.current = index;
		if (callback || false)
		{
			callback();
		}
	},
	
	/**
	 * True "sliding" transition. If the member variable slide_direction is set to
	 * one of the 8 compas points (n, s, e, w, ne, nw, se, sw), the transition will
	 * come from that direction. Transition defaults to coming from the east.
	 * @member Syn.Slideshow
	 * @param {int} index The index of the slide to which to transition
	 * @param {function} callback Optional callback function to execute upon completion
	 * @type void
	 */
	slide: function(index, callback)
	{
		var direction = this.slide_direction;
		if (!direction)
		{
			direction = 'e';
		}
		
		var slide1 = this.slides[this.current];
		var slide2 = this.slides[index];
		
		slide1.css('z-index', this.z_index - 10);
		slide2.css({
			zIndex: this.z_index,
			left: 'auto'
		});
		slide2.show();
		
		if (direction.charAt(0) == 'n')
		{
			slide2.css('marginTop', -(slide2.height()) + 'px');
		}
		else if (direction.charAt(0) == 's')
		{
			slide2.css('marginTop', slide2.height() + 'px');
		}
		else
		{
			slide2.css('marginTop', '0');
		}
		
		if (direction.substr(-1) == 'e')
		{
			slide2.css('marginLeft', slide2.width() + 'px');
		}
		else if (direction.substr(-1) == 'w')
		{
			slide2.css('marginLeft', -(slide2.width()) + 'px');
		}
		else
		{
			slide2.css('marginLeft', '0');
		}
		
		var o = this;
		slide2.animate({
			marginLeft: 0,
			marginTop: 0
		}, 1000, null, function()
		{
			slide1.hide();
			o.current = index;
			if (callback || false)
			{
				callback();
			}
		});
		
	},
	
	/**
	 * Sets the transition type for this object
	 * @member Syn.Slideshow
	 * @param {String} type Values: shutter|fade|slide
	 * @type void
	 */
	setTransitionType: function(type)
	{
		if (type == 'shutter')
		{
			this.transition = Syn.Slideshow.TRANSITION_TYPE_SHUTTER;
		}
		else if (type == 'fade')
		{
			this.transition = Syn.Slideshow.TRANSITION_TYPE_FADE;
		}
		else if (type == 'slide')
		{
			this.transition = Syn.Slideshow.TRANSITION_TYPE_SLIDE;
		}
	},
	
	/**
	 * Begin the slideshow animation and set the interval for rotation
	 * @member Syn.Slideshow
	 * @type void
	 */
	play: function()
	{
		this.running = true;
		if (this.timeout_id != null)
		{
			return;
		}
	
		this.trigger('beforeplay');

		var o = this;
		this.timeout_id = setTimeout(function(){ o.showNext(); }, this.timeout);

		this.trigger('onplay');
	},
	
	/**
	 * Stop slideshow animation by clearing the current object's interval
	 * @member Syn.Slideshow
	 * @type void
	 */
	stop: function()
	{
		if (this.timeout_id)
		{
			clearTimeout(this.timeout_id);
		}
		
		this.trigger('beforestop');

		this.timeout_id = null;
		this.running = false;

		this.trigger('onstop');
	},

	/**
	 * Adds a listener to the provided event
	 * @member Syn.Slideshow
	 * @param {String} e The event to which the listener is to be applied
	 * @param {function} fn The listener function
	 */
	addListener : function(e, fn)
	{
		if (this.listeners[e] || false)
		{
			this.listeners[e].push(fn);
		}
	},

	/**
	 * Removes the specified listener function from the provided event
	 * @member Syn.Slideshow
	 * @param {String} e The event from which the listener is to be removed
	 * @param {function} fn The listener to be removed
	 */
	removeListener : function(e, fn)
	{
		if (this.listeners[e] || false)
		{
			var new_listeners = [];
			for (var i = 0; i < this.listeners[e].length; i++)
			{
				if (this.listeners[e][i] != fn)
				{
					new_listeners.push(this.listeners[e][i]);
				}
			}
			this.listeners[e] = new_listeners;
		}
	},

	/**
	 * Clears all listeners from the specified event
	 * @member Syn.Slideshow
	 * @param {String} e The event
	 */
	clearListeners : function(e)
	{
		if (this.listeners[e] || false)
		{
			this.listeners[e] = [];
		}
	},

	/**
	 * Triggers the specified event, executing all listeners
	 * NOTE: All listeners are passed "this" Slideshow object as a parameter
	 * @member Syn.Slideshow
	 * @param {String} e The event
	 */
	trigger : function(e)
	{
		if (this.listeners[e] || false)
		{
			for (var i = 0; i < this.listeners[e].length; i++)
			{
				this.listeners[e][i](this);
			}
		}
	}
});

/**
 * Static member variable: Fade transition type
 */
Syn.Slideshow.TRANSITION_TYPE_FADE    = 0;
/**
 * Static member variable: Shutter transition type
 */
Syn.Slideshow.TRANSITION_TYPE_SHUTTER = 1;
/**
 * Static member variable: Slide transition type
 */
Syn.Slideshow.TRANSITION_TYPE_SLIDE   = 2;

/**
 * Static registry to retain a reference for all slideshows in this context
 */
Syn.Slideshow.registry = [];
;

Syn.CarouselDcc={initialized:false,tab:0,frame:0,frame_count:0,slide_count:0,visible:5,playing:true,frames:[],slideshow_obj:null,anim_duration:500,init:function()
{if(Syn.CarouselDcc.initialized===true)
{return;}
Syn.CarouselDcc.initialized=true;if(Syn.Slideshow.registry.length>0)
{Syn.CarouselDcc.slideshow_obj=Syn.Slideshow.registry[0];}
if(Syn.CarouselDcc.slideshow_obj==null)
{return;}
Syn.CarouselDcc.slideshow_obj.addListener('onnext',function()
{Syn.CarouselDcc.nextSlide();});Syn.CarouselDcc.slideshow_obj.addListener('beforenext',function()
{Syn.CarouselDcc.loadImages();});var dcc=$('#dcc');var slide_names=dcc.find('h2.tab-title');Syn.CarouselDcc.slide_count=slide_names.length;var tabs=[];var l=1;slide_names.each(function(){tabs[l++]=$(this).html();});Syn.CarouselDcc.frame_count=(Syn.CarouselDcc.slide_count<Syn.CarouselDcc.visible)?1:((Syn.CarouselDcc.slide_count%Syn.CarouselDcc.visible===0)?Syn.CarouselDcc.slide_count/Syn.CarouselDcc.visible:Syn.CarouselDcc.slide_count);var tab_ul=dcc.find('.tab-list');var frames=[];for(var i=0;i<Syn.CarouselDcc.frame_count;i++)
{frames[i]={};frames[i].n=i;frames[i].tabs=[];frames[i].el=tab_ul.find('li.carousel_frame').clone();frames[i].el.attr('id','dcc_tabs_frame_'+i);var start=(1+(i*Syn.CarouselDcc.visible))%Syn.CarouselDcc.slide_count;start=(start===0)?Syn.CarouselDcc.slide_count:start;for(var j=0;j<((Syn.CarouselDcc.frame_count>1)?Syn.CarouselDcc.visible:Syn.CarouselDcc.slide_count);j++)
{frames[i].tabs[j]={};next_slide=((start+j)%Syn.CarouselDcc.slide_count);next_slide=(next_slide===0)?Syn.CarouselDcc.slide_count:next_slide;frames[i].tabs[j].n=next_slide;var tab_el=frames[i].el.find('ul li').clone();tab_el.attr('class','carousel_tab tab_'+frames[i].tabs[j].n);tab_el.find('a').html(tabs[next_slide]);if(j==0)
{tab_el.addClass('first');}
frames[i].tabs[j].el=tab_el;}
if(Syn.CarouselDcc.frame_count===1&&Syn.CarouselDcc.slide_count<Syn.CarouselDcc.visible)
{for(var j=Syn.CarouselDcc.slide_count;j<Syn.CarouselDcc.visible;j++)
{frames[i].tabs[j]={};var tab_el=frames[i].el.find('ul li').clone();tab_el.attr('class','carousel_tab');tab_el.find('a').addClass('dummy');frames[i].tabs[j].el=tab_el;}}}
tab_ul.empty();for(var frame_i in frames)
{var frame=frames[frame_i];frame.el.appendTo(tab_ul);tab_ul.find('li#dcc_tabs_frame_'+frame.n+' ul').empty();for(var tab_i in frame.tabs)
{var tab=frame.tabs[tab_i];tab.el.appendTo(tab_ul.find('li#dcc_tabs_frame_'+frame.n+' ul'));}}
for(var k=0;k<Syn.CarouselDcc.slide_count;k++)
{var n=k+1;dcc.find('.tab-list li.tab_'+n).click(function(n){return function(){Syn.CarouselDcc.loadImages();Syn.CarouselDcc.goToTab(n);return false;};}(n));}
Syn.CarouselDcc.frames=frames;Syn.CarouselDcc.frame=0;Syn.CarouselDcc.tab=1;dcc.find('.tab-list li ul li.tab_1').addClass('on');dcc.find('.ss-controls a.ss-pause-play').click(Syn.CarouselDcc.togglePlayPause);dcc.find('.ss-controls a.ss-previous').click(Syn.CarouselDcc.prevSlide);var first_slide=dcc.find('div.slide');$(first_slide[0]).find('span').each(function(){var child=this.firstChild;if(child.nodeType===8)
{$(this).replaceWith(child.nodeValue);}});dcc.find('.ss-controls a.ss-previous').click(function(){Syn.CarouselDcc.loadImages();});dcc.find('.ss-controls a.ss-next').click(function(){Syn.CarouselDcc.loadImages();});$(window).ready(function(){$('#dcc').css('visibility','visible');});},loadImages:function()
{$('#dcc').find('span').each(function(){var child=this.firstChild;if(child.nodeType===8)
{$(this).replaceWith(child.nodeValue);}});},togglePlayPause:function()
{var dcc=$('#dcc');if(Syn.CarouselDcc.playing)
{Syn.CarouselDcc.slideshow_obj.stop();dcc.find('.ss-pause-play span').removeClass('dcc_nav_pause').addClass('dcc_nav_play');Syn.CarouselDcc.playing=false;}
else
{Syn.CarouselDcc.slideshow_obj.play();dcc.find('.ss-pause-play span').removeClass('dcc_nav_play').addClass('dcc_nav_pause');Syn.CarouselDcc.playing=true;}},nextSlide:function()
{var dcc=$('#dcc');dcc.find('.tab-list li ul li.tab_'+Syn.CarouselDcc.tab).removeClass('on');Syn.CarouselDcc.tab++;Syn.CarouselDcc.tab=(Syn.CarouselDcc.tab>Syn.CarouselDcc.slide_count)?1:Syn.CarouselDcc.tab;dcc.find('.tab-list li ul li.tab_'+Syn.CarouselDcc.tab).addClass('on');var curr_frame=Syn.CarouselDcc.frames[Syn.CarouselDcc.frame];if(!Syn.CarouselDcc.tabIsInFrame(Syn.CarouselDcc.tab,curr_frame))
{var from=Syn.CarouselDcc.frame;Syn.CarouselDcc.frame++;Syn.CarouselDcc.frame=(Syn.CarouselDcc.frame==Syn.CarouselDcc.frame_count)?0:Syn.CarouselDcc.frame;Syn.CarouselDcc.frameTransition(from,Syn.CarouselDcc.frame);}},prevSlide:function()
{var dcc=$('#dcc');dcc.find('.tab-list li ul li.tab_'+Syn.CarouselDcc.tab).removeClass('on');Syn.CarouselDcc.tab--;Syn.CarouselDcc.tab=(Syn.CarouselDcc.tab===0)?Syn.CarouselDcc.slide_count:Syn.CarouselDcc.tab;dcc.find('.tab-list li ul li.tab_'+Syn.CarouselDcc.tab).addClass('on');var curr_frame=Syn.CarouselDcc.frames[Syn.CarouselDcc.frame];if(!Syn.CarouselDcc.tabIsInFrame(Syn.CarouselDcc.tab,curr_frame))
{var from=Syn.CarouselDcc.frame;Syn.CarouselDcc.frame--;Syn.CarouselDcc.frame=(Syn.CarouselDcc.frame<0)?Syn.CarouselDcc.frame_count-1:Syn.CarouselDcc.frame;Syn.CarouselDcc.frameTransition(from,Syn.CarouselDcc.frame);}},goToTab:function(n)
{if(Syn.CarouselDcc.tab==n)
{return;}
if(!Syn.CarouselDcc.tabIsInFrame(n,Syn.CarouselDcc.frames[Syn.CarouselDcc.frame]))
{return;}
Syn.CarouselDcc.slideshow_obj.change(n-1);Syn.CarouselDcc.slideshow_obj.current=n-1;var dcc=$('#dcc');dcc.find('.tab-list li ul li.tab_'+Syn.CarouselDcc.tab).removeClass('on');Syn.CarouselDcc.tab=n;dcc.find('.tab-list li ul li.tab_'+Syn.CarouselDcc.tab).addClass('on');return false;},tabIsInFrame:function(nTab,frame)
{for(var tab_i in frame.tabs)
{var tab=frame.tabs[tab_i];if(tab.n==nTab)
{return true;}}
return false;},frameTransition:function(from,to)
{var last_frame=Syn.CarouselDcc.frame_count-1;var from_frame=$('#dcc_tabs_frame_'+from);var to_frame=$('#dcc_tabs_frame_'+to);from_frame.fadeOut(['fast']);to_frame.fadeIn(['fast']);},slideFrameFromRight:function(from,to)
{var from_frame=$('#dcc_tabs_frame_'+from);from_frame.animate({width:'0px'},Syn.CarouselDcc.anim_duration,function(){from_frame.appendTo('#dcc .dcc_nav .tab-list');from_frame.width('550px');});},slideFrameFromLeft:function(from,to)
{var to_frame=$('#dcc_tabs_frame_'+to);to_frame.width('0px');to_frame.prependTo('#dcc .dcc_nav .tab-list');to_frame.animate({width:'550px'},Syn.CarouselDcc.anim_duration);}};;
/**
 * jCarouselLite - jQuery plugin to navigate images/any content in a carousel style widget.
 * @requires jQuery v1.2 or above
 *
 * http://gmarwaha.com/jquery/jcarousellite/
 *
 * Copyright (c) 2007 Ganeshji Marwaha (gmarwaha.com)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Version: 1.0.1
 * Note: Requires jquery 1.2 or above from version 1.0.1
 */

/**
 * Creates a carousel-style navigation widget for images/any-content from a simple HTML markup.
 *
 * The HTML markup that is used to build the carousel can be as simple as...
 *
 *  <div class="carousel">
 *      <ul>
 *          <li><img src="image/1.jpg" alt="1"></li>
 *          <li><img src="image/2.jpg" alt="2"></li>
 *          <li><img src="image/3.jpg" alt="3"></li>
 *      </ul>
 *  </div>
 *
 * As you can see, this snippet is nothing but a simple div containing an unordered list of images.
 * You don't need any special "class" attribute, or a special "css" file for this plugin.
 * I am using a class attribute just for the sake of explanation here.
 *
 * To navigate the elements of the carousel, you need some kind of navigation buttons.
 * For example, you will need a "previous" button to go backward, and a "next" button to go forward.
 * This need not be part of the carousel "div" itself. It can be any element in your page.
 * Lets assume that the following elements in your document can be used as next, and prev buttons...
 *
 * <button class="prev">&lt;&lt;</button>
 * <button class="next">&gt;&gt;</button>
 *
 * Now, all you need to do is call the carousel component on the div element that represents it, and pass in the
 * navigation buttons as options.
 *
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev"
 * });
 *
 * That's it, you would have now converted your raw div, into a magnificient carousel.
 *
 * There are quite a few other options that you can use to customize it though.
 * Each will be explained with an example below.
 *
 * @param an options object - You can specify all the options shown below as an options object param.
 *
 * @option btnPrev, btnNext : string - no defaults
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev"
 * });
 * @desc Creates a basic carousel. Clicking "btnPrev" navigates backwards and "btnNext" navigates forward.
 *
 * @option btnGo - array - no defaults
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      btnGo: [".0", ".1", ".2"]
 * });
 * @desc If you don't want next and previous buttons for navigation, instead you prefer custom navigation based on
 * the item number within the carousel, you can use this option. Just supply an array of selectors for each element
 * in the carousel. The index of the array represents the index of the element. What i mean is, if the
 * first element in the array is ".0", it means that when the element represented by ".0" is clicked, the carousel
 * will slide to the first element and so on and so forth. This feature is very powerful. For example, i made a tabbed
 * interface out of it by making my navigation elements styled like tabs in css. As the carousel is capable of holding
 * any content, not just images, you can have a very simple tabbed navigation in minutes without using any other plugin.
 * The best part is that, the tab will "slide" based on the provided effect. :-)
 *
 * @option mouseWheel : boolean - default is false
 * @example
 * $(".carousel").jCarouselLite({
 *      mouseWheel: true
 * });
 * @desc The carousel can also be navigated using the mouse wheel interface of a scroll mouse instead of using buttons.
 * To get this feature working, you have to do 2 things. First, you have to include the mouse-wheel plugin from brandon.
 * Second, you will have to set the option "mouseWheel" to true. That's it, now you will be able to navigate your carousel
 * using the mouse wheel. Using buttons and mouseWheel or not mutually exclusive. You can still have buttons for navigation
 * as well. They complement each other. To use both together, just supply the options required for both as shown below.
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      mouseWheel: true
 * });
 *
 * @option auto : number - default is null, meaning autoscroll is disabled by default
 * @example
 * $(".carousel").jCarouselLite({
 *      auto: 800,
 *      speed: 500
 * });
 * @desc You can make your carousel auto-navigate itself by specfying a millisecond value in this option.
 * The value you specify is the amount of time between 2 slides. The default is null, and that disables auto scrolling.
 * Specify this value and magically your carousel will start auto scrolling.
 *
 * @option speed : number - 200 is default
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      speed: 800
 * });
 * @desc Specifying a speed will slow-down or speed-up the sliding speed of your carousel. Try it out with
 * different speeds like 800, 600, 1500 etc. Providing 0, will remove the slide effect.
 *
 * @option easing : string - no easing effects by default.
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      easing: "bounceout"
 * });
 * @desc You can specify any easing effect. Note: You need easing plugin for that. Once specified,
 * the carousel will slide based on the provided easing effect.
 *
 * @option vertical : boolean - default is false
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      vertical: true
 * });
 * @desc Determines the direction of the carousel. true, means the carousel will display vertically. The next and
 * prev buttons will slide the items vertically as well. The default is false, which means that the carousel will
 * display horizontally. The next and prev items will slide the items from left-right in this case.
 *
 * @option circular : boolean - default is true
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      circular: false
 * });
 * @desc Setting it to true enables circular navigation. This means, if you click "next" after you reach the last
 * element, you will automatically slide to the first element and vice versa. If you set circular to false, then
 * if you click on the "next" button after you reach the last element, you will stay in the last element itself
 * and similarly for "previous" button and first element.
 *
 * @option visible : number - default is 3
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      visible: 4
 * });
 * @desc This specifies the number of items visible at all times within the carousel. The default is 3.
 * You are even free to experiment with real numbers. Eg: "3.5" will have 3 items fully visible and the
 * last item half visible. This gives you the effect of showing the user that there are more images to the right.
 *
 * @option start : number - default is 0
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      start: 2
 * });
 * @desc You can specify from which item the carousel should start. Remember, the first item in the carousel
 * has a start of 0, and so on.
 *
 * @option scrool : number - default is 1
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      scroll: 2
 * });
 * @desc The number of items that should scroll/slide when you click the next/prev navigation buttons. By
 * default, only one item is scrolled, but you may set it to any number. Eg: setting it to "2" will scroll
 * 2 items when you click the next or previous buttons.
 *
 * @option beforeStart, afterEnd : function - callbacks
 * @example
 * $(".carousel").jCarouselLite({
 *      btnNext: ".next",
 *      btnPrev: ".prev",
 *      beforeStart: function(a) {
 *          alert("Before animation starts:" + a);
 *      },
 *      afterEnd: function(a) {
 *          alert("After animation ends:" + a);
 *      }
 * });
 * @desc If you wanted to do some logic in your page before the slide starts and after the slide ends, you can
 * register these 2 callbacks. The functions will be passed an argument that represents an array of elements that
 * are visible at the time of callback.
 *
 *
 * @cat Plugins/Image Gallery
 * @author Ganeshji Marwaha/ganeshread@gmail.com
 */

(function($) {                                          // Compliant with jquery.noConflict()
$.fn.jCarouselLite = function(o) {
    o = $.extend({
        btnPrev: null,
        btnNext: null,
        btnGo: null,
        mouseWheel: false,
        auto: null,

        speed: 200,
        easing: null,

        vertical: false,
        circular: true,
        visible: 3,
        start: 0,
        scroll: 1,

        beforeStart: null,
        afterEnd: null
    }, o || {});

    return this.each(function() {                           // Returns the element collection. Chainable.
		this.o = o;

        var running = false, animCss=o.vertical?"top":"left", sizeCss=o.vertical?"height":"width";
        var div = $(this), ul = $("ul", div), tLi = $("li", ul), tl = tLi.size(), v = o.visible;

        if(o.circular) {
            ul.prepend(tLi.slice(tl-v-1+1).clone())
              .append(tLi.slice(0,v).clone());
            o.start += v;
        }

        var li = $("li", ul), itemLength = li.size(), curr = o.start;
        div.css("visibility", "visible");

        li.css({overflow: "hidden", float: o.vertical ? "none" : "left"});
        ul.css({margin: "0", padding: "0", position: "relative", "list-style-type": "none", "z-index": "1"});
        div.css({overflow: "hidden", position: "relative", "z-index": "2", left: "0px"});

        var liSize = o.vertical ? height(li) : width(li);   // Full li size(incl margin)-Used for animation
        var ulSize = liSize * itemLength;                   // size of full ul(total length, not just for the visible items)
        var divSize = liSize * v;                           // size of entire div(total length for just the visible items)

        li.css({width: li.width(), height: li.height()});
        ul.css(sizeCss, ulSize+"px").css(animCss, -(curr*liSize));

        div.css(sizeCss, divSize+"px");                     // Width of the DIV. length of visible images

		var self = this;
        if(o.btnPrev)
            $(o.btnPrev).click(function() {
                return self.go(curr-o.scroll);
            });

        if(o.btnNext)
            $(o.btnNext).click(function() {
                return self.go(curr+o.scroll);
            });

        if(o.btnGo)
            $.each(o.btnGo, function(i, val) {
                $(val).click(function() {
                    return self.go(o.circular ? o.visible+i : i);
                });
            });

        if(o.mouseWheel && div.mousewheel)
            div.mousewheel(function(e, d) {
                return d>0 ? self.go(curr-o.scroll) : self.go(curr+o.scroll);
            });

        if(o.auto)
            setInterval(function() {
                self.go(curr+o.scroll);
            }, o.auto+o.speed);

        function vis() {
            return li.slice(curr).slice(0,v);
        };

        this.go = function(to) {
            if(!running) {

                if(o.beforeStart)
                    o.beforeStart.call(this, vis());

                if(o.circular) {            // If circular we are in first or last, then goto the other end
                    if(to<=o.start-v-1) {           // If first, then goto last
                        ul.css(animCss, -((itemLength-(v*2))*liSize)+"px");
                        // If "scroll" > 1, then the "to" might not be equal to the condition; it can be lesser depending on the number of elements.
                        curr = to==o.start-v-1 ? itemLength-(v*2)-1 : itemLength-(v*2)-o.scroll;
                    } else if(to>=itemLength-v+1) { // If last, then goto first
                        ul.css(animCss, -( (v) * liSize ) + "px" );
                        // If "scroll" > 1, then the "to" might not be equal to the condition; it can be greater depending on the number of elements.
                        curr = to==itemLength-v+1 ? v+1 : v+o.scroll;
                    } else curr = to;
                } else {                    // If non-circular and to points to first or last, we just return.
                    if(to<0 || to>itemLength-v) return;
                    else curr = to;
                }                           // If neither overrides it, the curr will still be "to" and we can proceed.

                running = true;

                ul.animate(
                    animCss == "left" ? { left: -(curr*liSize) } : { top: -(curr*liSize) } , o.speed, o.easing,
                    function() {
                        if(o.afterEnd)
                            o.afterEnd.call(this, vis());
                        running = false;
                    }
                );
                // Disable buttons when the carousel reaches the last/first, and enable when not
                if(!o.circular) {
                    $(o.btnPrev + "," + o.btnNext).removeClass("disabled");
                    $( (curr-o.scroll<0 && o.btnPrev)
                        ||
                       (curr+o.scroll > itemLength-v && o.btnNext)
                        ||
                       []
                     ).addClass("disabled");
                }

            }
            return false;
        };
    });
};

function css(el, prop) {
    return parseInt($.css(el[0], prop)) || 0;
};
function width(el) {
    return  el[0].offsetWidth + css(el, 'marginLeft') + css(el, 'marginRight');
};
function height(el) {
    return el[0].offsetHeight + css(el, 'marginTop') + css(el, 'marginBottom');
};

})(jQuery);
;
/**
 * The Syn.Tabbed Component Class
 */

/**
 * Create a Syn.Tabbed component instance
 * @constructor
 */
Syn.Tabbed = Syn.Component.extend(
{
	/**
	 * Initialize the component class. This is called automatically by the default constructor.
	 * @member Syn.Tabbed
	 * @param {Object} config The configuration data structure
	 */
	init: function(config)
	{
		//Init parent class
		this._super(config);
		var cache = (config.cache === undefined) ? true : config.cache;
		this.hrefToAjax($('#' + this.uniqueKey('tabs') + ' li > a'), "changeTabSetup", {cache:cache});
	},

	/**
	 * Called on ajax update.
	 * @member Syn.Tabbed
	 * @param {Object} config The configuration data structure
	 */
	changeTabSetup: function(dom, event)
	{
		this.showLoading({target: this.find('.tabbed_body')});
	}
});
;
/**
 * The Syn.TvEditorsPick Class
 */

/**
 * Create a Syn.TvEditorsPick instance
 * @constructor
 */
Syn.TvEditorsPick = Syn.Component.extend(
{
	/**
	 * Initialize the component class. This is called automatically by the default constructor.
	 * @member Syn.TvEditorsPick
	 * @param {Object} config The configuration data structure
	 */
	init: function(config)
	{
		this._super(config);
		this.uniqueElmt("pagination").find("a").connect("click", this, "showLoading", [{ target: this.find(".loading_body") }]);
		this.hrefToAjax(this.uniqueElmt("pagination").find("a"));
	},

	onAjaxUpdate: function(config)
	{
		this.config = config;
		this.uniqueElmt("pagination").find("a").connect("click", this, "showLoading", [{ target: this.find(".loading_body") }]);
	}
});

;
/**
 * The Syn.Facebook Component Class
 */

/**
 * Create a Syn.Facebook component instance
 * @constrctor
 */
Syn.Facebook = Syn.Component.extend({

	/**
	 * List of friends
	 */
	updates: null,

	/**
	 * Friend name filter
	 */
	search_friend_filter: '',

	/**
	 * Current page in friends list to display
	 */
	page: 1,

	/**
	 * Enables/disables auto-refresh of component
	 */
	auto_refresh_enabled: true,

	/**
	 * Sets auto-refresh rate (in minutes)
	 */
	auto_refresh_rate: 15,

	/**
	 * initialize the component class. This is called automatically by the default constructor.
	 *
	 * @member Syn.Facebook
	 * @param {Object} config The configuration data structure
	 */
	init: function (config)
	{
		this._super(config);
		this.showLoading();
		this.initializeFacebook(config);
	},

	/**
	 * onAjaxUpdate method to re-initialize the component on ajax updates.
	 */
	onAjaxUpdate: function (config)
	{
		this.initializeFacebook(config);
	},

	/**
	 * Initialize facebook 
	 */
	initializeFacebook: function (config)
	{
		this.config = config;
		this.request_url = Syn.Config.Framework.AppServer + 'projects/facebook/request.php';
		var self = this;

		// Facebook API stuff
		FB.init(config.api_key, Syn.Config.Framework.PortalRoot + 'facebook/xd_receiver.htm', {'doNotUseCachedConnectState':true});
		FB.ensureInit(function() 
		{ 
			FB.Connect.get_status().waitUntilReady( 
				function( status ) 
				{ 
					switch ( status ) 
					{ 
						case FB.ConnectState.connected: 
							self.onSessionValidated();
							break; 
						case FB.ConnectState.appNotAuthorized: 
						case FB.ConnectState.userNotLoggedIn:
							self.showLoading();
							FB.Connect.requireSession(
								function(){ self.submit({'action':'auth'}); }, 
								function(){ self.submit(); }); 
					} 
				}
			); 

		});
	},

	onSessionValidated: function()
	{
		var self = this;
		config = this.config;

		this.uniqueElmt('fb_login_button').connect('click', this, 'onLogin');

		if (config.session_key !== null)
		{

			this.auto_refresh_enabled = config.auto_refresh_enabled;
			this.auto_refresh_rate = config.auto_refresh_rate;
			this.showLoading();

			this.container().find('.fb_log_profile').click(function() {
				FB.Connect.logout(function()
				{
					var cname = config.api_key + '_session_key';
					document.cookie = cname + '=; expires=Thu, 01-Jan-1970 00:00:01 GMT';
					self.submit({});
				});
				return false;
			});

			this.container().find('.fb_refresh_profile').connect('click', this, 'forceReload');
			this.container().find('.fb_edit_link').connect('click', this, 'editStatus');
			this.uniqueElmt('search_friend_field').connect('keyup', this, 'searchFriends');
			this.uniqueElmt('search_friend_field').connect('focus', this, 'setSearchBox');
			this.uniqueElmt('search_friend_field').connect('blur', this, 'resetSearchBox');

			FB.ensureInit(function() {
				self.loadProfile();
				self.loadNotifications();
				self.loadFriends();
			});

			if (this.auto_refresh_enabled)
			{
				var rate = this.auto_refresh_rate * 60000;
				window.setTimeout(function() { self.forceReload(); }, (this.auto_refresh_rate * 60000));
			}
		}	
	},

	/**
	 * Called when the user logs into Facebook.
	 */
	onLogin: function(target, event)
	{
		var self = this;
		window.setTimeout(function() { self.forceReload(); }, 0);
	},

	/**
	 * Forces reload of component.
	 */
	forceReload: function()
	{
		this.submit({'action':'auth'});
	},

	/**
	 * Makes a json request given parameters and a callback.
	 */
	makeRequest: function(method, params, callback)
	{
		var json_request = this.request_url;

		params.secure = 0;
		params.method = method;
		params.session_id = this.config.session_key;
		params.api_key = this.config.api_key_encoded;
		params.secret_key = this.config.secret_key;

		if (this.config.timeout !== '')
		{
			params.timeout = encodeURIComponent(this.config.timeout);
		}

		FB.Connect.requireSession(function () {
			$.ajax({ 
				'url' : json_request, 
				'data' : params,
				'success': callback,
				'dataType' : 'jsonp'
			});
		});
	},

	/**
	 * Converts from given timestamp to relative time. Ex: 5 mins ago, 6 days ago
	 */
	convertTimeLocal: function(timestamp)
	{
		var current = Math.round((new Date().getTime()) / 1000);
		var rel_time = current - timestamp;
		var min, hour, day, month;

		if (rel_time < 60)
		{
			return '1 min ago';
		}

		if (rel_time < 3600)
		{
			min = Math.floor(rel_time / 60);
			return min + ' min' + (min > 1 ? 's' : '') + ' ago';
		}

		if (rel_time < 86400)
		{
			hour = Math.floor(rel_time / 3600);
			return hour + ' hour' + (hour > 1 ? 's' : '') + ' ago';
		}

		if (rel_time < 2592000)
		{
			day = Math.floor(rel_time / 86400);
			return day + ' day' + (day > 1 ? 's' : '') + ' ago';
		}

		month = Math.floor(rel_time / 2592000);
		return month + ' month' + (month > 1 ? 's' : '') + ' ago';
	},

	/**
	 * Loads the user's profile data.
	 */
	loadProfile: function()
	{
		var self = this;
		this.makeRequest('users.getid', {}, function (user_id) {
			self.makeRequest('users.getinfo', {uids : user_id, fields : 'name,profile_url,first_name,pic_square,status,wall_count'}, function (result) {
				self.uniqueElmt('user_profile').find('.fb_view_profile').attr('href', result[0].profile_url);
				self.uniqueElmt('user_profile').find('.fb_wall_icon').attr('href', 'http://www.facebook.com/wall.php?id=' + user_id);
				self.uniqueElmt('user_profile').find('.fb_user_img img').attr('src', result[0].pic_square ? result[0].pic_square : 'components/images/facebook/fb_status_no_img.gif');
				self.uniqueElmt('user_profile').find('.fb_status_name').html(result[0].name.length < 15 ? result[0].name : result[0].first_name);

				if (result[0].status.message === null || result[0].status.message == '')
				{
					self.container().find('.fb_status_blank').show();
					self.container().find('.fb_status_view').hide();
				}
				else
				{
					//Break words that are too long to fit
					result[0].status.message = self.breakWords(result[0].status.message);

					self.uniqueElmt('user_profile').find('.fb_status_message').html(result[0].status.message.length > self.config.strlen_user ? result[0].status.message.substr(0, self.config.strlen_user) + '...' : result[0].status.message);
					self.uniqueElmt('fb_new_status').html(result[0].status.message);
					self.uniqueElmt('user_profile').find('.fb_status_time').html(self.convertTimeLocal(result[0].status.time));
					self.uniqueElmt('notification_counts').find('.fb_wall_icon').html((result[0].wall_count ? result[0].wall_count : 0) + (self.config.layout == 'wide' ? ' Wall Posts' : ''));
				}
			});
		});
	},

	/**
	 * Loads the user's notifications.
	 */
	loadNotifications: function()
	{
		var self = this;
		this.makeRequest('notifications.get', {}, function (result) {
			self.uniqueElmt('notification_counts').find('.fb_mail_icon').html((result.messages.unread ? result.messages.unread : 0) + (self.config.layout == 'wide' ? ' New Messages' : ''));
			self.uniqueElmt('notification_counts').find('.fb_request_icon').html((result.friend_requests ? result.friend_requests.length : 0) + (self.config.layout == 'wide' ? ' Friend Requests' : ''));
			self.uniqueElmt('notification_counts').find('.fb_poke_icon').html((result.pokes.unread ? result.pokes.unread : 0) + (self.config.layout == 'wide' ? ' New Pokes' : ''));
		});
	},

	/**
	 * Converts Facebook timestamp to formatted time, either 'HH:MM am' if within
	 * 24 hours, or 'MM/DD/YYYY at HH:MM pm'.
	 */
	formatTime: function(timestamp)
	{
		var time = new Date();
		var now = new Date();
		var hour, ampm;

		time.setTime(timestamp * 1000);

		hour = time.getHours();

		ampm = hour >= 12 ? ' pm' : ' am';
		hour = hour % 12;

		if (hour == 0)
		{
			hour = 12;
		}

		if ((time.getFullYear() == now.getFullYear()) && (time.getMonth() == now.getMonth()) && (time.getDate() == now.getDate()))
		{
			return hour + ':' + (time.getMinutes() < 10 ? '0' + time.getMinutes() : time.getMinutes()) + ampm;
		}
		else
		{
			return (time.getMonth() + 1) + '/' + time.getDate() + '/' + time.getFullYear() + ' at ' + hour + ':' + (time.getMinutes() < 10 ? '0' + time.getMinutes() : time.getMinutes()) + ampm;
		}
	},

	/**
	 * Loads the user's friends feed data. Sorts reverse chronologically, with
	 * most recent entries appearing first.
	 */
	loadFriends: function()
	{
		var self = this;
		this.makeRequest('friends.get', {}, function (result) {

			var ids = '';
			for (var id in result)
			{
				ids = ids + result[id] + ',';
			}
			result = ids.substring(0, ids.length - 1);

			if (result === null || result == '' )
			{
				//No friends
				self.displayUpdates();
			}
			else
			{
				self.makeRequest('users.getinfo', {uids : result, fields : 'name,profile_url,pic_square,status,profile_update_time,sex'}, function (friends) {
					self.updates = new Array();
					var friend;
					for (var i = 0; i < friends.length; i++)
					{
						if (friends[i].status !== null && friends[i].status.message !== null && friends[i].status.message !== '')
						{
							friend = new Object();
							friend.status_class = 'fb_status_update';
							friend.name = friends[i].name;
							friend.profile_url = friends[i].profile_url;

							//Break words that are too long to fit
							friends[i].status.message = self.breakWords(friends[i].status.message);

							friend.status = (friends[i].status.message.length > self.config.strlen_friend) ? friends[i].status.message.substr(0, self.config.strlen_friend) + '...' : friends[i].status.message;
							friend.status_full = friends[i].status.message;
							friend.status_time = self.formatTime(friends[i].status.time);
							friend.status_timestamp = friends[i].status.time;

							self.updates.push(friend);
						}

					}

					self.updates.sort(function (a, b) {
						return (b.status_timestamp - a.status_timestamp);
					});

					self.displayUpdates();
				});
			}
		});
	},

	/**
	 * Switches between the status message and textbox to edit status.
	 */
	editStatus: function()
	{
		this.container().find('.fb_status_view').hide();
		this.container().find('.fb_status_blank').hide();
		this.container().find('.fb_status_edit').show();
		this.uniqueElmt('fb_new_status').select();
		this.uniqueElmt('fb_update_link').connect('click', this, 'setStatus');
		this.uniqueElmt('fb_cancel_link').connect('click', this, 'cancelStatus');

		this.makeRequest('users.hasapppermission', {extperm : 'status_update'}, function(result) {
			if (!result)
			{
				FB.Connect.showPermissionDialog('status_update');
			}
		});
	},

	/**
	 * Updates user's status via AJAX call.
	 */
	setStatus: function(target, event)
	{
		var status_field = this.uniqueElmt('fb_new_status');
		var new_status = $(status_field).val();
		var cur_status = this.container().find('.fb_status_message').html();
		var self = this;

		if (cur_status != new_status)
		{
			this.container().find('.fb_status_message').html(new_status);
			this.container().find('.fb_status_time').html('1 min ago');

			this.makeRequest('status.set', {status : new_status}, function (result) {
				self.postSetStatus();
			});
		}
		else
		{
			this.postSetStatus();
		}
	},

	/**
	 * Called after calling the FacebookServices webservice to update status.
	 */
	postSetStatus: function(result)
	{
		this.container().find('.fb_status_blank').hide();
		this.container().find('.fb_status_edit').hide();
		this.container().find('.fb_status_view').show();
		this.forceReload();
	},

	/**
	 * Resets the user's status when Cancel is clicked while editing status.
	 */
	cancelStatus: function()
	{
		this.uniqueElmt('fb_new_status').attr('value', this.container().find('.fb_status_message').html());
		if (this.container().find('.fb_status_message').html().length == 0)
		{
			this.container().find('.fb_status_blank').show();
		}
		else
		{
			this.container().find('.fb_status_view').show();
		}
		this.container().find('.fb_status_edit').hide();
	},

	/**
	 * Search for friends
	 */
	searchFriends: function(target, event)
	{
		this.page = 1;

		this.container().find('.fb_no_results').hide();
		this.search_friend_filter = $(target).val();
		this.displayUpdates();
		this.container().find('.fb_all_friends_link').show();
		this.container().find('.fb_all_friends_link').connect('click', this, 'clearSearch');
	},

	/**
	 * Reset search area when 'All Friends' link is clicked
	 */
	clearSearch: function()
	{
		this.container().find('.fb_no_results').hide();
		this.uniqueElmt('search_friend_field').removeClass('fb_search_box_active');
		this.uniqueElmt('search_friend_field').attr('value', 'Search Friends');
		this.search_friend_filter = '';
		this.container().find('.fb_all_friends_link').hide();
		this.displayUpdates();
	},

	/**
	 * Resets the 'Search Friends' textbox when focus is removed
	 */
	resetSearchBox: function()
	{
		if (this.search_friend_filter === '')
		{
			this.uniqueElmt('search_friend_field').removeClass('fb_search_box_active');
			this.uniqueElmt('search_friend_field').attr('value', 'Search Friends');
		}
	},

	/**
	 * Sets the 'Search Friends' textbox when focused on
	 */
	setSearchBox: function()
	{
		this.uniqueElmt('search_friend_field').addClass('fb_search_box_active');
		this.uniqueElmt('search_friend_field').attr('value', this.search_friend_filter);
		this.uniqueElmt('search_friend_field').select();
	},

	/**
	 * Display page of friends list
	 */
	displayUpdates: function()
	{
		var per_page = this.config.items_per_page;

		var index = 0;
		this.uniqueElmt('fb_friend_status').html('');
		if (this.updates)
		{
			for (var i = 0; i < this.updates.length; i++)
			{
				var friend = this.updates[i];

				// Do filtering.  Do not display friends who names don't match search_friend_filter property, if set
				if (this.search_friend_filter !== '' && !friend.name.toLowerCase().match(this.search_friend_filter.toLowerCase()))
				{
					continue;
				}

				index++;

				// Is index not in range of current page?
				var current_page_start = ((this.page - 1) * per_page) + 1;
				if (index < current_page_start || index > (current_page_start + (per_page - 1)))
				{
					continue;
				}

				this.uniqueElmt('fb_friend_status').append(this.generateUpdateItem(friend));
			}
		}

		if (index === 0)
		{
			this.container().find('.fb_no_results').show();
			this.container().find('.fb_search_term').text(this.search_friend_filter);
		}

		this.setUpdateItemsPageLinks(index);
	},

	/**
	 * Display a new page
	 */
	updatePage: function(target, event)
	{
		this.page = parseInt($(target).attr('rel'));
		this.displayUpdates();
	},

	/**
	 * Generate the HTML for a friends list item
	 */
	generateUpdateItem: function(update)
	{
		var update_item = this.uniqueElmt('_facebook_content_template').clone();

		update_item.removeAttr('id');
		update_item.attr('class', update.status_class);
		update_item.find('.name').html(update.name);
		update_item.find('.profile_link').attr('href', update.profile_url);
		update_item.find('.profile_link').attr('title', update.name);
		update_item.find('.status').html(update.status);
		update_item.find('.status').attr('title', update.status_full);
		update_item.find('.timestamp').html(update.status_time);

		return update_item;
	},

	/**
	 * Generate the HTML for the friends list page links
	 */
	setUpdateItemsPageLinks: function(item_count)
	{
		var page_count = Math.ceil(item_count / this.config.items_per_page);

		if ((this.page < 1) || (this.page > page_count))
		{
			this.page = 1;
		}

		// Clear out page links
		this.uniqueElmt('fb_pagination').html('');

		// Only show page links if more than 1 page
		if (page_count > 1)
		{
			if (this.page > 1)
			{
				this.uniqueElmt('fb_pagination').append('<a rel="" class="fb_pag_prev" href="#">&laquo; Prev</a> ');
				this.uniqueElmt('fb_pagination').find('.fb_pag_prev').connect('click', this, function() {
					this.page = this.page - 1;
					this.displayUpdates();
				});
			}
			else
			{
				this.uniqueElmt('fb_pagination').append('<span>&laquo; Prev</span> ');
			}

			//Show only five links, starting from two below the current page
			var page_index = this.page - 1;
			if (page_index < 1)
			{
				page_index = 1;
			}

			var limit = page_index + 4;
			if (limit > page_count)
			{
				limit = page_count;
				page_index = page_count - 4;
				if (page_index < 1)
				{
					page_index = 1;
				}
			}

			for (page_index; page_index <= limit; page_index++)
			{
				if (page_index != this.page)
				{
					this.uniqueElmt('fb_pagination').append('<a href="#" rel="' + page_index + '">' + page_index + '</a> ');
				}
				else
				{
					this.uniqueElmt('fb_pagination').append('<span class="on">' + page_index + '</span> ');
				}
			}

			if ((page_count > 1) && (this.page < page_count))
			{
				this.uniqueElmt('fb_pagination').append('<a class="fb_pag_next" rel="" href="#">Next &raquo;</a>');
				this.uniqueElmt('fb_pagination').find('.fb_pag_next').connect('click', this, function() {
					this.page = this.page + 1;
					this.displayUpdates();
				});
			}
			else
			{
				this.uniqueElmt('fb_pagination').append('<span>Next &raquo;</span>');
			}

			// Bind page links to update page method
			this.uniqueElmt('fb_pagination').find('a:not(.fb_pag_prev,.fb_pag_next)').connect('click', this, 'updatePage');
		}

		this.hideLoading();
	},

	/**
	 * Takes a string and insert breaks into words that are too long
	 * @param string text The text with words that need to be broken
	 * @return string The input string returned with breaks inserted where needed
	 */
	breakWords: function(text)
	{
		var maxWordLength = 30;
		var stringWords = text.split(' ');

		for (var i = 0; i < stringWords.length; i++)
		{
			if (stringWords[i].length > maxWordLength)
			{
				for (var j = maxWordLength; j < stringWords[i].length; j += maxWordLength)
				{
					stringWords[i] = stringWords[i].substr(0, j) + '<wbr />' + stringWords[i].substr(j, stringWords[i].length);
				}
			}
		}

		return stringWords.join(' ');
	}
});
;
