/*
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 2.6.0

This notice only applies to this section.

*/
if(typeof YAHOO=="undefined"||!YAHOO){var YAHOO={};}YAHOO.namespace=function(){var A=arguments,E=null,C,B,D;for(C=0;C<A.length;C=C+1){D=A[C].split(".");E=YAHOO;for(B=(D[0]=="YAHOO")?1:0;B<D.length;B=B+1){E[D[B]]=E[D[B]]||{};E=E[D[B]];}}return E;};YAHOO.log=function(D,A,C){var B=YAHOO.widget.Logger;if(B&&B.log){return B.log(D,A,C);}else{return false;}};YAHOO.register=function(A,E,D){var I=YAHOO.env.modules;if(!I[A]){I[A]={versions:[],builds:[]};}var B=I[A],H=D.version,G=D.build,F=YAHOO.env.listeners;B.name=A;B.version=H;B.build=G;B.versions.push(H);B.builds.push(G);B.mainClass=E;for(var C=0;C<F.length;C=C+1){F[C](B);}if(E){E.VERSION=H;E.BUILD=G;}else{YAHOO.log("mainClass is undefined for module "+A,"warn");}};YAHOO.env=YAHOO.env||{modules:[],listeners:[]};YAHOO.env.getVersion=function(A){return YAHOO.env.modules[A]||null;};YAHOO.env.ua=function(){var C={ie:0,opera:0,gecko:0,webkit:0,mobile:null,air:0};var B=navigator.userAgent,A;if((/KHTML/).test(B)){C.webkit=1;}A=B.match(/AppleWebKit\/([^\s]*)/);if(A&&A[1]){C.webkit=parseFloat(A[1]);if(/ Mobile\//.test(B)){C.mobile="Apple";}else{A=B.match(/NokiaN[^\/]*/);if(A){C.mobile=A[0];}}A=B.match(/AdobeAIR\/([^\s]*)/);if(A){C.air=A[0];}}if(!C.webkit){A=B.match(/Opera[\s\/]([^\s]*)/);if(A&&A[1]){C.opera=parseFloat(A[1]);A=B.match(/Opera Mini[^;]*/);if(A){C.mobile=A[0];}}else{A=B.match(/MSIE\s([^;]*)/);if(A&&A[1]){C.ie=parseFloat(A[1]);}else{A=B.match(/Gecko\/([^\s]*)/);if(A){C.gecko=1;A=B.match(/rv:([^\s\)]*)/);if(A&&A[1]){C.gecko=parseFloat(A[1]);}}}}}return C;}();(function(){YAHOO.namespace("util","widget","example");if("undefined"!==typeof YAHOO_config){var B=YAHOO_config.listener,A=YAHOO.env.listeners,D=true,C;if(B){for(C=0;C<A.length;C=C+1){if(A[C]==B){D=false;break;}}if(D){A.push(B);}}}})();YAHOO.lang=YAHOO.lang||{};(function(){var A=YAHOO.lang,C=["toString","valueOf"],B={isArray:function(D){if(D){return A.isNumber(D.length)&&A.isFunction(D.splice);}return false;},isBoolean:function(D){return typeof D==="boolean";},isFunction:function(D){return typeof D==="function";},isNull:function(D){return D===null;},isNumber:function(D){return typeof D==="number"&&isFinite(D);},isObject:function(D){return(D&&(typeof D==="object"||A.isFunction(D)))||false;},isString:function(D){return typeof D==="string";},isUndefined:function(D){return typeof D==="undefined";},_IEEnumFix:(YAHOO.env.ua.ie)?function(F,E){for(var D=0;D<C.length;D=D+1){var H=C[D],G=E[H];if(A.isFunction(G)&&G!=Object.prototype[H]){F[H]=G;}}}:function(){},extend:function(H,I,G){if(!I||!H){throw new Error("extend failed, please check that "+"all dependencies are included.");}var E=function(){};E.prototype=I.prototype;H.prototype=new E();H.prototype.constructor=H;H.superclass=I.prototype;if(I.prototype.constructor==Object.prototype.constructor){I.prototype.constructor=I;}if(G){for(var D in G){if(A.hasOwnProperty(G,D)){H.prototype[D]=G[D];}}A._IEEnumFix(H.prototype,G);}},augmentObject:function(H,G){if(!G||!H){throw new Error("Absorb failed, verify dependencies.");}var D=arguments,F,I,E=D[2];if(E&&E!==true){for(F=2;F<D.length;F=F+1){H[D[F]]=G[D[F]];}}else{for(I in G){if(E||!(I in H)){H[I]=G[I];}}A._IEEnumFix(H,G);}},augmentProto:function(G,F){if(!F||!G){throw new Error("Augment failed, verify dependencies.");}var D=[G.prototype,F.prototype];for(var E=2;E<arguments.length;E=E+1){D.push(arguments[E]);}A.augmentObject.apply(this,D);},dump:function(D,I){var F,H,K=[],L="{...}",E="f(){...}",J=", ",G=" => ";if(!A.isObject(D)){return D+"";}else{if(D instanceof Date||("nodeType" in D&&"tagName" in D)){return D;}else{if(A.isFunction(D)){return E;}}}I=(A.isNumber(I))?I:3;if(A.isArray(D)){K.push("[");for(F=0,H=D.length;F<H;F=F+1){if(A.isObject(D[F])){K.push((I>0)?A.dump(D[F],I-1):L);}else{K.push(D[F]);}K.push(J);}if(K.length>1){K.pop();}K.push("]");}else{K.push("{");for(F in D){if(A.hasOwnProperty(D,F)){K.push(F+G);if(A.isObject(D[F])){K.push((I>0)?A.dump(D[F],I-1):L);}else{K.push(D[F]);}K.push(J);}}if(K.length>1){K.pop();}K.push("}");}return K.join("");},substitute:function(S,E,L){var I,H,G,O,P,R,N=[],F,J="dump",M=" ",D="{",Q="}";for(;;){I=S.lastIndexOf(D);if(I<0){break;}H=S.indexOf(Q,I);if(I+1>=H){break;}F=S.substring(I+1,H);O=F;R=null;G=O.indexOf(M);if(G>-1){R=O.substring(G+1);O=O.substring(0,G);}P=E[O];if(L){P=L(O,P,R);}if(A.isObject(P)){if(A.isArray(P)){P=A.dump(P,parseInt(R,10));}else{R=R||"";var K=R.indexOf(J);if(K>-1){R=R.substring(4);}if(P.toString===Object.prototype.toString||K>-1){P=A.dump(P,parseInt(R,10));}else{P=P.toString();}}}else{if(!A.isString(P)&&!A.isNumber(P)){P="~-"+N.length+"-~";N[N.length]=F;}}S=S.substring(0,I)+P+S.substring(H+1);}for(I=N.length-1;I>=0;I=I-1){S=S.replace(new RegExp("~-"+I+"-~"),"{"+N[I]+"}","g");}return S;},trim:function(D){try{return D.replace(/^\s+|\s+$/g,"");}catch(E){return D;}},merge:function(){var G={},E=arguments;for(var F=0,D=E.length;F<D;F=F+1){A.augmentObject(G,E[F],true);}return G;},later:function(K,E,L,G,H){K=K||0;E=E||{};var F=L,J=G,I,D;if(A.isString(L)){F=E[L];}if(!F){throw new TypeError("method undefined");}if(!A.isArray(J)){J=[G];}I=function(){F.apply(E,J);};D=(H)?setInterval(I,K):setTimeout(I,K);return{interval:H,cancel:function(){if(this.interval){clearInterval(D);}else{clearTimeout(D);}}};},isValue:function(D){return(A.isObject(D)||A.isString(D)||A.isNumber(D)||A.isBoolean(D));}};A.hasOwnProperty=(Object.prototype.hasOwnProperty)?function(D,E){return D&&D.hasOwnProperty(E);}:function(D,E){return !A.isUndefined(D[E])&&D.constructor.prototype[E]!==D[E];};B.augmentObject(A,B,true);YAHOO.util.Lang=A;A.augment=A.augmentProto;YAHOO.augment=A.augmentProto;YAHOO.extend=A.extend;})();YAHOO.register("yahoo",YAHOO,{version:"2.6.0",build:"1321"});(function(){var B=YAHOO.util,F=YAHOO.lang,L,J,K={},G={},N=window.document;YAHOO.env._id_counter=YAHOO.env._id_counter||0;var C=YAHOO.env.ua.opera,M=YAHOO.env.ua.webkit,A=YAHOO.env.ua.gecko,H=YAHOO.env.ua.ie;var E={HYPHEN:/(-[a-z])/i,ROOT_TAG:/^body|html$/i,OP_SCROLL:/^(?:inline|table-row)$/i};var O=function(Q){if(!E.HYPHEN.test(Q)){return Q;}if(K[Q]){return K[Q];}var R=Q;while(E.HYPHEN.exec(R)){R=R.replace(RegExp.$1,RegExp.$1.substr(1).toUpperCase());}K[Q]=R;return R;};var P=function(R){var Q=G[R];if(!Q){Q=new RegExp("(?:^|\\s+)"+R+"(?:\\s+|$)");G[R]=Q;}return Q;};if(N.defaultView&&N.defaultView.getComputedStyle){L=function(Q,T){var S=null;if(T=="float"){T="cssFloat";}var R=Q.ownerDocument.defaultView.getComputedStyle(Q,"");if(R){S=R[O(T)];}return Q.style[T]||S;};}else{if(N.documentElement.currentStyle&&H){L=function(Q,S){switch(O(S)){case"opacity":var U=100;try{U=Q.filters["DXImageTransform.Microsoft.Alpha"].opacity;}catch(T){try{U=Q.filters("alpha").opacity;}catch(T){}}return U/100;case"float":S="styleFloat";default:var R=Q.currentStyle?Q.currentStyle[S]:null;return(Q.style[S]||R);}};}else{L=function(Q,R){return Q.style[R];};}}if(H){J=function(Q,R,S){switch(R){case"opacity":if(F.isString(Q.style.filter)){Q.style.filter="alpha(opacity="+S*100+")";if(!Q.currentStyle||!Q.currentStyle.hasLayout){Q.style.zoom=1;}}break;case"float":R="styleFloat";default:Q.style[R]=S;}};}else{J=function(Q,R,S){if(R=="float"){R="cssFloat";}Q.style[R]=S;};}var D=function(Q,R){return Q&&Q.nodeType==1&&(!R||R(Q));};YAHOO.util.Dom={get:function(S){if(S){if(S.nodeType||S.item){return S;}if(typeof S==="string"){return N.getElementById(S);}if("length" in S){var T=[];for(var R=0,Q=S.length;R<Q;++R){T[T.length]=B.Dom.get(S[R]);}return T;}return S;}return null;},getStyle:function(Q,S){S=O(S);var R=function(T){return L(T,S);};return B.Dom.batch(Q,R,B.Dom,true);},setStyle:function(Q,S,T){S=O(S);var R=function(U){J(U,S,T);};B.Dom.batch(Q,R,B.Dom,true);},getXY:function(Q){var R=function(S){if((S.parentNode===null||S.offsetParent===null||this.getStyle(S,"display")=="none")&&S!=S.ownerDocument.body){return false;}return I(S);};return B.Dom.batch(Q,R,B.Dom,true);},getX:function(Q){var R=function(S){return B.Dom.getXY(S)[0];};return B.Dom.batch(Q,R,B.Dom,true);},getY:function(Q){var R=function(S){return B.Dom.getXY(S)[1];};return B.Dom.batch(Q,R,B.Dom,true);},setXY:function(Q,T,S){var R=function(W){var V=this.getStyle(W,"position");if(V=="static"){this.setStyle(W,"position","relative");V="relative";}var Y=this.getXY(W);if(Y===false){return false;}var X=[parseInt(this.getStyle(W,"left"),10),parseInt(this.getStyle(W,"top"),10)];if(isNaN(X[0])){X[0]=(V=="relative")?0:W.offsetLeft;}if(isNaN(X[1])){X[1]=(V=="relative")?0:W.offsetTop;}if(T[0]!==null){W.style.left=T[0]-Y[0]+X[0]+"px";}if(T[1]!==null){W.style.top=T[1]-Y[1]+X[1]+"px";}if(!S){var U=this.getXY(W);if((T[0]!==null&&U[0]!=T[0])||(T[1]!==null&&U[1]!=T[1])){this.setXY(W,T,true);}}};B.Dom.batch(Q,R,B.Dom,true);},setX:function(R,Q){B.Dom.setXY(R,[Q,null]);},setY:function(Q,R){B.Dom.setXY(Q,[null,R]);},getRegion:function(Q){var R=function(S){if((S.parentNode===null||S.offsetParent===null||this.getStyle(S,"display")=="none")&&S!=S.ownerDocument.body){return false;}var T=B.Region.getRegion(S);return T;};return B.Dom.batch(Q,R,B.Dom,true);},getClientWidth:function(){return B.Dom.getViewportWidth();},getClientHeight:function(){return B.Dom.getViewportHeight();},getElementsByClassName:function(U,Y,V,W){U=F.trim(U);Y=Y||"*";V=(V)?B.Dom.get(V):null||N;if(!V){return[];}var R=[],Q=V.getElementsByTagName(Y),X=P(U);for(var S=0,T=Q.length;S<T;++S){if(X.test(Q[S].className)){R[R.length]=Q[S];if(W){W.call(Q[S],Q[S]);}}}return R;},hasClass:function(S,R){var Q=P(R);var T=function(U){return Q.test(U.className);};return B.Dom.batch(S,T,B.Dom,true);},addClass:function(R,Q){var S=function(T){if(this.hasClass(T,Q)){return false;}T.className=F.trim([T.className,Q].join(" "));return true;};return B.Dom.batch(R,S,B.Dom,true);},removeClass:function(S,R){var Q=P(R);var T=function(W){var V=false,X=W.className;if(R&&X&&this.hasClass(W,R)){W.className=X.replace(Q," ");if(this.hasClass(W,R)){this.removeClass(W,R);}W.className=F.trim(W.className);if(W.className===""){var U=(W.hasAttribute)?"class":"className";W.removeAttribute(U);}V=true;}return V;};return B.Dom.batch(S,T,B.Dom,true);},replaceClass:function(T,R,Q){if(!Q||R===Q){return false;}var S=P(R);var U=function(V){if(!this.hasClass(V,R)){this.addClass(V,Q);return true;}V.className=V.className.replace(S," "+Q+" ");if(this.hasClass(V,R)){this.removeClass(V,R);}V.className=F.trim(V.className);return true;};return B.Dom.batch(T,U,B.Dom,true);},generateId:function(Q,S){S=S||"yui-gen";var R=function(T){if(T&&T.id){return T.id;}var U=S+YAHOO.env._id_counter++;if(T){T.id=U;}return U;};return B.Dom.batch(Q,R,B.Dom,true)||R.apply(B.Dom,arguments);},isAncestor:function(R,S){R=B.Dom.get(R);S=B.Dom.get(S);var Q=false;if((R&&S)&&(R.nodeType&&S.nodeType)){if(R.contains&&R!==S){Q=R.contains(S);}else{if(R.compareDocumentPosition){Q=!!(R.compareDocumentPosition(S)&16);}}}else{}return Q;},inDocument:function(Q){return this.isAncestor(N.documentElement,Q);},getElementsBy:function(X,R,S,U){R=R||"*";S=(S)?B.Dom.get(S):null||N;if(!S){return[];}var T=[],W=S.getElementsByTagName(R);for(var V=0,Q=W.length;V<Q;++V){if(X(W[V])){T[T.length]=W[V];if(U){U(W[V]);}}}return T;},batch:function(U,X,W,S){U=(U&&(U.tagName||U.item))?U:B.Dom.get(U);if(!U||!X){return false;}var T=(S)?W:window;if(U.tagName||U.length===undefined){return X.call(T,U,W);}var V=[];for(var R=0,Q=U.length;R<Q;++R){V[V.length]=X.call(T,U[R],W);}return V;},getDocumentHeight:function(){var R=(N.compatMode!="CSS1Compat")?N.body.scrollHeight:N.documentElement.scrollHeight;var Q=Math.max(R,B.Dom.getViewportHeight());return Q;},getDocumentWidth:function(){var R=(N.compatMode!="CSS1Compat")?N.body.scrollWidth:N.documentElement.scrollWidth;var Q=Math.max(R,B.Dom.getViewportWidth());return Q;},getViewportHeight:function(){var Q=self.innerHeight;
var R=N.compatMode;if((R||H)&&!C){Q=(R=="CSS1Compat")?N.documentElement.clientHeight:N.body.clientHeight;}return Q;},getViewportWidth:function(){var Q=self.innerWidth;var R=N.compatMode;if(R||H){Q=(R=="CSS1Compat")?N.documentElement.clientWidth:N.body.clientWidth;}return Q;},getAncestorBy:function(Q,R){while((Q=Q.parentNode)){if(D(Q,R)){return Q;}}return null;},getAncestorByClassName:function(R,Q){R=B.Dom.get(R);if(!R){return null;}var S=function(T){return B.Dom.hasClass(T,Q);};return B.Dom.getAncestorBy(R,S);},getAncestorByTagName:function(R,Q){R=B.Dom.get(R);if(!R){return null;}var S=function(T){return T.tagName&&T.tagName.toUpperCase()==Q.toUpperCase();};return B.Dom.getAncestorBy(R,S);},getPreviousSiblingBy:function(Q,R){while(Q){Q=Q.previousSibling;if(D(Q,R)){return Q;}}return null;},getPreviousSibling:function(Q){Q=B.Dom.get(Q);if(!Q){return null;}return B.Dom.getPreviousSiblingBy(Q);},getNextSiblingBy:function(Q,R){while(Q){Q=Q.nextSibling;if(D(Q,R)){return Q;}}return null;},getNextSibling:function(Q){Q=B.Dom.get(Q);if(!Q){return null;}return B.Dom.getNextSiblingBy(Q);},getFirstChildBy:function(Q,S){var R=(D(Q.firstChild,S))?Q.firstChild:null;return R||B.Dom.getNextSiblingBy(Q.firstChild,S);},getFirstChild:function(Q,R){Q=B.Dom.get(Q);if(!Q){return null;}return B.Dom.getFirstChildBy(Q);},getLastChildBy:function(Q,S){if(!Q){return null;}var R=(D(Q.lastChild,S))?Q.lastChild:null;return R||B.Dom.getPreviousSiblingBy(Q.lastChild,S);},getLastChild:function(Q){Q=B.Dom.get(Q);return B.Dom.getLastChildBy(Q);},getChildrenBy:function(R,T){var S=B.Dom.getFirstChildBy(R,T);var Q=S?[S]:[];B.Dom.getNextSiblingBy(S,function(U){if(!T||T(U)){Q[Q.length]=U;}return false;});return Q;},getChildren:function(Q){Q=B.Dom.get(Q);if(!Q){}return B.Dom.getChildrenBy(Q);},getDocumentScrollLeft:function(Q){Q=Q||N;return Math.max(Q.documentElement.scrollLeft,Q.body.scrollLeft);},getDocumentScrollTop:function(Q){Q=Q||N;return Math.max(Q.documentElement.scrollTop,Q.body.scrollTop);},insertBefore:function(R,Q){R=B.Dom.get(R);Q=B.Dom.get(Q);if(!R||!Q||!Q.parentNode){return null;}return Q.parentNode.insertBefore(R,Q);},insertAfter:function(R,Q){R=B.Dom.get(R);Q=B.Dom.get(Q);if(!R||!Q||!Q.parentNode){return null;}if(Q.nextSibling){return Q.parentNode.insertBefore(R,Q.nextSibling);}else{return Q.parentNode.appendChild(R);}},getClientRegion:function(){var S=B.Dom.getDocumentScrollTop(),R=B.Dom.getDocumentScrollLeft(),T=B.Dom.getViewportWidth()+R,Q=B.Dom.getViewportHeight()+S;return new B.Region(S,T,Q,R);}};var I=function(){if(N.documentElement.getBoundingClientRect){return function(S){var T=S.getBoundingClientRect(),R=Math.round;var Q=S.ownerDocument;return[R(T.left+B.Dom.getDocumentScrollLeft(Q)),R(T.top+B.Dom.getDocumentScrollTop(Q))];};}else{return function(S){var T=[S.offsetLeft,S.offsetTop];var R=S.offsetParent;var Q=(M&&B.Dom.getStyle(S,"position")=="absolute"&&S.offsetParent==S.ownerDocument.body);if(R!=S){while(R){T[0]+=R.offsetLeft;T[1]+=R.offsetTop;if(!Q&&M&&B.Dom.getStyle(R,"position")=="absolute"){Q=true;}R=R.offsetParent;}}if(Q){T[0]-=S.ownerDocument.body.offsetLeft;T[1]-=S.ownerDocument.body.offsetTop;}R=S.parentNode;while(R.tagName&&!E.ROOT_TAG.test(R.tagName)){if(R.scrollTop||R.scrollLeft){T[0]-=R.scrollLeft;T[1]-=R.scrollTop;}R=R.parentNode;}return T;};}}();})();YAHOO.util.Region=function(C,D,A,B){this.top=C;this[1]=C;this.right=D;this.bottom=A;this.left=B;this[0]=B;};YAHOO.util.Region.prototype.contains=function(A){return(A.left>=this.left&&A.right<=this.right&&A.top>=this.top&&A.bottom<=this.bottom);};YAHOO.util.Region.prototype.getArea=function(){return((this.bottom-this.top)*(this.right-this.left));};YAHOO.util.Region.prototype.intersect=function(E){var C=Math.max(this.top,E.top);var D=Math.min(this.right,E.right);var A=Math.min(this.bottom,E.bottom);var B=Math.max(this.left,E.left);if(A>=C&&D>=B){return new YAHOO.util.Region(C,D,A,B);}else{return null;}};YAHOO.util.Region.prototype.union=function(E){var C=Math.min(this.top,E.top);var D=Math.max(this.right,E.right);var A=Math.max(this.bottom,E.bottom);var B=Math.min(this.left,E.left);return new YAHOO.util.Region(C,D,A,B);};YAHOO.util.Region.prototype.toString=function(){return("Region {"+"top: "+this.top+", right: "+this.right+", bottom: "+this.bottom+", left: "+this.left+"}");};YAHOO.util.Region.getRegion=function(D){var F=YAHOO.util.Dom.getXY(D);var C=F[1];var E=F[0]+D.offsetWidth;var A=F[1]+D.offsetHeight;var B=F[0];return new YAHOO.util.Region(C,E,A,B);};YAHOO.util.Point=function(A,B){if(YAHOO.lang.isArray(A)){B=A[1];A=A[0];}this.x=this.right=this.left=this[0]=A;this.y=this.top=this.bottom=this[1]=B;};YAHOO.util.Point.prototype=new YAHOO.util.Region();YAHOO.register("dom",YAHOO.util.Dom,{version:"2.6.0",build:"1321"});YAHOO.util.CustomEvent=function(D,B,C,A){this.type=D;this.scope=B||window;this.silent=C;this.signature=A||YAHOO.util.CustomEvent.LIST;this.subscribers=[];if(!this.silent){}var E="_YUICEOnSubscribe";if(D!==E){this.subscribeEvent=new YAHOO.util.CustomEvent(E,this,true);}this.lastError=null;};YAHOO.util.CustomEvent.LIST=0;YAHOO.util.CustomEvent.FLAT=1;YAHOO.util.CustomEvent.prototype={subscribe:function(B,C,A){if(!B){throw new Error("Invalid callback for subscriber to '"+this.type+"'");}if(this.subscribeEvent){this.subscribeEvent.fire(B,C,A);}this.subscribers.push(new YAHOO.util.Subscriber(B,C,A));},unsubscribe:function(D,F){if(!D){return this.unsubscribeAll();}var E=false;for(var B=0,A=this.subscribers.length;B<A;++B){var C=this.subscribers[B];if(C&&C.contains(D,F)){this._delete(B);E=true;}}return E;},fire:function(){this.lastError=null;var K=[],E=this.subscribers.length;if(!E&&this.silent){return true;}var I=[].slice.call(arguments,0),G=true,D,J=false;if(!this.silent){}var C=this.subscribers.slice(),A=YAHOO.util.Event.throwErrors;for(D=0;D<E;++D){var M=C[D];if(!M){J=true;}else{if(!this.silent){}var L=M.getScope(this.scope);if(this.signature==YAHOO.util.CustomEvent.FLAT){var B=null;if(I.length>0){B=I[0];}try{G=M.fn.call(L,B,M.obj);}catch(F){this.lastError=F;if(A){throw F;}}}else{try{G=M.fn.call(L,this.type,I,M.obj);}catch(H){this.lastError=H;if(A){throw H;}}}if(false===G){if(!this.silent){}break;}}}return(G!==false);},unsubscribeAll:function(){for(var A=this.subscribers.length-1;A>-1;A--){this._delete(A);}this.subscribers=[];return A;},_delete:function(A){var B=this.subscribers[A];if(B){delete B.fn;delete B.obj;}this.subscribers.splice(A,1);},toString:function(){return"CustomEvent: "+"'"+this.type+"', "+"scope: "+this.scope;}};YAHOO.util.Subscriber=function(B,C,A){this.fn=B;this.obj=YAHOO.lang.isUndefined(C)?null:C;this.override=A;};YAHOO.util.Subscriber.prototype.getScope=function(A){if(this.override){if(this.override===true){return this.obj;}else{return this.override;}}return A;};YAHOO.util.Subscriber.prototype.contains=function(A,B){if(B){return(this.fn==A&&this.obj==B);}else{return(this.fn==A);}};YAHOO.util.Subscriber.prototype.toString=function(){return"Subscriber { obj: "+this.obj+", override: "+(this.override||"no")+" }";};if(!YAHOO.util.Event){YAHOO.util.Event=function(){var H=false;var I=[];var J=[];var G=[];var E=[];var C=0;var F=[];var B=[];var A=0;var D={63232:38,63233:40,63234:37,63235:39,63276:33,63277:34,25:9};var K=YAHOO.env.ua.ie?"focusin":"focus";var L=YAHOO.env.ua.ie?"focusout":"blur";return{POLL_RETRYS:2000,POLL_INTERVAL:20,EL:0,TYPE:1,FN:2,WFN:3,UNLOAD_OBJ:3,ADJ_SCOPE:4,OBJ:5,OVERRIDE:6,CAPTURE:7,lastError:null,isSafari:YAHOO.env.ua.webkit,webkit:YAHOO.env.ua.webkit,isIE:YAHOO.env.ua.ie,_interval:null,_dri:null,DOMReady:false,throwErrors:false,startInterval:function(){if(!this._interval){var M=this;var N=function(){M._tryPreloadAttach();};this._interval=setInterval(N,this.POLL_INTERVAL);}},onAvailable:function(R,O,S,Q,P){var M=(YAHOO.lang.isString(R))?[R]:R;for(var N=0;N<M.length;N=N+1){F.push({id:M[N],fn:O,obj:S,override:Q,checkReady:P});}C=this.POLL_RETRYS;this.startInterval();},onContentReady:function(O,M,P,N){this.onAvailable(O,M,P,N,true);},onDOMReady:function(M,O,N){if(this.DOMReady){setTimeout(function(){var P=window;if(N){if(N===true){P=O;}else{P=N;}}M.call(P,"DOMReady",[],O);},0);}else{this.DOMReadyEvent.subscribe(M,O,N);}},_addListener:function(O,M,X,S,N,a){if(!X||!X.call){return false;}if(this._isValidCollection(O)){var Y=true;for(var T=0,V=O.length;T<V;++T){Y=this._addListener(O[T],M,X,S,N,a)&&Y;}return Y;}else{if(YAHOO.lang.isString(O)){var R=this.getEl(O);if(R){O=R;}else{this.onAvailable(O,function(){YAHOO.util.Event._addListener(O,M,X,S,N,a);});return true;}}}if(!O){return false;}if("unload"==M&&S!==this){J[J.length]=[O,M,X,S,N,a];return true;}var b=O;if(N){if(N===true){b=S;}else{b=N;}}var P=function(c){return X.call(b,YAHOO.util.Event.getEvent(c,O),S);};var Z=[O,M,X,P,b,S,N,a];var U=I.length;I[U]=Z;if(this.useLegacyEvent(O,M)){var Q=this.getLegacyIndex(O,M);if(Q==-1||O!=G[Q][0]){Q=G.length;B[O.id+M]=Q;G[Q]=[O,M,O["on"+M]];E[Q]=[];O["on"+M]=function(c){YAHOO.util.Event.fireLegacyEvent(YAHOO.util.Event.getEvent(c),Q);};}E[Q].push(Z);}else{try{this._simpleAdd(O,M,P,a);}catch(W){this.lastError=W;this._removeListener(O,M,X,a);return false;}}return true;},addListener:function(O,Q,N,P,M){return this._addListener(O,Q,N,P,M,false);},addFocusListener:function(O,N,P,M){return this._addListener(O,K,N,P,M,true);},removeFocusListener:function(N,M){return this._removeListener(N,K,M,true);},addBlurListener:function(O,N,P,M){return this._addListener(O,L,N,P,M,true);},removeBlurListener:function(N,M){return this._removeListener(N,L,M,true);},fireLegacyEvent:function(Q,O){var S=true,M,U,T,V,R;U=E[O].slice();for(var N=0,P=U.length;N<P;++N){T=U[N];if(T&&T[this.WFN]){V=T[this.ADJ_SCOPE];R=T[this.WFN].call(V,Q);S=(S&&R);}}M=G[O];if(M&&M[2]){M[2](Q);}return S;},getLegacyIndex:function(N,O){var M=this.generateId(N)+O;if(typeof B[M]=="undefined"){return -1;}else{return B[M];}},useLegacyEvent:function(M,N){return(this.webkit&&this.webkit<419&&("click"==N||"dblclick"==N));},_removeListener:function(N,M,V,Y){var Q,T,X;if(typeof N=="string"){N=this.getEl(N);}else{if(this._isValidCollection(N)){var W=true;for(Q=N.length-1;Q>-1;Q--){W=(this._removeListener(N[Q],M,V,Y)&&W);}return W;}}if(!V||!V.call){return this.purgeElement(N,false,M);}if("unload"==M){for(Q=J.length-1;Q>-1;Q--){X=J[Q];if(X&&X[0]==N&&X[1]==M&&X[2]==V){J.splice(Q,1);return true;}}return false;}var R=null;var S=arguments[4];if("undefined"===typeof S){S=this._getCacheIndex(N,M,V);}if(S>=0){R=I[S];}if(!N||!R){return false;}if(this.useLegacyEvent(N,M)){var P=this.getLegacyIndex(N,M);var O=E[P];if(O){for(Q=0,T=O.length;Q<T;++Q){X=O[Q];if(X&&X[this.EL]==N&&X[this.TYPE]==M&&X[this.FN]==V){O.splice(Q,1);break;}}}}else{try{this._simpleRemove(N,M,R[this.WFN],Y);}catch(U){this.lastError=U;return false;}}delete I[S][this.WFN];delete I[S][this.FN];
I.splice(S,1);return true;},removeListener:function(N,O,M){return this._removeListener(N,O,M,false);},getTarget:function(O,N){var M=O.target||O.srcElement;return this.resolveTextNode(M);},resolveTextNode:function(N){try{if(N&&3==N.nodeType){return N.parentNode;}}catch(M){}return N;},getPageX:function(N){var M=N.pageX;if(!M&&0!==M){M=N.clientX||0;if(this.isIE){M+=this._getScrollLeft();}}return M;},getPageY:function(M){var N=M.pageY;if(!N&&0!==N){N=M.clientY||0;if(this.isIE){N+=this._getScrollTop();}}return N;},getXY:function(M){return[this.getPageX(M),this.getPageY(M)];},getRelatedTarget:function(N){var M=N.relatedTarget;if(!M){if(N.type=="mouseout"){M=N.toElement;}else{if(N.type=="mouseover"){M=N.fromElement;}}}return this.resolveTextNode(M);},getTime:function(O){if(!O.time){var N=new Date().getTime();try{O.time=N;}catch(M){this.lastError=M;return N;}}return O.time;},stopEvent:function(M){this.stopPropagation(M);this.preventDefault(M);},stopPropagation:function(M){if(M.stopPropagation){M.stopPropagation();}else{M.cancelBubble=true;}},preventDefault:function(M){if(M.preventDefault){M.preventDefault();}else{M.returnValue=false;}},getEvent:function(O,M){var N=O||window.event;if(!N){var P=this.getEvent.caller;while(P){N=P.arguments[0];if(N&&Event==N.constructor){break;}P=P.caller;}}return N;},getCharCode:function(N){var M=N.keyCode||N.charCode||0;if(YAHOO.env.ua.webkit&&(M in D)){M=D[M];}return M;},_getCacheIndex:function(Q,R,P){for(var O=0,N=I.length;O<N;O=O+1){var M=I[O];if(M&&M[this.FN]==P&&M[this.EL]==Q&&M[this.TYPE]==R){return O;}}return -1;},generateId:function(M){var N=M.id;if(!N){N="yuievtautoid-"+A;++A;M.id=N;}return N;},_isValidCollection:function(N){try{return(N&&typeof N!=="string"&&N.length&&!N.tagName&&!N.alert&&typeof N[0]!=="undefined");}catch(M){return false;}},elCache:{},getEl:function(M){return(typeof M==="string")?document.getElementById(M):M;},clearCache:function(){},DOMReadyEvent:new YAHOO.util.CustomEvent("DOMReady",this),_load:function(N){if(!H){H=true;var M=YAHOO.util.Event;M._ready();M._tryPreloadAttach();}},_ready:function(N){var M=YAHOO.util.Event;if(!M.DOMReady){M.DOMReady=true;M.DOMReadyEvent.fire();M._simpleRemove(document,"DOMContentLoaded",M._ready);}},_tryPreloadAttach:function(){if(F.length===0){C=0;clearInterval(this._interval);this._interval=null;return ;}if(this.locked){return ;}if(this.isIE){if(!this.DOMReady){this.startInterval();return ;}}this.locked=true;var S=!H;if(!S){S=(C>0&&F.length>0);}var R=[];var T=function(V,W){var U=V;if(W.override){if(W.override===true){U=W.obj;}else{U=W.override;}}W.fn.call(U,W.obj);};var N,M,Q,P,O=[];for(N=0,M=F.length;N<M;N=N+1){Q=F[N];if(Q){P=this.getEl(Q.id);if(P){if(Q.checkReady){if(H||P.nextSibling||!S){O.push(Q);F[N]=null;}}else{T(P,Q);F[N]=null;}}else{R.push(Q);}}}for(N=0,M=O.length;N<M;N=N+1){Q=O[N];T(this.getEl(Q.id),Q);}C--;if(S){for(N=F.length-1;N>-1;N--){Q=F[N];if(!Q||!Q.id){F.splice(N,1);}}this.startInterval();}else{clearInterval(this._interval);this._interval=null;}this.locked=false;},purgeElement:function(Q,R,T){var O=(YAHOO.lang.isString(Q))?this.getEl(Q):Q;var S=this.getListeners(O,T),P,M;if(S){for(P=S.length-1;P>-1;P--){var N=S[P];this._removeListener(O,N.type,N.fn,N.capture);}}if(R&&O&&O.childNodes){for(P=0,M=O.childNodes.length;P<M;++P){this.purgeElement(O.childNodes[P],R,T);}}},getListeners:function(O,M){var R=[],N;if(!M){N=[I,J];}else{if(M==="unload"){N=[J];}else{N=[I];}}var T=(YAHOO.lang.isString(O))?this.getEl(O):O;for(var Q=0;Q<N.length;Q=Q+1){var V=N[Q];if(V){for(var S=0,U=V.length;S<U;++S){var P=V[S];if(P&&P[this.EL]===T&&(!M||M===P[this.TYPE])){R.push({type:P[this.TYPE],fn:P[this.FN],obj:P[this.OBJ],adjust:P[this.OVERRIDE],scope:P[this.ADJ_SCOPE],capture:P[this.CAPTURE],index:S});}}}}return(R.length)?R:null;},_unload:function(S){var M=YAHOO.util.Event,P,O,N,R,Q,T=J.slice();for(P=0,R=J.length;P<R;++P){N=T[P];if(N){var U=window;if(N[M.ADJ_SCOPE]){if(N[M.ADJ_SCOPE]===true){U=N[M.UNLOAD_OBJ];}else{U=N[M.ADJ_SCOPE];}}N[M.FN].call(U,M.getEvent(S,N[M.EL]),N[M.UNLOAD_OBJ]);T[P]=null;N=null;U=null;}}J=null;if(I){for(O=I.length-1;O>-1;O--){N=I[O];if(N){M._removeListener(N[M.EL],N[M.TYPE],N[M.FN],N[M.CAPTURE],O);}}N=null;}G=null;M._simpleRemove(window,"unload",M._unload);},_getScrollLeft:function(){return this._getScroll()[1];},_getScrollTop:function(){return this._getScroll()[0];},_getScroll:function(){var M=document.documentElement,N=document.body;if(M&&(M.scrollTop||M.scrollLeft)){return[M.scrollTop,M.scrollLeft];}else{if(N){return[N.scrollTop,N.scrollLeft];}else{return[0,0];}}},regCE:function(){},_simpleAdd:function(){if(window.addEventListener){return function(O,P,N,M){O.addEventListener(P,N,(M));};}else{if(window.attachEvent){return function(O,P,N,M){O.attachEvent("on"+P,N);};}else{return function(){};}}}(),_simpleRemove:function(){if(window.removeEventListener){return function(O,P,N,M){O.removeEventListener(P,N,(M));};}else{if(window.detachEvent){return function(N,O,M){N.detachEvent("on"+O,M);};}else{return function(){};}}}()};}();(function(){var EU=YAHOO.util.Event;EU.on=EU.addListener;EU.onFocus=EU.addFocusListener;EU.onBlur=EU.addBlurListener;
/* DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller */
if(EU.isIE){YAHOO.util.Event.onDOMReady(YAHOO.util.Event._tryPreloadAttach,YAHOO.util.Event,true);var n=document.createElement("p");EU._dri=setInterval(function(){try{n.doScroll("left");clearInterval(EU._dri);EU._dri=null;EU._ready();n=null;}catch(ex){}},EU.POLL_INTERVAL);}else{if(EU.webkit&&EU.webkit<525){EU._dri=setInterval(function(){var rs=document.readyState;if("loaded"==rs||"complete"==rs){clearInterval(EU._dri);EU._dri=null;EU._ready();}},EU.POLL_INTERVAL);}else{EU._simpleAdd(document,"DOMContentLoaded",EU._ready);}}EU._simpleAdd(window,"load",EU._load);EU._simpleAdd(window,"unload",EU._unload);EU._tryPreloadAttach();})();}YAHOO.util.EventProvider=function(){};YAHOO.util.EventProvider.prototype={__yui_events:null,__yui_subscribers:null,subscribe:function(A,C,F,E){this.__yui_events=this.__yui_events||{};
var D=this.__yui_events[A];if(D){D.subscribe(C,F,E);}else{this.__yui_subscribers=this.__yui_subscribers||{};var B=this.__yui_subscribers;if(!B[A]){B[A]=[];}B[A].push({fn:C,obj:F,override:E});}},unsubscribe:function(C,E,G){this.__yui_events=this.__yui_events||{};var A=this.__yui_events;if(C){var F=A[C];if(F){return F.unsubscribe(E,G);}}else{var B=true;for(var D in A){if(YAHOO.lang.hasOwnProperty(A,D)){B=B&&A[D].unsubscribe(E,G);}}return B;}return false;},unsubscribeAll:function(A){return this.unsubscribe(A);},createEvent:function(G,D){this.__yui_events=this.__yui_events||{};var A=D||{};var I=this.__yui_events;if(I[G]){}else{var H=A.scope||this;var E=(A.silent);var B=new YAHOO.util.CustomEvent(G,H,E,YAHOO.util.CustomEvent.FLAT);I[G]=B;if(A.onSubscribeCallback){B.subscribeEvent.subscribe(A.onSubscribeCallback);}this.__yui_subscribers=this.__yui_subscribers||{};var F=this.__yui_subscribers[G];if(F){for(var C=0;C<F.length;++C){B.subscribe(F[C].fn,F[C].obj,F[C].override);}}}return I[G];},fireEvent:function(E,D,A,C){this.__yui_events=this.__yui_events||{};var G=this.__yui_events[E];if(!G){return null;}var B=[];for(var F=1;F<arguments.length;++F){B.push(arguments[F]);}return G.fire.apply(G,B);},hasEvent:function(A){if(this.__yui_events){if(this.__yui_events[A]){return true;}}return false;}};YAHOO.util.KeyListener=function(A,F,B,C){if(!A){}else{if(!F){}else{if(!B){}}}if(!C){C=YAHOO.util.KeyListener.KEYDOWN;}var D=new YAHOO.util.CustomEvent("keyPressed");this.enabledEvent=new YAHOO.util.CustomEvent("enabled");this.disabledEvent=new YAHOO.util.CustomEvent("disabled");if(typeof A=="string"){A=document.getElementById(A);}if(typeof B=="function"){D.subscribe(B);}else{D.subscribe(B.fn,B.scope,B.correctScope);}function E(J,I){if(!F.shift){F.shift=false;}if(!F.alt){F.alt=false;}if(!F.ctrl){F.ctrl=false;}if(J.shiftKey==F.shift&&J.altKey==F.alt&&J.ctrlKey==F.ctrl){var G;if(F.keys instanceof Array){for(var H=0;H<F.keys.length;H++){G=F.keys[H];if(G==J.charCode){D.fire(J.charCode,J);break;}else{if(G==J.keyCode){D.fire(J.keyCode,J);break;}}}}else{G=F.keys;if(G==J.charCode){D.fire(J.charCode,J);}else{if(G==J.keyCode){D.fire(J.keyCode,J);}}}}}this.enable=function(){if(!this.enabled){YAHOO.util.Event.addListener(A,C,E);this.enabledEvent.fire(F);}this.enabled=true;};this.disable=function(){if(this.enabled){YAHOO.util.Event.removeListener(A,C,E);this.disabledEvent.fire(F);}this.enabled=false;};this.toString=function(){return"KeyListener ["+F.keys+"] "+A.tagName+(A.id?"["+A.id+"]":"");};};YAHOO.util.KeyListener.KEYDOWN="keydown";YAHOO.util.KeyListener.KEYUP="keyup";YAHOO.util.KeyListener.KEY={ALT:18,BACK_SPACE:8,CAPS_LOCK:20,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,META:224,NUM_LOCK:144,PAGE_DOWN:34,PAGE_UP:33,PAUSE:19,PRINTSCREEN:44,RIGHT:39,SCROLL_LOCK:145,SHIFT:16,SPACE:32,TAB:9,UP:38};YAHOO.register("event",YAHOO.util.Event,{version:"2.6.0",build:"1321"});YAHOO.register("yahoo-dom-event", YAHOO, {version: "2.6.0", build: "1321"});

/* End of Yahoo Copyrighted / BSD Licensed section */
/*
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 2.6.0

This notice only applies to this section.

*/
/**
 * The Browser History Manager provides the ability to use the back/forward
 * navigation buttons in a DHTML application. It also allows a DHTML
 * application to be bookmarked in a specific state.
 *
 * This library requires the following static markup:
 *
 * &lt;iframe id="yui-history-iframe" src="path-to-real-asset-in-same-domain"&gt;&lt;/iframe&gt;
 * &lt;input id="yui-history-field" type="hidden"&gt;
 *
 * @module history
 * @requires yahoo,event
 * @namespace YAHOO.util
 * @title Browser History Manager
 */

/**
 * The History class provides the ability to use the back/forward navigation
 * buttons in a DHTML application. It also allows a DHTML application to
 * be bookmarked in a specific state.
 *
 * @class History
 * @constructor
 */
YAHOO.util.History = (function () {

    /**
     * Our hidden IFrame used to store the browsing history.
     *
     * @property _histFrame
     * @type HTMLIFrameElement
     * @default null
     * @private
     */
    var _histFrame = null;

    /**
     * INPUT field (with type="hidden" or type="text") or TEXTAREA.
     * This field keeps the value of the initial state, current state
     * the list of all states across pages within a single browser session.
     *
     * @property _stateField
     * @type HTMLInputElement|HTMLTextAreaElement
     * @default null
     * @private
     */
    var _stateField = null;

    /**
     * Flag used to tell whether YAHOO.util.History.initialize has been called.
     *
     * @property _initialized
     * @type boolean
     * @default false
     * @private
     */
    var _initialized = false;

    /**
     * List of registered modules.
     *
     * @property _modules
     * @type array
     * @default []
     * @private
     */
    var _modules = [];

    /**
     * List of fully qualified states. This is used only by Safari.
     *
     * @property _fqstates
     * @type array
     * @default []
     * @private
     */
    var _fqstates = [];

	/**
	 * To be overridden by initialize(), a user-defined global state-change handler 
	 */

	function _fqStateChangeFn() {}

    /**
     * location.hash is a bit buggy on Opera. I have seen instances where
     * navigating the history using the back/forward buttons, and hence
     * changing the URL, would not change location.hash. That's ok, the
     * implementation of an equivalent is trivial.
     *
     * @method _getHash
     * @return {string} The hash portion of the document's location
     * @private
     */
    function _getHash() {
        var i, href;
        href = top.location.href;
        i = href.indexOf("#");
        return i >= 0 ? href.substr(i + 1) : null;
    }

    /**
     * Stores all the registered modules' initial state and current state.
     * On Safari, we also store all the fully qualified states visited by
     * the application within a single browser session. The storage takes
     * place in the form field specified during initialization.
     *
     * @method _storeStates
     * @private
     */
    function _storeStates() {

        var moduleName, moduleObj, initialStates = [], currentStates = [];

        for (moduleName in _modules) {
            if (YAHOO.lang.hasOwnProperty(_modules, moduleName)) {
                moduleObj = _modules[moduleName];
                initialStates.push(moduleName + "=" + moduleObj.initialState);
                currentStates.push(moduleName + "=" + moduleObj.currentState);
            }
        }

        _stateField.value = initialStates.join("&") + "|" + currentStates.join("&");

        if (YAHOO.env.ua.webkit) {
            _stateField.value += "|" + _fqstates.join(",");
        }
    }

    /**
     * Sets the new currentState attribute of all modules depending on the new
     * fully qualified state. Also notifies the modules which current state has
     * changed.
     *
     * @method _handleFQStateChange
     * @param {string} fqstate Fully qualified state
     * @private
     */
    function _handleFQStateChange(fqstate) {

        var i, len, moduleName, moduleObj, modules, states, tokens, currentState;

        if (!fqstate) {

            for (moduleName in _modules) {
                if (YAHOO.lang.hasOwnProperty(_modules, moduleName)) {
                    moduleObj = _modules[moduleName];
                    moduleObj.currentState = moduleObj.initialState;
                    moduleObj.onStateChange(decodeURI(moduleObj.currentState));
                }
            }
            return;
        }

        modules = [];
        states = fqstate.split("&");
        for (i = 0, len = states.length; i < len; i++) {
            tokens = states[i].split("=");
            if (tokens.length === 2) {
                moduleName = tokens[0];
                currentState = tokens[1];
                modules[moduleName] = currentState;
            }
        }

        for (moduleName in _modules) {
            if (YAHOO.lang.hasOwnProperty(_modules, moduleName)) {
                moduleObj = _modules[moduleName];
                currentState = modules[moduleName];
                if (!currentState || moduleObj.currentState !== currentState) {
                    moduleObj.currentState = currentState || ''; //moduleObj.initialState;
                    moduleObj.onStateChange(decodeURI(moduleObj.currentState));
                }
            }
        }

		_fqStateChangeFn();
    }

    /**
     * Update the IFrame with our new state.
     *
     * @method _updateIFrame
     * @private
     * @return {boolean} true if successful. false otherwise.
     */
    function _updateIFrame (fqstate) {

        var html, doc;

        html = '<html><body><div id="state">' + fqstate + '</div></body></html>';

        try {
            doc = _histFrame.contentWindow.document;
            doc.open();
            doc.write(html);
            doc.close();
            return true;
        } catch (e) {
            return false;
        }
    }

    /**
     * Periodically checks whether our internal IFrame is ready to be used.
     *
     * @method _checkIframeLoaded
     * @private
     */
    function _checkIframeLoaded() {

        var doc, elem, fqstate, hash;

        if (!_histFrame.contentWindow || !_histFrame.contentWindow.document) {

            setTimeout(_checkIframeLoaded, 10);
            return;
        }







        doc = _histFrame.contentWindow.document;
        elem = doc.getElementById("state");



        fqstate = elem ? elem.innerText : null;

        hash = _getHash();

        setInterval(function () {

            var newfqstate, states, moduleName, moduleObj, newHash, historyLength;

            doc = _histFrame.contentWindow.document;
            elem = doc.getElementById("state");

            newfqstate = elem ? elem.innerText : null;

            newHash = _getHash();

            if (newfqstate !== fqstate) {

                fqstate = newfqstate;
                _handleFQStateChange(fqstate);

                if (!fqstate) {
                    states = [];
                    for (moduleName in _modules) {
                        if (YAHOO.lang.hasOwnProperty(_modules, moduleName)) {
                            moduleObj = _modules[moduleName];
                            states.push(moduleName + "=" + moduleObj.initialState);
                        }
                    }
                    newHash = states.join("&");
                	_handleFQStateChange(newHash);
                } else {
                    newHash = fqstate;
                }







                top.location.hash = newHash;
                hash = newHash;

                _storeStates();

            } else if (newHash !== hash) {













                hash = newHash;



                _updateIFrame(newHash);
            }

        }, 50);

        _initialized = true;
        YAHOO.util.History.onLoadEvent.fire();
    }

    /**
     * Finish up the initialization of the Browser History Manager.
     *
     * @method _initialize
     * @private
     */
    function _initialize() {

        var i, len, parts, tokens, moduleName, moduleObj, initialStates, initialState, currentStates, currentState, counter, hash;


        parts = _stateField.value.split("|");

        if (parts.length > 1) {

            initialStates = parts[0].split("&");
            for (i = 0, len = initialStates.length; i < len; i++) {
                tokens = initialStates[i].split("=");
                if (tokens.length === 2) {
                    moduleName = tokens[0];
                    initialState = tokens[1];
                    moduleObj = _modules[moduleName];
                    if (moduleObj) {
                        moduleObj.initialState = initialState;
                    }
                }
            }

            currentStates = parts[1].split("&");
            for (i = 0, len = currentStates.length; i < len; i++) {
                tokens = currentStates[i].split("=");
                if (tokens.length >= 2) {
                    moduleName = tokens[0];
                    currentState = tokens[1];
                    moduleObj = _modules[moduleName];
                    if (moduleObj) {
                        moduleObj.currentState = currentState;
                    }
                }
            }
        }

        if (parts.length > 2) {
            _fqstates = parts[2].split(",");
        }

        if (YAHOO.env.ua.ie) {

            _checkIframeLoaded();

        } else {















            counter = history.length;


            hash = _getHash();

            setInterval(function () {

                var state, newHash, newCounter;

                newHash = _getHash();
                newCounter = history.length;
                if (newHash !== hash) {
                    hash = newHash;
                    counter = newCounter;
                    _handleFQStateChange(hash);
                    _storeStates();
                } else if (newCounter !== counter && YAHOO.env.ua.webkit) {
                    hash = newHash;
                    counter = newCounter;
                    state = _fqstates[counter - 1];
                    _handleFQStateChange(state);
                    _storeStates();
                }

            }, 50);

            _initialized = true;
            YAHOO.util.History.onLoadEvent.fire();
        }
    }

    return {

        /**
         * Fired when the Browser History Manager is ready. If you subscribe to
         * this event after the Browser History Manager has been initialized,
         * it will not fire. Therefore, it is recommended to use the onReady
         * method instead.
         *
         * @event onLoadEvent
         * @see onReady
         */
        onLoadEvent: new YAHOO.util.CustomEvent("onLoad"),

        /**
         * Executes the supplied callback when the Browser History Manager is
         * ready. This will execute immediately if called after the Browser
         * History Manager onLoad event has fired.
         *
         * @method onReady
         * @param {function} fn what to execute when the Browser History Manager is ready.
         * @param {object} obj an optional object to be passed back as a parameter to fn.
         * @param {boolean|object} override If true, the obj passed in becomes fn's execution scope.
         * @see onLoadEvent
         */
        onReady: function (fn, obj, override) {

            if (_initialized) {

                setTimeout(function () {
                    var ctx = window;
                    if (override) {
                        if (override === true) {
                            ctx = obj;
                        } else {
                            ctx = override;
                        }
                    }
                    fn.call(ctx, "onLoad", [], obj);
                }, 0);

            } else {

                YAHOO.util.History.onLoadEvent.subscribe(fn, obj, override);

            }
        },

        /**
         * Registers a new module.
         *
         * @method register
         * @param {string} module Non-empty string uniquely identifying the
         *     module you wish to register.
         * @param {string} initialState The initial state of the specified
         *     module corresponding to its earliest history entry.
         * @param {function} onStateChange Callback called when the
         *     state of the specified module has changed.
         * @param {object} obj An arbitrary object that will be passed as a
         *     parameter to the handler.
         * @param {boolean} override If true, the obj passed in becomes the
         *     execution scope of the listener.
         */
        register: function (module, initialState, onStateChange, obj, override) {

            var scope, wrappedFn;

			if (initialState == undefined) {
				initialState = '';
			}

            if (typeof module !== "string" || YAHOO.lang.trim(module) === "" ||
                typeof initialState !== "string" ||
                typeof onStateChange !== "function") {
                throw new Error("Missing or invalid argument");
            }

            if (_modules[module]) {


                return;
            }








            if (_initialized) {
                throw new Error("All modules must be registered before calling YAHOO.util.History.initialize");
            }


            module = encodeURI(module);
            initialState = encodeURI(initialState);



            scope = null;
            if (override === true) {
                scope = obj;
            } else {
                scope = override;
            }

            wrappedFn = function (state) {
                return onStateChange.call(scope, state, obj);
            };

            _modules[module] = {
                name: module,
                initialState: initialState,
                currentState: initialState,
                onStateChange: wrappedFn
            };
        },

        /**
         * Initializes the Browser History Manager. Call this method
         * from a script block located right after the opening body tag.
         *
         * @method initialize
         * @param {string|HTML Element} stateField <input type="hidden"> used
         *     to store application states. Must be in the static markup.
         * @param {string|HTML Element} histFrame IFrame used to store
         *     the history (only required on Internet Explorer)
         * @public
         */
        initialize: function (stateField, histFrame, fqStateChangeFn) {

            if (_initialized) {

                return;
            }

			if (typeof fqStateChangeFn == 'function') {
				_fqStateChangeFn = fqStateChangeFn;
			}

            if (YAHOO.env.ua.opera) {











            }

            if (typeof stateField === "string") {
                stateField = document.getElementById(stateField);
            }

            if (!stateField ||
                stateField.tagName.toUpperCase() !== "TEXTAREA" &&
                (stateField.tagName.toUpperCase() !== "INPUT" ||
                 stateField.type !== "hidden" &&
                 stateField.type !== "text")) {
                throw new Error("Missing or invalid argument");
            }

            _stateField = stateField;

            if (YAHOO.env.ua.ie) {

                if (typeof histFrame === "string") {
                    histFrame = document.getElementById(histFrame);
                }

                if (!histFrame || histFrame.tagName.toUpperCase() !== "IFRAME") {
                    throw new Error("Missing or invalid argument");
                }

                _histFrame = histFrame;
            }





            YAHOO.util.Event.onDOMReady(_initialize);
        },

        /**
         * Call this method when you want to store a new entry in the browser's history.
         *
         * @method navigate
         * @param {string} module Non-empty string representing your module.
         * @param {string} state String representing the new state of the specified module.
         * @return {boolean} Indicates whether the new state was successfully added to the history.
         * @public
         */
        navigate: function (module, state) {

            var states;

            if (typeof module !== "string" || typeof state !== "string") {
                throw new Error("Missing or invalid argument");
            }

            states = {};
            states[module] = state;

            return YAHOO.util.History.multiNavigate(states);
        },

        /**
         * Call this method when you want to store a new entry in the browser's history.
         *
         * @method multiNavigate
         * @param {object} states Associative array of module-state pairs to set simultaneously.
         * @return {boolean} Indicates whether the new state was successfully added to the history.
         * @public
         */
        multiNavigate: function (states) {

            var currentStates, moduleName, moduleObj, currentState, fqstate;

            if (typeof states !== "object") {
                throw new Error("Missing or invalid argument");
            }

            if (!_initialized) {
                throw new Error("The Browser History Manager is not initialized");
            }








            currentStates = [];

            for (moduleName in _modules) {
                if (YAHOO.lang.hasOwnProperty(_modules, moduleName)) {
                    moduleObj = _modules[moduleName];
                    if (YAHOO.lang.hasOwnProperty(states, moduleName)) {
                        currentState = states[decodeURI(moduleName)];
                    } else {
                        currentState = decodeURI(moduleObj.currentState);
                    }


                    moduleName = encodeURI(moduleName);
                    currentState = encodeURI(currentState);

					if (currentState.length) {
                    	currentStates.push(moduleName + "=" + currentState);
					}
                }
            }

            fqstate = currentStates.join("&");

            if (YAHOO.env.ua.ie) {

                return _updateIFrame(fqstate);

            } else {









                top.location.hash = fqstate;
                if (YAHOO.env.ua.webkit) {





                    _fqstates[history.length] = fqstate;
                    _storeStates();
                }

                return true;

            }
        },

        /**
         * Returns the current state of the specified module.
         *
         * @method getCurrentState
         * @param {string} module Non-empty string representing your module.
         * @return {string} The current state of the specified module.
         * @public
         */
        getCurrentState: function (module) {

            var moduleObj;

            if (typeof module !== "string") {
                throw new Error("Missing or invalid argument");
            }

            if (!_initialized) {
                throw new Error("The Browser History Manager is not initialized");
            }

            moduleObj = _modules[module];
            if (!moduleObj) {
                throw new Error("No such registered module: " + module);
            }

            return decodeURI(moduleObj.currentState);
        },

        /**
         * Returns the state of a module according to the URL fragment
         * identifier. This method is useful to initialize your modules
         * if your application was bookmarked from a particular state.
         *
         * @method getBookmarkedState
         * @param {string} module Non-empty string representing your module.
         * @return {string} The bookmarked state of the specified module.
         * @public
         */
        getBookmarkedState: function (module) {

            var i, len, idx, hash, states, tokens, moduleName;

            if (typeof module !== "string") {
                throw new Error("Missing or invalid argument");
            }




            idx = top.location.href.indexOf("#");
            hash = idx >= 0 ? top.location.href.substr(idx + 1) : top.location.href;


            states = hash.split("&");
            for (i = 0, len = states.length; i < len; i++) {
                tokens = states[i].split("=");
                if (tokens.length === 2) {
                    moduleName = tokens[0];
                    if (moduleName === module) {
                        return decodeURI(tokens[1]);
                    }
                }
            }

            return null;
        },

        /**
         * Returns the value of the specified query string parameter.
         * This method is not used internally by the Browser History Manager.
         * However, it is provided here as a helper since many applications
         * using the Browser History Manager will want to read the value of
         * url parameters to initialize themselves.
         *
         * @method getQueryStringParameter
         * @param {string} paramName Name of the parameter we want to look up.
         * @param {string} queryString Optional URL to look at. If not specified,
         *     this method uses the URL in the address bar.
         * @return {string} The value of the specified parameter, or null.
         * @public
         */
        getQueryStringParameter: function (paramName, url) {

            var i, len, idx, queryString, params, tokens;

            url = url || top.location.href;

            idx = url.indexOf("?");
            queryString = idx >= 0 ? url.substr(idx + 1) : url;


            idx = queryString.lastIndexOf("#");
            queryString = idx >= 0 ? queryString.substr(0, idx) : queryString;

            params = queryString.split("&");

            for (i = 0, len = params.length; i < len; i++) {
                tokens = params[i].split("=");
                if (tokens.length >= 2) {
                    if (tokens[0] === paramName) {
                        return decodeURI(tokens[1]);
                    }
                }
            }

            return null;
        }

    };

})();
YAHOO.register("history", YAHOO.util.History, {version: "2.6.0", build: "1321"});

/* End of Yahoo Copyrighted / BSD Licensed section */
/* Copyright (c) 2008 Shutterstock Images LLC */

var readyStateCheckInterval = 250;

var activeResultSlot;

function clearRecentSearches() {
	$('recent-searches').setOpacity(0.5);
	new Ajax.Request('/show_component.mhtml', {
		parameters: {
			component_path: 'clear_recent_searches.md'
		},
		onSuccess: function() {
			$('recent-searches').hide();
		},
		onFailure: function() {
			$('recent-searches').setOpacity(1);
			alert($t('DYNAMIC_RESULTS_ERROR_CLEAR_RECENT_SEARCHES', 'Unfortunately, due to a technical error, we were unable to clear your recent searches'));
		}
	} );
}

function updateThumbSize(args) { // args: sizeName, e

	browser.toggleCursorState('progress', args.e);

	searchControls.setDisplayPrefs( {
		thumbSize: thumbSizes[args.sizeName].session_name,
		callback: function() {
			location = '/change_results_mode.mhtml?results_mode=dynamic&' + search.results.normalizedQueryString
		}
	} );

}

function updateDisplayRows(args) { // args: rows, e

	browser.toggleCursorState('progress', args.e);

	searchControls.setDisplayPrefs( {
		rowsPerPage: args.rows,
		callback: function() {
			location = '/change_results_mode.mhtml?results_mode=dynamic&' + search.results.normalizedQueryString
		}
	} );

}

function bootstrap(args) { // args: searchCriteria, pageNumber, callback, dontInterrupt, dontSyncLocation, direction, reloadSearchPreferences

	if (args.reloadSearchPreferences) {
		location = '/change_results_mode.mhtml?results_mode=dynamic&update_preferences=1&' + $('keyword_form').serialize();
		return;
	}

	args.direction = args.direction == 'backward' ? args.direction : 'forward';
	
	initiallyBootstrapped = true;



	if (args.searchCriteria &&
	    args.searchCriteria.criteria.searchterm) {
		var searchterm = args.searchCriteria.criteria.searchterm;
		if ( searchterm.match(/^\s*?\d+\s*?$/) ) { // remove leading or trailing spaces
			var stripped_searchterm = searchterm.replace( /\s+/g, "" );
			search.showDetails( { 
				photoId: stripped_searchterm, e: args.e 
			} );
			return;
		}
	}

	searchResults.results = {};

	args.pageNumber = args.pageNumber ? args.pageNumber : 1;
	var chapterNumber = parseInt(Math.floor((args.pageNumber - 1) / pagesPerChapter));






	previousSearchCriteria = args.searchCriteria;

	var normalizedLocationArgs = args.searchCriteria.criteria;
	if (args.pageNumber && args.pageNumber != 1) {
		normalizedLocationArgs.page = args.PageNumber;
	}	



	searchResults.fetch( {
		chapterNumber: chapterNumber,
		searchCriteria: args.searchCriteria.criteria,
		sortMethod: args.searchCriteria.criteria.sort_method,
		initialSearch: true,
		interruptPendingRequests: args.dontInterrupt ? false : true,
		callback: function() {
			browser.wait( {
				condition: 'window.search',
				retryInterval: 100,
				callback: function() {
					syncResultsPageCount();
					easel.setCanvasOrder({ direction: args.direction });
					search.criteria = args.searchCriteria;
					easel.nascentCanvas.populateResults( { 
						pageNumber: args.pageNumber,
						callback: function() {

							searchControls.syncSearchInputsDisplay();
							if (!searchResults.count) {
								search.elements.resultsContainer.style.display = 'none';
								$('loading-indicator').style.display = 'none';
								search.elements.detailsContainer.style.display = 'none';
								$('search-results-header').style.display = 'block';
								browser.toggleCursorState('revert');

								return;	
							}
							$('loading-indicator').style.display = 'none';
							search.elements.detailsContainer.style.display = 'none';
							search.elements.resultsContainer.style.display = 'block';
							search.elements.resultsContainer.style.position = 'static';
							search.elements.resultsContainer.style.visibility = 'visible';
							$('search-results-header').style.display = 'block';
							search.showNextPage( { e: document.body, bootstrap: true, dontSetPage: true, direction: args.direction, dontConsultLocks: true } );
							if (typeof(args.callback) == 'function') {
								args.callback();
							}
							searchControls.syncDisplayPrefSelects();
							searchControls.syncPagerLinkClasses();	



						} 
					} );
				}
			} );
		}
	} );
}

function doSearch(args) { // e
	
	browser.toggleCursorState('progress', args.e);
	search.restoreResultsView();

	var criteria = {};

	if (args.e && args.e.hasClassName('view-selector-input')) {
		criteria[args.e.name] = criteria[args.e.value];
	}

	searchInputIds.each( function(inputElementId) {
		var e = $(inputElementId);
		if (!e) {
			return;
		}
		if (e && e.blur) e.blur();

		if (e.name == 'show_color_wheel') {
			if (e.checked) {
				if ($('color-hex-input').value) {
					criteria.color = $('color-hex-input').value;
					criteria.color = criteria.color.replace(/^\#/, '');
				}
			}
		} else if (e.tagName == 'INPUT' && e.type == 'checkbox' && !criteria[e.name]) {
			criteria[e.name] = e.checked ? 1 : 0;
		} else {
			criteria[e.name] = criteria[e.name] ? criteria[e.name] : e.value;
			if (e.value) {

			}
		}
	} );

	browser.updateLocation( { args: criteria, clear: true, e: args.e } );
}

var newlyActiveThumb;
function setActiveThumb(args) {

	activeResultSlot = args.resultSlot;
	newlyActiveThumb = true;
}

function debug(message) {

}

function calmlyShowPhotoDetails() {


	if (browser.mouseSpeed < 50 && browser.mouseoverEnabled) {
		if (!resultPreview.showing && newlyActiveThumb) {
			resultPreview.showing = true;
			newlyActiveThumb = false;
			resultPreview.populate( { resultSlot: activeResultSlot } );
		} else {

		}
	}
}

function syncResultsPageCount() {
	$$('.results-page-count').each( function(e) { e.innerHTML = search.results.pageCount } );
}

var requests = {};
var activeRequestNumber = 0;

function setCatPageHandlers() {
	setTimeout(
		function() {
			$$('a').each( function(link) {
				if (link.href.match(/\/cat\W/)) {
					var e = link;
					link.onclick = function() {
						var categoryId = link.getAttribute('x_shutterstock_category_id');

						browser.updateLocation( { args: { category_id: categoryId }, clear: true, e: e } );
						return false;
					};
				}
			} )
		}, 10);
}
function setKeywordSearchHandlers() {
	setTimeout(
		function() {
			$$('#pic-page-container a').each ( function(link) {
				if (link.href.match(/\/s\/.+\/search.html$/)) {
					link.onclick = function() {
						var searchterm = link.getAttribute('x_shutterstock_keyword');
						browser.updateLocation( { args: { searchterm: searchterm }, clear: true, e: link } );
						return false;
					};
				}
			} );
		},
		10
	);
}

var searchInputIds = $w('searchterm-input category-select search-group-select orientation-select exclude-input ' +
                        'model-released-checkbox exclude-editorial-checkbox enhanced-only-checkbox photographer-input');

var previousSearchCriteria = new Object;

function testObjectEquality(o1, o2) {

	if (!o1 || !o2) {

		return false;
	}
	for (var key in o1) {
		if (o1[key] != 'all' && o1[key] && o1[key] != o2[key]) {

			return false;
		}
	}
	for (var key in o2) {
		if (o2[key] != 'all' && o2[key] && o1[key] != o2[key]) {

			return false;
		}
	}

	return true;	
}

function dismissPreviewMessage() {
	var messageElement = $('image-preview-message');
	messageElement.setOpacity(0.5);
	new Ajax.Request( '/show_component.mhtml', {
		parameters: {
			component_path: 'dismiss_image_preview_message.md'
		},
		onSuccess: function() {
			messageElement.hide();
		}
	} );
}

var lastLocation;
var handleHistoryEvent = function(newLocation, historyData) {


	var pendingLinkElement = browser.pendingLinkElements.pop();
	if (pendingLinkElement) {
		browser.toggleCursorState('progress', pendingLinkElement);
	}





	if (browser.historyEventCallbacks) {
		$A(browser.historyEventCallbacks).each( function(cb) {
			cb();
		});
	}

	browser.lastLocation = newLocation;
	browser.pageArgs = browser.parseArgs();

	var pageArgs = browser.pageArgs;



	if (pageArgs.photo_id) {





		browser.toggleCursorState('progress', document.body);
		search.showDetails( { photoId: pageArgs.photo_id, e: pendingLinkElement, src: pageArgs.src } );
		return;
	}

	var criteria = $H(pageArgs).clone().toObject();
	delete criteria.page;
	delete criteria.photo_id;

	var searchCriteria = new SearchCriteria( { criteria: criteria } );

	var reusePopulatedResults =
		(searchCriteria && previousSearchCriteria && previousSearchCriteria.getNormalizedQueryString && searchCriteria.getNormalizedQueryString() == previousSearchCriteria.getNormalizedQueryString());



	arguments.callee.initialCallDone = true;

	if (reusePopulatedResults && (search.activePageNumber == pageArgs.page || (!pageArgs.page && search.activePageNumber == 1))) {


	
		search.elements.detailsContainer.style.display = 'none';
		easel.activeCanvas.element.style.visibility = 'visible';
		search.elements.resultsContainer.style.display = 'block';
		search.elements.resultsContainer.style.position = 'static';
		document.getElementById('search-results-header').style.display = 'block';

		window.scroll(0, search.canvasScrollOffset);
		
		search.restoreResultsView();
		searchControls.syncSearchInputsDisplay();

		document.title = searchResults.pageTitle;

	} else if (reusePopulatedResults && easel.activeCanvas.nextCanvas.pageNumber == pageArgs.page) {

		search.showNextPage( { e: pendingLinkElement } );

	} else if (reusePopulatedResults && easel.activeCanvas.prevCanvas.pageNumber == (pageArgs.page || 1)) {

		search.showNextPage( { direction: 'backward', e: pendingLinkElement } );

	} else {



		browser.toggleCursorState('progress', document.body);


		var pageNumber = pageArgs.page ? pageArgs.page : 1;

		if (pageNumber < 1) {
			pageNumber = 1;
		} else if (pageNumber > resultsPageCount) {
			pageNumber = resultsPageCount;
		}

		var direction = pageArgs.page == search.activePageNumber - 1 && reusePopulatedResults ? 'backward' : 'forward';




		bootstrap( { 
			pageNumber: parseInt(pageArgs.page ? pageArgs.page : 1), 
			searchCriteria: new SearchCriteria( { criteria: browser.parseArgs() } ),
			callback: function () { browser.toggleCursorState('revert', pendingLinkElement) },
			direction: direction,
			reloadSearchPreferences: window.shouldReloadSearchPreferences
		} );
	}
}

var showAddToLightboxList = function(args) {
	selectedPhotoId = args.photoId;

	var placeholder = document.getElementById('pic-page-lightbox-dropdown-placeholder');
	var dialog = document.getElementById('add-to-lightbox-dialog');

	placeholder.appendChild(dialog);
	dialog.style.display = 'block';

	dropdownDialogShowing = true;
}

var getLocationHash = function() {
	var i, href;
	href = top.location.href;
	i = href.indexOf("#");
	return i >= 0 ? href.substr(i + 1) : null;
}

var changeResultsMode = function(legacyQueryString) {
	var resultsMode = $('results-mode-form').results_mode.value;
	var queryString = window.search && window.browser ? browser.getHash() : legacyQueryString;
	location = "/change_results_mode.mhtml?results_mode=" + [resultsMode, queryString].join('&');	
}
/* Copyright (c) 2008 Shutterstock Images LLC */

var start = new Date().getTime();
function logTime(label) {
	var now = new Date().getTime();

	start = now;
}
function BaseObject() {
	var self = arguments.callee;
	if (self.instantiated) return;

	this.instantiate = function(instance) {
		for (var p in instance.properties) {
	
			if (typeof instance.properties[p] == 'function' && 0) {
				instance.prototype[p] = instance.properties[p];
			} else {
				instance[p] = instance.properties[p];
			}
		}
	}
}

var base = new BaseObject();
/* Copyright (c) 2008 Shutterstock Images LLC */

function Canvas(args) { // id

	this.properties = {

		id: args.id,

		element: args.element,

		pageNumber: null,

		readyState: 'uninitialized',
		readyStateCheckInterval: 250, // milliseconds

		resultSlots: []	
	};
	
	base.instantiate(this);

	var enume_counter = 0;
	for (var i = 0; i < this.element.childNodes.length; i++) {
		var child = this.element.childNodes[i];
		
		if (child.nodeType != 1)
			continue;

		var resultSlot = new ResultSlot( {
			canvas: this,
			enume: enume_counter++,
			containerElement: this.element.childNodes[i]
		} );

		this.resultSlots.push(resultSlot);

	} 	

}


Canvas.prototype = {

		populateResults: function(args) { // resultSlotsCount, callback, results, pageNumber, iterationCount

			var canvas = this;

			this.pageNumber = args.pageNumber != undefined ? args.pageNumber : this.pageNumber;

			this.readyState = 'loading';

			var resultsOffset = resultsPerPage * (canvas.pageNumber - 1);

			this.photo_enume_map = new Hash();

			canvas.chapterNumber = Math.floor(resultsOffset / resultsPerChapter);
			canvas.chapterPageNumber = Math.floor((resultsOffset - canvas.chapterNumber * resultsPerChapter) / resultsPerPage);  //suspect

			var chapterNumberOffset = 0;

			for (var i = 0; i < resultsPerPage; i++) {

				var chapterNumber = Math.floor( (resultsOffset + i) / resultsPerChapter);
				var chapterResultsIndex = (resultsOffset + i) % resultsPerChapter;

				if (!searchResults.results[chapterNumber]) {

					if (!searchResults.locks.chapterNumbers[chapterNumber]) {

						searchResults.fetch( { 
							chapterNumber: chapterNumber,
							searchCriteria: search.criteria.criteria,
							callback: function() {
								this.populateResults(args);
							}.bind(this)
						} );
						return;
					} else {


						args.iterationCount = args.iterationCount ? args.iterationCount + 1 : 1;
						if (args.iterationCount > 180) {
							log.fatal("giving up waiting for canvas to populate after 180 iterations");
							return;
						}
						setTimeout( function() { this.populateResults(args) }.bind(this), 250);
						return; 
					}
				}

				var result = searchResults.results[chapterNumber][chapterResultsIndex];

				if (!result) {
					canvas.resultSlots[i].clear();
				} else {
					canvas.resultSlots[i].populate( {
						result: result,
						thumbSize: activeThumbSize,
						clear: !result, 
						enume: i
					} );

					this.photo_enume_map[result.id] = i;
				}
			}	

			canvas.readyState = 'ready';

			if (typeof(args.callback) == 'function') {
				args.callback();
			}
		},


		hideResultContainers: function() { 
			for (var i = 0; i < this.resultSlots.length; i++) {
				var resultSlot = this.resultSlots[i];
				resultSlot.clear();
			}
		}
	
};
/* Copyright (c) 2008 Shutterstock Images LLC */

function ResultSlot(args) { // canvas, enume, elements, lightboxIcon, enlargeIcon
	this.properties = {

		elements: {}, 

		photoId: undefined,

		canvas: args.canvas,
		enume: args.enume,

		result: {},

		id: args.canvas.id + '-' + args.enume
	};

	base.instantiate(this);


	this._populateElementRefs(args.containerElement);
	this.elements.container = args.containerElement;
	if (!this.elements.thumb) {
		return;
	}

	this.lightboxIcon = new ResultSlotIcon( {
		activeElement: this.elements.lightboxActive,
		inactiveElement: this.elements.lightboxInactive
	} );
	this.detailsIcon = new ResultSlotIcon( {
		activeElement: this.elements.enlargeActive,
		inactiveElement: this.elements.enlargeInactive
	} );

	var enterHandlerName, leaveHandlerName;

	if (Prototype.Browser.IE) {
		enterHandlerName = 'onmouseenter';
		leaveHandlerName = 'onmouseleave';
	} else {
		enterHandlerName = 'onmouseover';
		leaveHandlerName = 'onmouseout';
	}

	this.elements.container[enterHandlerName] = this.highlight.bind(this);
	this.elements.container[leaveHandlerName] = this.unHighlight.bind(this);
	
	this.elements.thumb.onmouseover = function() { setActiveThumb( { resultSlot: this } ) }.bind(this);
	this.elements.thumb.onmouseout = function() { resultPreview.unPopulate( { resultSlot: this } ) }.bind(this);

	this.lightboxIcon.activeElement.onclick = function() { this.showAddToLightboxList() }.bind(this);
	this.detailsIcon.activeElement.onclick = function() {
		browser.toggleCursorState('progress', this.detailsIcon.activeElement);
		browser.updateLocation( { args: { similar_photo_id: this.result.id }, e: this.detailsIcon.activeElement, clear: true } );
	}.bind(this);
}

ResultSlot.prototype = {

		highlight: function() {
			this.elements.container.className += ' highlighted-result-container';
			this.lightboxIcon.highlight();
			this.detailsIcon.highlight();
		},

		unHighlight: function() {
			this.elements.container.className = this.elements.container.className.replace(/ highlighted-result-container$/, '');
			this.lightboxIcon.unHighlight();
			this.detailsIcon.unHighlight();
		},

		showAddToLightboxList: function(args) { // id, canvasEnum
			dropdownDialogShowing = true;
			selectedPhotoId = this.photoId;
			selectedPhotoSrc = this.currentSearchSrcId;

			var placeHolder = this.elements.dropdownPlaceHolder;
			$(placeHolder).insert(Ss.Lightbox.multipleAdder.getPulldown().getElement());
			Ss.Lightbox.multipleAdder.getPulldown().expand();
			
			if(Ss.user.loggedIn) {
				Ss.Lightbox.multipleAdder.refresh(getAllLightboxes());
			}
			
		},

		getDimensions: function(maxDimensionPixels) { 
			var width, height;

			var aspectRatio = this.result.aspect_ratio;


			if (!aspectRatio) aspectRatio = 1;

			if (aspectRatio > 1) {
				width = maxDimensionPixels;
				height = Math.round(width / aspectRatio);
			} else {
				height = maxDimensionPixels;
				width = Math.round(height * aspectRatio);
			}

			return { width: width, height: height };

		},

		populate: function(args) { // result, canvas, enume, clear, thumbSize

			var result = this.result = args.result;
			var canvas = this.canvas;

			var thumb = this.elements.thumb;
			
			if (!thumb) {

				return;
			}
			
			var thumbContainer = thumb.parentNode.tagName == 'A' ? thumb.parentNode.parentNode : thumb.parentNode;

			if (!result) {

				return;
			}

			this.photoId = result.id;

			thumb.style.visibility = 'hidden';

			var maxDimensionPixels = args.thumbSize.max_dimension_pixels;

			var dimensions = this.getDimensions(maxDimensionPixels);
	
			thumbContainer.style.width = dimensions.width + 'px'; 
			thumbContainer.style.height = dimensions.height + 'px';

			thumbContainer.style.marginTop = Math.round((maxDimensionPixels - dimensions.height) / 2) + 'px';
			thumbContainer.style.marginLeft = Math.round((maxDimensionPixels - dimensions.width) / 2) + 'px';

			if (thumb.parentNode.tagName == 'A') {

				if (searchResults.searchSrcID) {		
					this.currentSearchSrcId = searchResults.searchSrcID + '-' + canvas.pageNumber + '-' + this.enume;
					thumb.parentNode.href = "/pic-" + result.id + ".html?src=" + this.currentSearchSrcId;
					thumb.parentNode.setAttribute('x_shutterstock_src',this.currentSearchSrcId);

				} else {
					this.currentSearchSrcId = '';
					thumb.parentNode.href = "/pic-" + result.id + ".html";
				}
			}
			
			this.elements.description.innerHTML = document.language == 'en' ? result['display_description'] : '';	

			var thumbURL = ['http:/', result.host, 'photos', args.thumbSize.name, result.set_name, result.filename].join('/');
	
			if (thumb.src == thumbURL) {
				thumb.style.visibility = 'visible';
			} else {
				thumb.src = thumbURL;
			} 

			this.elements.container.style.visibility = 'visible';


			thumb.onclick = function() { 
				browser.toggleCursorState('progress', thumb); 
				setTimeout( 
					function() { browser.updateLocation({ clear: true, args: { photo_id: result.id, src: thumb.parentNode.getAttribute('x_shutterstock_src') }, e: thumb }) }, 
					10
				);
			};

			this.detailsIcon.onclick = function() { search.showDetails({ photoId: result.id, e: this.detailsIcon, enume: this.enume }) };
		},

		clear: function(args) {
			this.elements.thumb.src = 'http://www.shutterstock.com/images/spacer.gif';
			this.elements.container.style.visibility = 'hidden';
		},

		_populateElementRefs: function(parent) {

			var elementMap = {
				'result-thumb': 'thumb',
				'result-description': 'description',
				'result-dropdown-placeholder': 'dropdownPlaceHolder',
				'grid-icon lightbox-active': 'lightboxActive',
				'grid-icon lightbox-inactive': 'lightboxInactive',
				'grid-icon enlarge-active': 'enlargeActive',
				'grid-icon enlarge-inactive': 'enlargeInactive'
			};

			if (parent.hasChildNodes()) {

				for (var i = 0; i < parent.childNodes.length; i++) {
					var child = parent.childNodes[i];
					if (child.nodeType != 1) {
						continue;
					}
					if (elementMap[child.className]) {
						this.elements[elementMap[child.className]] = child;
					}
					this._populateElementRefs(child);
				}
			}
			
		}

};

function showPhotoDetails(e) {
	if (window.search && browser) {
		var matches;
		if (matches = e.href.match(/\/pic-(\d+)/)) {
			var photoId = matches[1];
			var src = e.getAttribute('x_shutterstock_src');

			browser.updateLocation( { args: { photo_id: photoId, src: src }, clear: true, e: e } );
			return false;
		}
	}
} 
/* Copyright (c) 2008 Shutterstock Images LLC */

function ResultSlotIcon(args) { // activeElement, inactiveElement

	this.properties = {
		activeElement: args.activeElement,
		inactiveElement: args.inactiveElement
	};
 
	base.instantiate(this);

};

ResultSlotIcon.prototype = {
	highlight: function() {
		this.activeElement.style.display = 'block';
		this.inactiveElement.style.display = 'none';
	},

	unHighlight: function() {
		this.activeElement.style.display = 'none';
		this.inactiveElement.style.display = 'block';
	}
};
/* Copyright (c) 2008 Shutterstock Images LLC */

function Easel(args) {

	this.properties = {

		canvases: {},

		moribundCanvas: undefined,
		activeCanvas: undefined,
		nascentCanvas: undefined,

		setCanvasOrder: function(args) { // direction
			args.direction = args.direction ? args.direction : 'forward';
			if (args.direction == 'forward') {
				this.nascentCanvas = this.activeCanvas.nextCanvas;
				this.moribundCanvas = this.activeCanvas.prevCanvas;	
			} else {
				this.nascentCanvas = this.activeCanvas.prevCanvas;
				this.moribundCanvas = this.activeCanvas.nextCanvas;	
			}
		},

		rotateCanvasContext: function(args) { // direction
			if (args.direction == 'forward') {
				this.activeCanvas = this.activeCanvas.nextCanvas;
			} else {
				this.activeCanvas = this.activeCanvas.prevCanvas;
			}
			this.setCanvasOrder(args);
		},

		updateCanvasDisplayStack: function(args) {

			args = args ? args : {};

			this.activeCanvas.element.style.zIndex = 30;
			this.moribundCanvas.element.style.zIndex = 20;
			this.nascentCanvas.element.style.zIndex = 10;

			this.moribundCanvas.element.hide();
			this.activeCanvas.element.show();

			if (args.pageScrollCallback) {
				args.pageScrollCallback();
			}

			this.activeCanvas.element.style.visibility = 'visible';
			this.activeCanvas.element.style.opacity = 1;

		}
	};

	base.instantiate(this);

	this.nascentCanvas = args.canvases.shift();
	this.activeCanvas = args.canvases.shift();
	this.moribundCanvas = args.canvases.shift();



	this.nascentCanvas.nextCanvas = this.activeCanvas;
	this.activeCanvas.nextCanvas = this.moribundCanvas;
	this.moribundCanvas.nextCanvas = this.nascentCanvas;

	this.moribundCanvas.prevCanvas = this.activeCanvas;
	this.activeCanvas.prevCanvas = this.nascentCanvas;
	this.nascentCanvas.prevCanvas = this.moribundCanvas;	
}
/* Copyright (c) 2008 Shutterstock Images LLC */

function Search(args) {

	this.properties = {

		locks: {
			showNextPage: false,
			detailsShowing: false,
			detailsClicks: false
		},

		entryPhoto: 0,

		dynamicResultsVersion: 102,

		elements: {},

		easel: args.easel,

		results: args.results,

		criteria: args.criteria,

		activePageNumber: undefined,

		showNextPage: function(args) { // e, showPrev, dontSetPage, dontProgress, dontConsultLocks, bootstrap, onlySetLocation

			args.direction = args.direction ? args.direction : 'forward';

			if (!args.iterationCount) {
				args.iterationCount = 1;
			}
	
			if (this.activePageNumber == 1 && args.direction == 'backward') {

				return; 
			}

			if (!args.bootstrap && this.activePageNumber == search.results.pageCount && args.direction == 'forward') {

				return;
			}	
		
			if (this.locks.showNextPage && !args.dontConsultLocks) {

				return;
			} else {
				this.locks.showNextPage = true;
			}


			if (args.iterationCount == 180 * 1000 / readyStateCheckInterval) {
				alert($t('DYNAMIC_RESULTS_ERROR_TIMEOUT', "We were unable to retreive more results due to a technical error.  Please try again."));
				this.locks.showNextPage = false;
				browser.toggleCursorState('revert', args.e);
				return;
			}
		
			if (!args.dontProgress) {
				this.easel.setCanvasOrder({ direction: args.direction });
				this.easel.rotateCanvasContext({ direction: args.direction });
			}

			var unitIncrement = args.direction == 'forward' ? 1 : -1;


			if (this.easel.activeCanvas.readyState == 'loading') {
				if (args.iterationCount == 1) {

				}
				setTimeout(
					function() { 
						this.showNextPage( {
							e: args.e, 
							direction: args.direction,
							dontSetPage: args.dontSetPage, 
							dontProgress: true, 
							dontConsultLocks: true,
							iterationCount: args.iterationCount + 1,
							bootstrap: args.bootstrap
						} ) 
					}.bind(this), 
					readyStateCheckInterval
				);
				return;

			} else if (this.easel.activeCanvas.readyState == 'uninitialized') {
				this.easel.activeCanvas.populateResults( { 
					pageNumber: this.activePageNumber + unitIncrement,
					callback: function() {
						this.showNextPage( {
							dontProgress: true,
							dontConsultLocks: true
						} );
					}.bind(this)
				} );
				return;
			}

			if (args.onlySetLocation) {

				browser.updateLocation( { args: { page: search.activePageNumber + unitIncrement } } );
				this.locks.showNextPage = false;
				this.pendingPagerLink = args.e;
				return;
			}

			var nextChapterNumber = parseInt(this.easel.activeCanvas.chapterNumber) + parseInt(unitIncrement);


			/* pre-fetch the next chapter if it looks like the user is paging through */
			if (
				nextChapterNumber > 0 
				&& searchResults.results[nextChapterNumber] == undefined 
				&& eval(
					'easel.activeCanvas.chapterPageNumber' + 
					(unitIncrement == 1 ? '>=' : '<=') + 
					'Math.round(pagesPerChapter / 2) + -1 * unitIncrement * Math.round(pagesPerChapter / 4)'
				)
				&& !searchResults.locks.chapterNumbers[nextChapterNumber]
				&& searchResults.count > nextChapterNumber * searchResults.resultsPerChapter
			) {

				this.results.fetch( { 
					searchCriteria: search.criteria.criteria, 
					chapterNumber: nextChapterNumber,
					unitIncrement: unitIncrement
				} );
			}
	

			this.easel.updateCanvasDisplayStack( { 
				pageScrollCallback: function(activePageNumber) { 
					this.activePageNumber = easel.activeCanvas.pageNumber;
					for (var i = 0; i < this.elements.currentPageIndicators.length; i++) { 
						this.elements.currentPageIndicators[i].value = this.activePageNumber;
					}
					window.scroll(0, 0);
				}.bind(this)
			} );

			searchControls.revertPagerLinkCursorStyles();

			this.locks.showNextPage = false;

			mouseoverEnabled = false;

			searchControls.syncPagerLinkClasses();
			
			var adjacentPageNumber = this.easel.activeCanvas.pageNumber + unitIncrement;

			if (adjacentPageNumber > 0 && adjacentPageNumber <= search.results.pageCount) {

				this.easel.nascentCanvas.populateResults( { pageNumber: adjacentPageNumber } );
			}
		},

		jumpToPage: function(pageNumber) {

			pageNumber = parseInt(pageNumber);
			if (pageNumber > search.results.pageCount) {
				pageNumber = search.results.pageCount;
			} else if (pageNumber < 1) {
				pageNumber = 1;
			}
			browser.toggleCursorState('progress', document.body);
			browser.updateLocation( { args: { page: pageNumber } } );
		},

		restoreResultsView: function(args) {
			args = args ? args : {};
			activeResultSlot = null;
			resultPreview.unPopulate( { dontClearCursor: true } );
			this.locks.detailsShowing = false;
		},

		resetActiveResultSlot: function(args) {
			args = args ? args : {};
			activeResultSlot = null;
			resultPreview.unPopulate( { dontClearCursor: true } );
		},

		showDetails: function(args) { // args: photoId, e, src
			if (this.locks.detailsClicks[args.photoId.toString()]) { 

				browser.toggleCursorState('revert');
				return;
			}

			browser.toggleCursorState('progress', args.e);

			this.canvasScrollOffset = document.viewport.getScrollOffsets().top;

			this.resetActiveResultSlot();

			currentSearchSrcId = '';
			if (args.src) {
				currentSearchSrcId = args.src;

			} else if (this.locks.detailsShowing && this.entryPhoto != args.photoId) {
				currentSearchSrcId = 'p';
		
			} else if (args.photoId) {

				this.entryPhoto = args.photoId;
				if (!currentSearchSrcId && this.easel.activeCanvas.photo_enume_map) {
					currentSearchSrcId = searchResults.searchSrcID + '-' + this.activePageNumber + '-' + this.easel.activeCanvas.photo_enume_map[args.photoId];
				}
			}

			this.locks.detailsShowing = true;
			this.locks.detailsClicks[args.photoId.toString()] = true;

			new Ajax.Updater('pic-page-container', '/show_component.mhtml', {
				parameters: {
					component_path: 'pic.mhtml',
					id: args.photoId,
					src: currentSearchSrcId
				},
				evalScripts: true,
				onSuccess: function() {
					if (browser.isSafari) { 
						$('cursor-indicator').hide();
					}
					$('loading-indicator').hide();
					search.elements.resultsContainer.style.display = 'none';
					$('search-results-header').style.display = 'none';
					easel.activeCanvas.element.style.visibility = 'hidden';

					search.elements.detailsContainer.style.display = 'block';
					search.elements.detailsContainer.style.visibility = 'visible';
					search.elements.detailsContainer.style.position = 'static';
					if (window.hidePopupExplanation) {
						hidePopupExplanation();
					}
				},
				onFailure: function() {
					alert($t('DYNAMIC_RESULTS_ERROR_PHOTO_DETAILS', "Unfortunately there was a technical error getting details about this photo"));
				},
				onComplete: function() {
					document.body.scrollTo(); 
					this.activePhotoId = args.photoId;
					browser.toggleCursorState('revert', args.e);
					this.locks.detailsClicks[args.photoId.toString()] = false;
					searchControls.syncSearchInputsDisplay();
					setKeywordSearchHandlers();
				}.bind(this)
			});
		}

	};

	base.instantiate(this);

	this.elements.currentPageIndicators = $$('.current-results-page');
	this.elements.resultsContainer = document.getElementById('results-container');
	this.elements.detailsContainer = document.getElementById('pic-page-container');
}
/* Copyright (c) 2008 Shutterstock Images LLC */

function SearchResults(args) {

	this.properties = {

		locks: {
			chapterNumbers: {}
		},

		elements: args.elements,

		results: {},

		count: undefined,

		activeRequestNumber: 0,		

		resultsPerChapter: args.resultsPerChapter,

		fetch: function(args) { // chapterNumber, callback, searchCriteria, unitIncrement, interruptPendingRequests, resultsPerChapter, initialSearch

			if (!args.interruptPendingRequests) {

				if (this.locks.chapterNumbers[args.chapterNumber]) {

					return;
				}

				if (this.results[args.chapterNumber]) {
					if (typeof args.callback == 'function') {
						args.callback();
					}

					return;
				}
			}

			this.locks.chapterNumbers[args.chapterNumber] = true;





			this.activeRequestNumber++;


			var request = new Ajax.Request('/show_component.mhtml', {
				method: Prototype.Browser.Webkit ? 'post' : 'get',
				evalScripts: false,
				parameters: 
					$H(args.searchCriteria).merge( {
						component_path: 'get_chapter_results_data.md',
						results_per_chapter: this.resultsPerChapter,
						chapter_number: args.chapterNumber,
						requestNumber: this.activeRequestNumber,
						rows_per_page: args.rowsPerPage,
						thumb_size: args.thumbSize,
						initialSearch: args.initialSearch,
						sort_method: args.sortMethod || defaultSortMethod,
						language: document.language,
						safesearch: disableSafesearch ? 0 : 1
					} ).toObject(),

				onFailure: function(transport) {
					if (transport.status == 500) {
						alert($t('DYNAMIC_RESULTS_ERROR_NEXT_PAGE', "Unfortunately, there was a technical problem retrieving the next page of search results."));
					}
				},
				onSuccess: function(transport) {



					if (transport.request.parameters.requestNumber != this.activeRequestNumber) { 

						this.locks.chapterNumbers[args.chapterNumber] = false;	
						return;
					}

					var response;
					if (transport.responseText.isJSON()) {

						response = transport.responseText.evalJSON(true);
					} else {
						log.fatal("got bad response: " + transport.status);
						this.locks.chapterNumbers[args.chapterNumber] = false;	
						browser.toggleCursorState('revert', args.e);
						return;
					}






					if (response.initialSearch) {
	
						this.count = response.resultsCount;
					    this.pageCount = Math.ceil(searchResults.count / resultsPerPage);

						this.normalizedQueryString = response.normalizedQueryString;
						this.sortMethod = response.sortMethod;

						if (window.easel) easel.activeCanvas.element.style.display = 'none';
						document.getElementById('loading-indicator').style.display = 'none';

						if (this.elements.header) {
							this.elements.header.innerHTML = response.searchResultsHeaderHTML;
						}

						response.searchResultsHeaderHTML.evalScripts();

						if (this.elements.recentSearches) {
							this.elements.recentSearches.innerHTML = response.recentSearchesHTML;
						}

						document.title = this.pageTitle = response.pageTitle;

					} else {
						if (response.normalizedQueryString != this.normalizedQueryString) {
							log.fatal('Got unexpected search results: ' + response.normalizedQueryString + ' vs ' + this.normalizedQueryString);
						}
					}
	
					this.results[response.chapterNumber] = response.results;
					this.searchSrcID = response.searchSrcID;

					if (typeof(args.callback) == 'function') {
						args.callback();
					}
					
					this.locks.chapterNumbers[args.chapterNumber] = false;


					var moribundChapterNumber = args.chapterNumber + -1 * args.unitIncrement * 2;
					if (moribundChapterNumber >= 0 && this.results[moribundChapterNumber]) {

						this.results[moribundChapterNumber] = undefined;
					}

				}.bind(this)
			} ).name = 'SearchResults#fetch';
		}
	}

	base.instantiate(this);
}
/* Copyright (c) 2008 Shutterstock Images LLC */

function SearchControls(args) {

	this.properties = {

		elementSelectors: args.elementSelectors,
	
		elements: args.elements || {},

		syncDisplayPrefSelects: function() {

			if (this.elements.rowsPerPageSelects) {
				for (var i = 0; i < this.elements.rowsPerPageSelects.length; i++) {
					var select = this.elements.rowsPerPageSelects[i];

					for (var j = 0; j < select.options.length; j++) {
						var option = select.options[j];

						if (option.value == rowsPerPage) {
							option.selected = true;
						} else {
							option.selected = false;
						}
					}
				}
			}

			if (this.elements.sortMethodSelects) {
				for (var i = 0; i < this.elements.sortMethodSelects.length; i++) {
					var select = this.elements.sortMethodSelects[i];

					for (var j = 0; j < select.options.length; j++) {
						var option = select.options[j];

						if (option.value == searchResults.sortMethod) {
							option.selected = true;
						} else {
							option.selected = false;
						}
					}
				}
			}

			if (this.elements.thumbSizeSelects) {
				for (var i = 0; i < this.elements.thumbSizeSelects.length; i++) {
					var select = this.elements.thumbSizeSelects[i];

					for (var j = 0; j < select.options.length; j++) {
						var option = select.options[j];

						if (option.value == activeThumbSize.name) {
							option.selected = true;
						} else {
							option.selected = false;
						}
					}
				}
			}
		},

		syncSearchInputsDisplay: function() {


			var pageArgs = browser.pageArgs;
			



			
			searchInputIds.each( function(inputElementId) {
				
				var e = $(inputElementId);
				
				if(!e) {
					return;
				}
			
				if (inputElementId == 'color-search-checkbox') {
					if (pageArgs.color) {
						$('color-hex-input').value = pageArgs.color;
						e.checked = true;
						$('colortable').show();
					} else {
						$('colortable').hide();
						$('color-hex-input').value = '';
						e.checked = false;		
					}
					return;
				}

				if (inputElementId == 'similar-photo-id-input') {
					if (pageArgs.similar_photo_id && pageArgs.similar_photo_id.toString().match(/^\d+$/)) {
						$('similar-images-container').show();
						$('similar-photo-id-display').update(pageArgs.similar_photo_id);
						new Ajax.Updater( $('similar-images-container').select('.thumb-cell').shift(), '/show_component.mhtml', {
							parameters: { id: pageArgs.similar_photo_id, size: 'thumb_small', scale_percentage: 40, component_path: 'show_image.mh' }
						} );
					} else {
						clearSimilarPhotoCriteria();
					}
				}

				if (e.tagName == 'INPUT' && e.type == 'checkbox') {

					if (e.className == 'safesearch-checkbox') {
						e.checked = !disableSafesearch;
						return;
					}

					if (parseInt(pageArgs[e.name])) {
						e.checked = true;
						if (e.className != 'safesearch-checkbox') {
							toggleCheckboxHighlight(e);
						}
					} else {
						e.checked = false;
						toggleCheckboxHighlight(e);
					}

				} else {
					if (pageArgs[e.name]) {
						e.value = pageArgs[e.name];
					} else {
						if (e.type == 'text') {
							e.value = '';
						} else if (e.name == 'search_cat') {
							e.value = '';
						} else if (e.name == 'orient' || e.name == 'search_group') {
							e.value = 'all'
						}
					}
					if (!e.id.match(/^view-selector-input/)) { 
						toggleInputHighlight(e);
					}
				}
			} );

			if (window.updateReleaseOptions) {
				window.updateReleaseOptions();
			}
			
		},

		setDisplayPrefs: function(args) { // thumbSize, rowsPerPage, sortMethod, callback

			new Ajax.Request( '/show_component.mhtml', {
				method: 'get',
				parameters: {
					component_path: 'set_display_prefs.md',
					rows_per_page: args.rowsPerPage,
					thumb_size: args.thumbSize,
					sort_method: args.sortMethod
				},
				onFailure: function() {
					alert($t('DYNAMIC_RESULTS_TROUBLE_SAVING_PREFS', "Unfortunately there was a problem saving your preferences"));
				},
				onSuccess: function() {
					if (args.callback) {
						args.callback();
					}
				}
			} );
		},

		syncPagerLinkClasses: function() {
			$A([$('pager-link-next-1'), $('pager-link-next-2')]).each( function(e) {
				if (search.activePageNumber == search.results.pageCount) {
					e.addClassName('disabled-pager-link');
				} else {
					e.removeClassName('disabled-pager-link');
				}
			} );	
			$A([$('pager-link-prev-1'), $('pager-link-prev-2')]).each( function(e) {
				if (search.activePageNumber == 1) {
					e.addClassName('disabled-pager-link');
				} else {
					e.removeClassName('disabled-pager-link');
				}
			} );	
		},

		toggleSafeSearch: function(args) {
			var safesearch = args.e.checked ? 1 : 0;
			disableSafesearch = !safesearch;
			$('safesearch-input').value = safesearch ? 1 : 0;
			browser.updateLocation( { args: { safesearch: safesearch ? 1 : 0 } } );
		},

		refreshSort: function(args) { // args: e

			browser.toggleCursorState('progress', args.e);
			search.restoreResultsView();
			defaultSortMethod = args.e.value;

			browser.updateLocation( { args: { sort_method: args.e.value }, e: args.e } );

			this.setDisplayPrefs( {sortMethod: args.e.value} );	
		},

		handleNextPageClick: function(e, direction) {
			if (search.locks.showNextPage) {
				browser.toggleCursorState('revert', e);
				return;
			}
			
			if (search.activePageNumber == 1 && direction == 'backward') {
				browser.toggleCursorState('revert', e);
				return;
			}

			if (search.activePageNumber == search.results.pageCount && direction == 'forward') {
				browser.toggleCursorState('revert', e);
				return;
			}

			setTimeout( function() {
				browser.toggleCursorState('progress', e);
				browser.updateLocation( { args: { page: search.activePageNumber + (direction == 'forward' ? 1 : -1) } } );
			}, 10);
		},
		
		revertPagerLinkCursorStyles: function() {
			for (var i = 0; i < this.elements.pagerLinks.length; i++) {
				var pagerLink = this.elements.pagerLinks[i];
				browser.toggleCursorState('revert', pagerLink);
			}
			
		}

	};
	
	base.instantiate(this);	

	$$(this.elementSelectors.sortMethodSelect).each(
		function(element) {
			element.observe('change', function() { log.debug("onchange"); this.refreshSort( { e: element } ) }.bind(this));
		},
		this 
	);

}
/* Copyright (c) 2008 Shutterstock Images LLC */

function SearchCriteria(args) {

	this.properties = {

		criteria: {},

		inconsequentialValues: {
			anyorall: 'all',
			search_group: 'all',
			orient: 'all',
			model_released: '0',
			commercial_ok: '0'
		},

		inconsequentialKeys: {	
			lang: 1, 	
			search_type: 1,
			page: 1,
			x: 1,
			y: 1
		},

		oldKeysMap: {
			submitter: 'submitter_id',
			gallery_id: 'submitter_id',
			cat: 'category_id',
			search_cat: 'category_id',
			orient: 'orientation',
			sortby: 'sort_method'
		},
	
		getNormalizedQueryString: function() {
		
			var pairs = [];
	
			$H(this.criteria).keys().sortBy( function (s) { return s } ).each(
				function(key) {
					if (this.inconsequentialKeys[key]) {
						return;
					}
					var normalizedKey = this.oldKeysMap[key] || key;
					pairs.push(normalizedKey + '=' + encodeURIComponent(this.criteria[key]));
				},
				this
			);

			return pairs.join('&');
		}
	};

	base.instantiate(this);

	$H(args.criteria).each( function(pair) {
		if (this.inconsequentialValues[pair.key] == pair.value) {
			return;
		}
		if (this.inconsequentialKeys[pair.key]) {
			return;
		}
		if (pair.value == undefined || pair.value == '') {
			return;
		}

		this.criteria[pair.key] = pair.value;

	}, this );
}
	
/* Copyright (c) 2008 Shutterstock Images LLC */

function ResultPreview(args) {

	var self = arguments.callee;
	if (self.instantiated) return;
	self.instantiated = true;

	this.properties = {

		elements: args.elements,

		showing: false,

		locks: {
			thumbLoad: {}
		},

		activeResultSlot: {},






		populate: function(args) {

			var resultSlot = args.resultSlot;

			this.showing = true;





			var thumb = resultSlot.elements.thumb;
			var previewThumb = this.elements.thumb;
			var previewImage = this.elements.previewImage;


			var imageSrc = resultSlot.previewThumbSrc
				? resultSlot.previewThumbSrc
				: ['http:/', resultSlot.result.host, 'photos', 'display_pic_with_logo', resultSlot.result.set_name, resultSlot.result.filename].join('/');


			if (previewImage.src == imageSrc) {
				this.show();
			} else {
				this.locks[resultSlot.id] = true;


				var hqAnnotationHeight = 20;

				var dimensionMax = 450;


				var aspectRatio = args.resultSlot.result.aspect_ratio;
				var displayHeight = aspectRatio < 1
					? dimensionMax
					: Math.round(dimensionMax / aspectRatio);
				var displayWidth = aspectRatio < 1
					? Math.round(dimensionMax * aspectRatio)
					: dimensionMax;


				var previewContainer = previewThumb.parentNode;
				previewContainer.style.height = displayHeight + 'px';
				previewContainer.style.width = displayWidth + 'px';
				previewContainer.style.overflow = 'hidden';


				var iframeBacking = this.elements.iframeBacking;
				if (iframeBacking) {
					iframeBacking.style.height = (displayHeight + 65) + 'px';
					iframeBacking.style.width = (displayWidth + 65) + 'px';
				}


				this.position( {
					resultSlot: resultSlot,
					placement: args.placement,
					fixedContainer: args.fixedContainer,
					fixedAncestor: args.fixedAncestor
				} );


				previewThumb.show();
				previewImage.hide();



				previewImage.src = imageSrc;
				previewImage.height = displayHeight + hqAnnotationHeight;
				previewImage.width = displayWidth;

				previewImage.onload = function () {

					if (this.locks[resultSlot.id]) {
						browser.toggleCursorState('revert', this.activeResultSlot.elements.thumb, 'local');
						this.locks[resultSlot.id] = false;
					}
					previewThumb.hide();
					previewImage.show();
				}.bind(this);




				if(!thumb) {

					return;
				}
				previewThumb.src = thumb.src;
				previewThumb.height = aspectRatio <= 1
					? dimensionMax
					: dimensionMax * (thumb.naturalHeight || thumb.height) / (thumb.naturalWidth || thumb.width);
				previewThumb.width = aspectRatio <= 1
					? dimensionMax * (thumb.naturalWidth || thumb.width) / (thumb.naturalHeight || thumb.height)
					: dimensionMax;
				



				this.elements.container.style.display = 'block';
			}



			setTimeout(function() {
				if (this.locks[resultSlot.id]) {
					browser.toggleCursorState('progress', thumb, 'local');
				}
			}.bind(this), 1000);

		},

		unPopulate: function(args) {
			if (!args) args = {};
			this.locks[this.activeResultSlot.id] = false;
			this.elements.container.style.display = 'none';	
			this.showing = false;
			if (this.activeResultSlot.elements && !args.dontClearCursor) {
				browser.toggleCursorState('revert', this.activeResultSlot.elements.thumb, 'local'); 
			}

			newlyActiveThumb = false;
		},

		position: function(args) { // resultSlot, placement

			this.activeResultSlot = args.resultSlot;

			var thumbPosition;

			if (args.fixedContainer && args.fixedAncestor) {
				thumbPosition = browser.getFixedPosition(args.fixedContainer, args.resultSlot.elements.container, args.fixedAncestor);
			} else {
				thumbPosition = browser.getElementScreenPosition(args.resultSlot.elements.container);
			}

			var viewportDimensions = document.viewport.getDimensions();
			var viewportOffsets = document.viewport.getScrollOffsets();

			var padding = 10; // pixels


			var dimensions = args.resultSlot.getDimensions(450);


			var previewHeight = dimensions.height + 60;
			var previewWidth = dimensions.width + 60;

			var thumbSize = activeThumbSize;
			var thumbHeight = thumbSize.max_dimension_pixels;
			var thumbWidth = thumbHeight;

			var berth = {
				top: thumbPosition.top - previewHeight,
				left: thumbPosition.left - previewWidth,
				bottom: viewportDimensions.height - thumbPosition.top - previewHeight,
				right: viewportDimensions.width - thumbPosition.left - thumbWidth - previewWidth
			}; 

			var bestPlacement;
			$H(berth).keys().each( function(placement) {
				bestPlacement = bestPlacement ? bestPlacement : placement;
				bestPlacement = berth[placement] > berth[bestPlacement] ? placement : bestPlacement;
			} );

			bestPlacement = bestPlacement ? bestPlacement : 'bottom';
			var previewPosition;

			switch (bestPlacement) {
				case 'top':
					previewPosition = {
						top: thumbPosition.top - previewHeight - padding,
						left: thumbPosition.left + (thumbWidth / 2) - (previewWidth / 2)
					};
					break;
				case 'left':
					previewPosition = {
						top: thumbPosition.top + (thumbHeight / 2) - (previewHeight / 2),
						left: thumbPosition.left - previewWidth - padding
					};
					break;
				case 'bottom':
					previewPosition = {
						top: thumbPosition.top + thumbHeight + padding,
						left: thumbPosition.left + (thumbWidth / 2) - (previewWidth / 2)
					};
					break;
				case 'right':
					previewPosition = {
						top: thumbPosition.top + (thumbHeight / 2) - (previewHeight / 2),
						left: thumbPosition.left + thumbWidth + padding
					};
					break;
			}

			var containerStyle = this.elements.container.style;
			$w('top left').each( function(dimension) {
				if (previewPosition[dimension] !== null) {

					if ((bestPlacement == 'left' || bestPlacement == 'right') && (dimension  == 'top')
						|| (bestPlacement == 'top' || bestPlacement == 'bottom') && (dimension  == 'left')) {
					
						if (previewPosition[dimension] < 0) {
							previewPosition[dimension] = padding;

						} else if (dimension == 'left' && previewPosition[dimension] + previewWidth > viewportDimensions.width) {
							previewPosition[dimension] = viewportDimensions.width - previewWidth - padding;

						} else if (dimension == 'top' && previewPosition[dimension] + previewHeight > viewportDimensions.height) {
							previewPosition[dimension] = viewportDimensions.height - previewHeight - padding;
						}
	
					}

					if (dimension == 'top' || dimension == 'bottom') {
						containerStyle[dimension] = previewPosition[dimension] + viewportOffsets.top + 'px';
					} else {
						containerStyle[dimension] = previewPosition[dimension] + 'px';
					}
				
				} else {
					containerStyle[dimensions] = null;
				}
			} );

		},
		show: function() {
			if (!this.showing) return;
			this.elements.container.style.display = 'block';
			if (window.hidePopupExplanation) {
				hidePopupExplanation();
			}
		}
	};


	base.instantiate(this);


	this.elements.previewImage = new Image();
	$(this.elements.previewImage).hide();
	this.elements.thumb.parentNode.insertBefore(
		this.elements.previewImage,
		this.elements.thumb
	);

	this.elements.thumb.observe('load', this.show.bind(this));
}



var legacyActiveThumb;
function previewThumb(e) {
	legacyActiveThumb = e;
	setTimeout( function() {
		if (legacyActiveThumb && legacyActiveThumb.src == e.src) {

			var container = legacyActiveThumb.parentNode.parentNode;

			var thumbWidth = parseInt(container.style.width);
			var thumbHeight = parseInt(container.style.height);

			if (!thumbWidth || !thumbHeight) {

			}

			var fakeResultSlot = {
				elements: {
					container: legacyActiveThumb.parentNode.parentNode,
					thumb: legacyActiveThumb
				},
				getDimensions: function(maxDimensionPixels) {
					
					var multiplier = maxDimensionPixels / Math.max(thumbWidth, thumbHeight);
					return { 
						width: thumbWidth * multiplier, 
						height: thumbHeight * multiplier
					};
				},
				result: {
					aspect_ratio: (thumbWidth / thumbHeight)
				},
				previewThumbSrc: legacyActiveThumb.src.replace(/\/thumb_(small|large)\//, '/display_pic_with_logo/')
			};

			if (window.resultPreview) {
				var lightboxContainer = document.getElementById('lightbox-contents-table');
				var lightboxFixedAncestor = document.getElementById('lightbox-preview-container');
				var fixedContainer = lightboxContainer && Element.extend(legacyActiveThumb).descendantOf(lightboxContainer) ? lightboxContainer: null;
				resultPreview.populate( { resultSlot: fakeResultSlot, fixedContainer: fixedContainer, fixedAncestor: lightboxFixedAncestor } );
				resultPreview.show();
			}
		}
	}, 250);
}
function cancelPreview(e) {
	legacyActiveThumb = null;
	if (window.resultPreview) {
		resultPreview.unPopulate();
	}
}
/* Copyright (c) 2008 Shutterstock Images LLC */

function Browser(args) {

	args = args ? args : {};

	this.properties = {

		pageArgs: {},

		mouseSpeed: undefined,

		mousePosition: {},

		prevMousePosition: {},

		mouseoverEnabled: false,

		showingCursorIndicator: false,

		updateLocationCallback: args.updateLocationCallback,

		currentLocation: undefined,

		historyEventHandler: args.historyEventHandler,

		parameterNames: args.parameterNames || [],

		history: YAHOO.util.History,

		pendingLinkElements: [],

		historyEventCallbacks: [],

		parseArgs: function(args) {
			args = args ? args : {};
			args.stateType = args.stateType ? args.stateType : 'current';
			var pageArgs = {}; 
			for (var i = 0; i < this.parameterNames.length; i++) {
				var parameterName = this.parameterNames[i];
				if (args.stateType == 'bookmarked') {
					pageArgs[parameterName] = this.history.getBookmarkedState(parameterName);
				} else {
					pageArgs[parameterName] = this.history.getCurrentState(parameterName);
				}
			}
			return pageArgs;
		},

		registerHistoryEventCallback: function(cb) {
			this.historyEventCallbacks.push(cb);
		},

		updateLocation: function(args) { // args: args, clear, e
			browser.toggleCursorState('progress', args.e);
			this.pendingLinkElements.push(args.e);

			if (args.clear) {
				this.pageArgs = {};
			}
			
			for (var i = 0; i < this.parameterNames.length; i++) {
				var parameterName = this.parameterNames[i];
				this.pageArgs[parameterName] = args.args[parameterName] !== undefined ?  args.args[parameterName] : this.pageArgs[parameterName] || '';
			}

			var queryString = $H(this.pageArgs).toQueryString();

			browser.history.multiNavigate(this.pageArgs);

			if (this.updateLocationCallback) {
				this.updateLocationCallback();
			}

			if (!args.args.photo_id) {
				window.name = queryString;
			}
		},


		getElementPosition: function(obj, containerId) {
				var left = 0, top = 0;
				if (obj.offsetParent) {
						do {
							if (containerId && obj.id == containerId) {
								break;
							}
							left += obj.offsetLeft;
							top += obj.offsetTop;
						} while (obj = obj.offsetParent);
				}
			
			return { left: left, top: top };
		},

		getElementScreenPosition: function(e, fixedOffsets) {
			
			var elementPagePosition = this.getElementPosition(e);
			var scrollOffsets = fixedOffsets ? fixedOffsets : document.viewport.getScrollOffsets();
	
			return { 
				left: elementPagePosition.left - scrollOffsets.left,
				top: elementPagePosition.top - scrollOffsets.top
			};
		},

		getFixedPosition: function(container, element, fixedAncestor) {

			var elementPosition = this.getElementPosition(element, container.id);

			var elementAdjustedTop = elementPosition.top - container.scrollTop;
			var elementAdjustedLeft = elementPosition.left - container.scrollLeft;
			
			var containerPosition;
			if (Element.getStyle(fixedAncestor, 'position') == 'fixed') {
				containerPosition = this.getElementPosition(container);
			} else {
				containerPosition = this.getElementScreenPosition(container);
			}

			var elementScreenTop = elementAdjustedTop + containerPosition.top;
			var elementScreenLeft = elementAdjustedLeft + containerPosition.left;

			return { top: elementScreenTop, left: elementScreenLeft };

		},

		toggleCursorState: function(state, e, scope) {

			if (this.isSafari) {
				
				var cursorIndicator = $('cursor-indicator');

				if (state == 'revert') {
					cursorIndicator.hide();	

				} else {
					this.showingCursorIndicator = true;
					this.positionCursorIndicator();
					cursorIndicator.show();
				}

			} else {

				if (state == 'revert') {
					if (e && e.style.cursor == 'progress') {
						e.style.cursor = initialElementCursorStyles[e.id];
					}
					if (scope != 'local') {
						document.body.style.cursor = 'auto';
					}

				} else {
					if (e && e.style.cursor != 'progress') {
						initialElementCursorStyles[e.id] = e.style.cursor;
					}

					if (e) e.style.cursor = state;

					if (scope != 'local') {
						document.body.style.cursor = state;
					}
				}
			}
		},

		updateMouseSpeed: function() {

			var localMouseSpeed = Math.sqrt(
				Math.pow(this.mousePosition.x - this.prevMousePosition.x, 2) + 
				Math.pow(this.mousePosition.y - this.prevMousePosition.y, 2)
			);

			if (!this.mouseoverEnabled && localMouseSpeed > 3) { 

				this.mouseoverEnabled = true;
				return;
			}		

			this.mouseSpeed = localMouseSpeed;

			this.prevMousePosition.x = this.mousePosition.x;
			this.prevMousePosition.y = this.mousePosition.y;


		},

		updateMousePosition: function(event) {

			this.mousePosition = {
				x: event.clientX,
				y: event.clientY
			};

			if (this.showingCursorIndicator) {
				this.positionCursorIndicator();	
			}

			return;
		},

		positionCursorIndicator: function() {
			var scrollOffsets = document.viewport.getScrollOffsets();

			this.containerOffsets = this.getElementPosition($('cursor-indicator-container'));

			$('cursor-indicator').style.top = this.mousePosition.y - this.containerOffsets.top + 16 + 'px';
			$('cursor-indicator').style.left = this.mousePosition.x - this.containerOffsets.left + 16 + 'px';
		},

		wait: function(args) {
			args.iterationCount = args.iterationCount ? args.iterationCount : 0;
			if (eval(args.condition)) {
				if (typeof(args.callback) == 'function') {
					args.callback();
				}
			} else if (args.iterationCount > 40) {
				log.fatal('waited too long for ' + args.condition);

			} else {

				setTimeout( function() { 
					browser.wait( { 
						retryInterval: args.retryInterval, 
						condition: args.condition, 
						iterationCount: args.iterationCount + 1 
					} ) 
				}, args.retryInterval);
			}
		},

		getHash: window.getLocationHash
/*
		isSupported: function() {

			var supportedBrowserVersions = {
				Explorer: 6,
				Opera: 9,
				Firefox: 2,
				Safari: 3 
			};

			if (BrowserDetect.version >= supportedBrowserVersions[ BrowserDetect.browser ]) {
				return true;
			} else {
				return false;
			}
		}
*/

	};

	base.instantiate(this);

	document.observe('mousemove', function(e) { this.updateMousePosition(e) }.bindAsEventListener(this) );
	setInterval( function() { this.updateMouseSpeed() }.bind(this), 100 );

	this.history.onReady( function() {
		if (args.historyReadyCallback) {
			args.historyReadyCallback();
		}
	} );

	for (var i = 0; i < this.parameterNames.length; i++) {
		var parameterName = this.parameterNames[i];
		this.history.register(parameterName, this.history.getBookmarkedState(parameterName), function() {} );
	}

	if (args.historyEventHandler) {
		try {
			YAHOO.util.History.initialize("yui-history-field", "yui-history-iframe", args.historyEventHandler);

		} catch (e) {



			log.fatal('history error: ' + e.message);
		}
	}

	Event.observe(window, 'scroll', function() { 
		if (resultPreview.showing) {

			search.resetActiveResultSlot();
		}
		this.mouseoverEnabled = false;
	}.bind(this) );

	this.isSafari = navigator.userAgent.indexOf('AppleWebKit/') > -1; 

}
/************************
 * Patterns (patterns.js)
 */
Ss = window.Ss || {};
Ss.patterns = {};


/* SUBJECT */
Ss.patterns.Subject = Class.create({
	initialize: function() {
		this.observers = [];
	},
	subscribe: function(f) {
		this.observers.push(f);	
	},
	unsubscribe: function(f) {
		this.observers = this.observers.without(f);
	},
	notify: function(data) {
		this.observers.each(function(fn) {
			fn(data);
		});
	}
});


/* ABSTRACT MODEL */
Ss.patterns.Model = Class.create(Ss.patterns.Subject, {
	initialize: function($super, data) {
		$super();
		this.data = data;
	},
	set: function(data) {
		this.data = data;
		this.notify(data);
	}
});


/* ABSTRACT VIEWS */
Ss.patterns.View = Class.create({
	initialize: function(element, model, controller) {
		this.element = element;
		this.model = model;
		this.controller = controller;
		
		this.model.subscribe(this.update.bind(this));
		this._events();
	},
	observe: function(eType) {
		this.element.observe(eType, this.controller[eType]);
	},
	update: function(data) { 

		this.element.update(data);
	},
	_events: function() { /*abstract*/ }
});

Ss.patterns.CompositeView = Class.create(Ss.patterns.View, {
	initialize: function($super, element, model, controller) {
		$super(element, model, controller);
		this._views = [];
	},
	update: function() {
		this._views.invoke('update');
	},
	add: function(view) {
		this._views.push(view);
	},
	remove: function(view) {
		this._views = this.views.reject(function(v){return view == v});
	},
	get: function(index) {
		return this.children[index];
	}
});


/* ABSTRACT CONTROLLERS */
Ss.patterns.Controller = Class.create({
	initialize: function(model) {
		this.model = model;
	},
	click: function(event) { /*abstract*/ }
});
/*********************
 * Utilities (util.js)
 */
Ss = window.Ss || {};
Ss.util = {};
Ss.util.disableTextSelection = function(element) {
	element.onselectstart = function() { return false; };
	element.unselectable = "on";
	element.style.MozUserSelect = "none";
};
Ss.util.getElementText = function(element) {
	var ret = $A(element.childNodes).collect(function(c){
		if(c.nodeType != 8){
			return (c.nodeType != 1 ? c.nodeValue: Ss.util.getElementText(c))
		}
	}).join('');
	return ret.strip();
};
Ss.util.isIE6 = function() {
	return (Prototype.Browser.IE &&
		parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5))==6);
};
/***********
 * Pulldown
 */
Ss = window.Ss || {};
Ss.Pulldown = Class.create(Ss.patterns.Subject, {
	initialize: function($super, element, trigger, content, contentContainer, titleBar) {
		$super();
		this.element = element
		this.trigger = trigger;
		this.content = content;
		this.contentContainer = contentContainer;
		this.titleBar = titleBar;
		this.state = "";
		this.collapse();
		this._decorate();
		this._events();
		this._tId;
		Ss.Pulldown.INSTANCES.set(this.element.identify(), this);
	},
	collapse: function() {
		this._setState(Ss.Pulldown.STATES.collapsed);
		this._postCollapse();
	},
	expand: function() {
		this._setState(Ss.Pulldown.STATES.expanded);
		this._postExpand();
	},
	appendContent: function(content) {
		$(this.content).insert(content);
		this.reconfigure();
	},
	appendJson: function(jsonArr) {
		jsonArr = (Object.isArray(jsonArr) ? jsonArr : [jsonArr]);
		Ss.Pulldown.jsonToItems(jsonArr).each(
			function(item) {
				this._appendItem(item);		
			}, this);
		this.reconfigure();
	},
	replaceContent: function(content) {
		$(this.content).update(content);
		this.reconfigure();
	},
	replaceTrigger: function(trigger) {
		$(this.trigger).update(trigger);

		$(this.trigger).insert('<a class="pulldown_open_icon">&#9660;</a>');
	},
	clearContent: function(){
		this.replaceContent('');
	},
	appendToTrigger: function(content) {
		$(this.trigger).insert(content);
	},

	reconfigure: function() {
		if(this.state == Ss.Pulldown.STATES.expanded) {
			this._postExpand();
		}
	},
	disableAutoClose: function() {
		$(this.element).stopObserving('mouseout');
	},
	enableAutoClose: function() {
		$(this.element).observe('mouseout', this._mouseout.bind(this));
	},
	showLoading: function() {
		$(this.element).addClassName(Ss.Pulldown.COMPONENTS.loading);
	},
	hideLoading: function() {
		$(this.element).removeClassName(Ss.Pulldown.COMPONENTS.loading);
	},
	getElement: function() {
		return this.element;
	},
	/* private */
	_postExpand: function() {
		this._expandResize();
	},
	_postCollapse: function() {
		this._collapseResize();
	},
	destroy: function() {
		$(this.element, this.trigger, this.content, this.contentContainer).invoke('stopObserving');
		try { $(this.element).remove(); }
		catch(e) { /*console.log(e)*/ }
	},
	_appendItem: function(item) {
		if(!$(this.content).select("UL").size() > 0) {
			$(this.content).insert(new Element("UL"));
		}
		$(this.content).select("UL").pop().insert(item);
	},
	_toggleState: function() {
		this.state == Ss.Pulldown.STATES.expanded ? this.collapse() : this.expand();
	},
	_events: function() {
		$(this.trigger).observe('click', this._click.bind(this));
		$(this.element).observe('mouseout', this._mouseout.bind(this));
		$(this.element).observe('mouseover', this._mouseover.bind(this));
		$(this.titleBar).observe('click', this.collapse.bind(this));
		Ss.util.disableTextSelection(this.trigger);
	},
	_click: function(event) {
		this._toggleState();
	},
	_mouseout: function(event) {
		if( !Position.within($(this.element), Event.pointerX(event), Event.pointerY(event)) &&
			!Position.within($(this.contentContainer), Event.pointerX(event), Event.pointerY(event)) &&
			this.state != Ss.Pulldown.STATES.collapsed)
		{
			this._tId = (function() {
				this.collapse();
			}).bind(this).delay(Ss.Pulldown.COLLAPSE_DELAY_SECONDS);
		}
	},
	_mouseover: function(event) {
		if(this._tId)
			window.clearTimeout(this._tId);
	},
	_reset: function() {
		$H(Ss.Pulldown.STATES).values().each(function(state) {
			$(this.element).removeClassName(state);
		}, this);
	},
	_decorate: function() {
		$(this.contentContainer).insert({
			top: new Element("DIV").update(
				$R(1,9).collect(function(i) {
					return '<div class="drop shadow-' + i + '"></div>';		
				}).join(''))
		});
	},
	_setState: function(state) {
		this._reset();
		this.state = state;
		$(this.element).addClassName(state);
		this.notify({state: state});
	},
	/* Resizing DOM Manipulation */

	_expandResize: function() {
		var elemW = $(this.element).getWidth();
		var contW = $(this.content).descendants().findAll(function(d){return $(d).visible() && !$(d).tagName.include('STYLE')}).invoke('getWidth').max();
		var largerW = (contW > elemW ? contW : elemW);	
		$(this.contentContainer).setStyle({width: largerW  + "px"});
	},
	_collapseResize: function() {
		$(this.contentContainer).setStyle({width: ""});
	}
});


if(Prototype.Browser.IE) {
	Ss.Pulldown.addMethods({
		_postExpand: function() {
			this._expandResize();
			if(Ss.util.isIE6()) {
				this._stretchContent();
				this._showIframe();
			}
		},
		_postCollapse: function() {
			this._collapseResize();
			this._roundTrigger();
			this._hideIframe();
		},
		_showIframe: function() {
			if(!this._iframe) {
				var iframe = new Element('IFRAME', {
					frameborder: 0
				});
				var dim = $(this.contentContainer).getDimensions();
				iframe.setStyle({
					position: 'absolute',
					top: '0',
					left: '0',
					height: dim.height + 'px',
					width: dim.width + 'px',
					zIndex: '-1'
				});
				this.contentContainer.insert({top: iframe});
				this._iframe = iframe;
			}
			$(this._iframe).show();
		},
		_hideIframe: function() {
			if(this._iframe) {
				$(this._iframe).hide();
			}
		},
		_stretchContent: function() {
			var c = this.contentContainer, d = c.getDimensions();
			var _width = d.width;
			var _tWidth = _width - 34;
			var _height = d.height - 7;
			
			[2,8].each(function(i){
				$(c).select('.shadow-' + i).shift().setStyle({width: _tWidth + 'px'})
			});
			[4,6].each(function(i){
				$(c).select('.shadow-' + i).shift().setStyle({height: _height + 'px'})
			});
			this.titleBar.setStyle({width: _width + 'px'});
		},
		_roundTrigger: function() {
			if(!this._rounded) {
				$(this.element).insert({
						top: new Element("DIV").update(
							$R(1,4).collect(function(pos) {
								return '<div class="t_corner tc_' + pos + '"></div>';
						}).join(''))
				});
				this._rounded = true;
			}
		}
	});
}

/****************
 * Ajax Pulldown
 */
Ss.AjaxPulldown = Class.create(Ss.Pulldown, {
	initialize: function($super, element, trigger, content, contentContainer, titleBar, url, parameters, callback) {
		$super(element, trigger, content, contentContainer, titleBar);
		this.url = url;
		this.parameters = parameters;
		this.callback = callback;
		this.isLoaded = false;
	},
	load: function() {
		this.showLoading();
		this.isLoaded = true;
		var ap = this;
		var xhr = new Ajax.Request(ap.url, {
			parameters: ap.parameters,
			onSuccess: function(response) {
				ap.appendContent(response.responseText);
				response.responseText.evalScripts();
				ap._doCallback(response);
				ap.expand();
				ap.hideLoading();
			}
		});			
	},
	setCallback: function(f) {
		this.callback = f;
	},
	_doCallback: function(response) {
		if(Object.isFunction(this.callback)) {
			this.callback.call(this, response);
		}		
	},
	_click: function(event) {
		this[ this.isLoaded ? '_toggleState' : 'load']();
	}
});


/******************
 * Select Pulldown
 */
Ss.SelectPulldown = Class.create(Ss.Pulldown, {
	initialize: function($super, element, trigger, content, contentContainer, titleBar, charLimit) {
		$super(element, trigger, content, contentContainer, titleBar);
		this.charLimit = charLimit;
	},
	items: function() {
		return $(this.element).select('LI');
	},
	select: function(key) {
		var item = this.find(key);
		if(item) {
			return this._select(item);
		}
		throw("Item '" + key + "' not found");
	},
	find: function(key) {
		if(Object.isNumber(key) 
			&& this.items().length > key) 
		{
			return this.items()[key];
		}
		if(Object.isString(key)) {
			return this.items().find(function(item) {
				return (Ss.util.getElementText(item).toLowerCase() == key.toLowerCase())
			});
		}
		return false;
	},
	_appendItem: function($super, item) {
		this._registerItem(item);
		$super(item);
	},
	_select: function(item) {
		this.items().invoke("show");
		$(item).hide();
		this.replaceTrigger(this._toTrigger(item));
		this.collapse();
		this.notify({state: this.state, selected: item});
	},
	_toTrigger : function(item) {
		var triggerText = Ss.util.getElementText(item).truncate(this.charLimit);
		var icon = $(item).select("IMG").shift();
		var trigger = new Element('SPAN').update(triggerText);
		if(icon) {
			trigger.insert({top: icon.cloneNode(true)});
		}
		return trigger;
	},
	_events: function($super) {
		$super();
		this._registerItems();
	},
	_registerItems: function() {
		this.items().each(function(item) {
			this._registerItem(item);
		}, this);
	},
	_registerItem: function(item) {
		$(item).observe('click', (function(event) {
			this._select(item);
		}).bind(this));
	}
});


/***********************
 * Ajax Select Pulldown
 */
Ss.AjaxSelectPulldown = Class.create(Ss.SelectPulldown);
Ss.AjaxSelectPulldown.addMethods({
	initialize: function($super, element, trigger, content, contentContainer, titleBar, charLimit, url, parameters, callback) {
		$super(element, trigger, content, contentContainer, titleBar, charLimit);

		this.url = url;
		this.parameters = parameters;
		this.callback = callback;
		this.isLoaded = false;
	},

	load: Ss.AjaxPulldown.prototype.load,
	setCallback: Ss.AjaxPulldown.prototype.setCallback,
	_click: Ss.AjaxPulldown.prototype._click,
	_doCallback: function(response) {
		this._registerItems();
		Ss.AjaxPulldown.prototype._doCallback.apply(this);
	}
});


/**************************
 * Class Properties/Methods
 */
Ss.Pulldown.INSTANCES = new Hash();
Ss.Pulldown.COLLAPSE_DELAY_SECONDS = .5;
Ss.Pulldown.STATES = { //CSS class names applied/removed when current state changes
	collapsed: 'collapsed',
	expanded: 'expanded'
};
Ss.Pulldown.COMPONENTS = { //CSS class names used for various elements/subcomponents
	element: 'pulldown',
	trigger: 'pulldown_trigger',
	contentContainer: 'pulldown_content_container',
	content: 'pulldown_content',
	loading: 'pulldown_loading',
	openIcon: 'pulldown_open_icon',
	titleBar: 'pulldown_title_bar'
};

Ss.Pulldown.get = function(id) {
	return Ss.Pulldown.INSTANCES.get(id);
};

Ss.Pulldown.create = function(id) {
	return Ss.Pulldown.construct(Ss.Pulldown.createElement(id));
};

Ss.Pulldown.construct = function(element) {
	return new Ss.Pulldown(element, 
		Ss.Pulldown.getComponent(element, Ss.Pulldown.COMPONENTS.trigger), 
		Ss.Pulldown.getComponent(element, Ss.Pulldown.COMPONENTS.content),
		Ss.Pulldown.getComponent(element, Ss.Pulldown.COMPONENTS.contentContainer),
		Ss.Pulldown.getComponent(element, Ss.Pulldown.COMPONENTS.titleBar));
};
Ss.AjaxPulldown.construct = function(element, url, parameters, callback) {
	return new Ss.AjaxPulldown(element,
		Ss.Pulldown.getComponent(element, Ss.Pulldown.COMPONENTS.trigger), 
		Ss.Pulldown.getComponent(element, Ss.Pulldown.COMPONENTS.content),
		Ss.Pulldown.getComponent(element, Ss.Pulldown.COMPONENTS.contentContainer),
		Ss.Pulldown.getComponent(element, Ss.Pulldown.COMPONENTS.titleBar),
		url, parameters, callback);
};
Ss.SelectPulldown.construct = function(element, charLimit) {
	return new Ss.SelectPulldown(element, 
		Ss.Pulldown.getComponent(element, Ss.Pulldown.COMPONENTS.trigger), 
		Ss.Pulldown.getComponent(element, Ss.Pulldown.COMPONENTS.content),
		Ss.Pulldown.getComponent(element, Ss.Pulldown.COMPONENTS.contentContainer),
		Ss.Pulldown.getComponent(element, Ss.Pulldown.COMPONENTS.titleBar),
		charLimit);
};
Ss.AjaxSelectPulldown.construct = function(element, charLimit, url, parameters, callback) {
	return new Ss.AjaxSelectPulldown(element,
		Ss.Pulldown.getComponent(element, Ss.Pulldown.COMPONENTS.trigger), 
		Ss.Pulldown.getComponent(element, Ss.Pulldown.COMPONENTS.content),
		Ss.Pulldown.getComponent(element, Ss.Pulldown.COMPONENTS.contentContainer),	
		Ss.Pulldown.getComponent(element, Ss.Pulldown.COMPONENTS.titleBar),
		charLimit, url, parameters, callback);
};

Ss.Pulldown.createElement = function(id) {
	var t = new Template('<div class="#{trigger}"><a class="#{openIcon}">&#9660;</a></div><div class="#{contentContainer}"><div class="#{content}"></div><div class="#{titleBar}"><a>&#215;</a></div></div>');
	var element = new Element("DIV", {"class": Ss.Pulldown.COMPONENTS.element}).insert(t.evaluate(Ss.Pulldown.COMPONENTS));
	return ( id ? element.writeAttribute({"id":id}) : element );
};

Ss.Pulldown.getComponent = function(element, type) {
	return $(element).select("." + type).shift();
};

Ss.Pulldown.jsonToItem = function(obj) {
	var anchor = new Element('A').update(obj.name);
	var item = new Element('LI').update(anchor);	
	if(obj.icon_src) {
		anchor.insert({top: new Element('IMG', {src: obj.icon_src})});
	}
	if(Object.isString(obj.onclick)) {
		item.observe('click', function() {eval(obj.onclick);})
	}
	else if(Object.isFunction(obj.onclick)) {
		item.observe('click', obj.onclick);
	}
	return item;
};
Ss.Pulldown.jsonToItems = function(jsonArr) {
	var items = [];
	jsonArr.each(function(obj) {
		items.push(Ss.Pulldown.jsonToItem(obj));
	});
	return items;
};


Ss.Pulldown.convert = function(select, id, charLimit) {
	var sOptions = select.select('option');
	var sPulldown = Ss.SelectPulldown.construct(Ss.Pulldown.createElement(id), charLimit);
	var optionsJson = sOptions.collect(function(option, i){return {name: option.text, index: i};});
	sPulldown.appendJson(optionsJson);
	sPulldown.select(select.options[select.selectedIndex].text);
	sPulldown.subscribe(function(state){
		var selectedItem = state.selected;
		if(selectedItem){
			var selectedText = Ss.util.getElementText(selectedItem);
			var itemObj = optionsJson.find(function(obj){return obj.name == selectedText});
			select.selectedIndex = itemObj.index;
		}
	});
	select.insert({after: sPulldown.element});
	select.hide();
	return sPulldown;
};
Ss = window.Ss || {};
Ss.share = {
	pulldowns: [],
	translatedToError: "",
	translatedFromError: "",
	translatedAddressError: "",
	
	closeEmailForm: function(e) {
		$(e).down('.network-form').reset();
		$(e).down('.message-area').hide();
		$(e).down('.email-form-container').hide();
		$(e).down('.network-errors').update();
		$(e).down('.social_network_list').show();
	},
	
	openEmailForm: function(e) {
		$(e).up('.social_network_list').hide();
		$(e).up('.share_interface_content').down('.email-form-container').show();
	},
	

	addPulldown: function(pulldown) {
		this.pulldowns.push(pulldown);
	},
	
	getPulldown: function(e){
		return this.pulldowns.find(function(p){ return e.descendantOf(p.getElement()); });
	},
	
	toggleNetworkEmail: function(e) {		
		this.openEmailForm(e);
		

		var pulldown = this.getPulldown(e);
		

		pulldown.reconfigure();
		

		pulldown.disableAutoClose();
		

		pulldown.subscribe( function(data) {
			if(data.state == Ss.Pulldown.STATES.collapsed) {
				pulldown.enableAutoClose();
				Ss.share.closeEmailForm(pulldown.getElement());
				pulldown.unsubscribe(arguments.callee);
			}
		});
	},
	
	sendNetworkEmail: function(t) {
		var container = $(t).up('.share_interface_content');
		if (this.validateAddresses($(t).up('form'))) {
			$(t).up('form').request({
				onFailure: function(){ 
					alert('Sorry, your message was not sent.');
				}
			});
			container.down('.email-form-container').hide();
			container.down('.message-area').show();
		}
	},
	
	validateAddresses: function(form) {
		var addressList = new Array();
		var errors      = new Array();
		var fromAddress = form.getInputs('text', 'from')[0].getValue();
	
		if (!fromAddress) {
			errors.push(this.translatedFromError);
		}
	
		var toAddresses = form.getInputs('text', 'to')[0].getValue().split(/\s*\,\s*/);
	
		if (toAddresses && !toAddresses[0]) {
			errors.push(this.translatedToError);
		}
	
		var allAddressesValid = true;
		var translatedAddressError = this.translatedAddressError;
		$A([[fromAddress], toAddresses]).flatten().each(function(address) {
			if (!address.match(/[\w.-]+\@[\w.-]+\.[\w]{2,5}/)) {
				allAddressesValid = false;
				errors.push( translatedAddressError + " '" + address + "'");
			}
		});
	
		if (!allAddressesValid) { 
			var errorMessage = errors.shift();
			form.previous().update(errorMessage);
		}
		return allAddressesValid;
	},
	
	open: function(path) {
		window.open(path);
	},
	
	close: function(e) {
		this.getPulldown(e).collapse();
	}
};







//





String.prototype.parseColor = function() {
  var color = '#';
  if (this.slice(0,4) == 'rgb(') {
    var cols = this.slice(4,this.length-1).split(',');
    var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
  } else {
    if (this.slice(0,1) == '#') {
      if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
      if (this.length==7) color = this.toLowerCase();
    }
  }
  return (color.length==7 ? color : (arguments[0] || this));
};

/*--------------------------------------------------------------------------*/

Element.collectTextNodes = function(element) {
  return $A($(element).childNodes).collect( function(node) {
    return (node.nodeType==3 ? node.nodeValue :
      (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
  }).flatten().join('');
};

Element.collectTextNodesIgnoreClass = function(element, className) {
  return $A($(element).childNodes).collect( function(node) {
    return (node.nodeType==3 ? node.nodeValue :
      ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
        Element.collectTextNodesIgnoreClass(node, className) : ''));
  }).flatten().join('');
};

Element.setContentZoom = function(element, percent) {
  element = $(element);
  element.setStyle({fontSize: (percent/100) + 'em'});
  if (Prototype.Browser.WebKit) window.scrollBy(0,0);
  return element;
};

Element.getInlineOpacity = function(element){
  return $(element).style.opacity || '';
};

Element.forceRerendering = function(element) {
  try {
    element = $(element);
    var n = document.createTextNode(' ');
    element.appendChild(n);
    element.removeChild(n);
  } catch(e) { }
};

/*--------------------------------------------------------------------------*/

var Effect = {
  _elementDoesNotExistError: {
    name: 'ElementDoesNotExistError',
    message: 'The specified DOM element does not exist, but is required for this effect to operate'
  },
  Transitions: {
    linear: Prototype.K,
    sinoidal: function(pos) {
      return (-Math.cos(pos*Math.PI)/2) + .5;
    },
    reverse: function(pos) {
      return 1-pos;
    },
    flicker: function(pos) {
      var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4;
      return pos > 1 ? 1 : pos;
    },
    wobble: function(pos) {
      return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5;
    },
    pulse: function(pos, pulses) {
      return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5;
    },
    spring: function(pos) {
      return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
    },
    none: function(pos) {
      return 0;
    },
    full: function(pos) {
      return 1;
    }
  },
  DefaultOptions: {
    duration:   1.0,   // seconds
    fps:        100,   // 100= assume 66fps max.
    sync:       false, // true for combining
    from:       0.0,
    to:         1.0,
    delay:      0.0,
    queue:      'parallel'
  },
  tagifyText: function(element) {
    var tagifyStyle = 'position:relative';
    if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';

    element = $(element);
    $A(element.childNodes).each( function(child) {
      if (child.nodeType==3) {
        child.nodeValue.toArray().each( function(character) {
          element.insertBefore(
            new Element('span', {style: tagifyStyle}).update(
              character == ' ' ? String.fromCharCode(160) : character),
              child);
        });
        Element.remove(child);
      }
    });
  },
  multiple: function(element, effect) {
    var elements;
    if (((typeof element == 'object') ||
        Object.isFunction(element)) &&
       (element.length))
      elements = element;
    else
      elements = $(element).childNodes;

    var options = Object.extend({
      speed: 0.1,
      delay: 0.0
    }, arguments[2] || { });
    var masterDelay = options.delay;

    $A(elements).each( function(element, index) {
      new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
    });
  },
  PAIRS: {
    'slide':  ['SlideDown','SlideUp'],
    'blind':  ['BlindDown','BlindUp'],
    'appear': ['Appear','Fade']
  },
  toggle: function(element, effect) {
    element = $(element);
    effect = (effect || 'appear').toLowerCase();
    var options = Object.extend({
      queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
    }, arguments[2] || { });
    Effect[element.visible() ?
      Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
  }
};

Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;

/* ------------- core effects ------------- */

Effect.ScopedQueue = Class.create(Enumerable, {
  initialize: function() {
    this.effects  = [];
    this.interval = null;
  },
  _each: function(iterator) {
    this.effects._each(iterator);
  },
  add: function(effect) {
    var timestamp = new Date().getTime();

    var position = Object.isString(effect.options.queue) ?
      effect.options.queue : effect.options.queue.position;

    switch(position) {
      case 'front':

        this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
            e.startOn  += effect.finishOn;
            e.finishOn += effect.finishOn;
          });
        break;
      case 'with-last':
        timestamp = this.effects.pluck('startOn').max() || timestamp;
        break;
      case 'end':

        timestamp = this.effects.pluck('finishOn').max() || timestamp;
        break;
    }

    effect.startOn  += timestamp;
    effect.finishOn += timestamp;

    if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
      this.effects.push(effect);

    if (!this.interval)
      this.interval = setInterval(this.loop.bind(this), 15);
  },
  remove: function(effect) {
    this.effects = this.effects.reject(function(e) { return e==effect });
    if (this.effects.length == 0) {
      clearInterval(this.interval);
      this.interval = null;
    }
  },
  loop: function() {
    var timePos = new Date().getTime();
    for(var i=0, len=this.effects.length;i<len;i++)
      this.effects[i] && this.effects[i].loop(timePos);
  }
});

Effect.Queues = {
  instances: $H(),
  get: function(queueName) {
    if (!Object.isString(queueName)) return queueName;

    return this.instances.get(queueName) ||
      this.instances.set(queueName, new Effect.ScopedQueue());
  }
};
Effect.Queue = Effect.Queues.get('global');

Effect.Base = Class.create({
  position: null,
  start: function(options) {
    function codeForEvent(options,eventName){
      return (
        (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
        (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
      );
    }
    if (options && options.transition === false) options.transition = Effect.Transitions.linear;
    this.options      = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
    this.currentFrame = 0;
    this.state        = 'idle';
    this.startOn      = this.options.delay*1000;
    this.finishOn     = this.startOn+(this.options.duration*1000);
    this.fromToDelta  = this.options.to-this.options.from;
    this.totalTime    = this.finishOn-this.startOn;
    this.totalFrames  = this.options.fps*this.options.duration;

    this.render = (function() {
      function dispatch(effect, eventName) {
        if (effect.options[eventName + 'Internal'])
          effect.options[eventName + 'Internal'](effect);
        if (effect.options[eventName])
          effect.options[eventName](effect);
      }

      return function(pos) {
        if (this.state === "idle") {
          this.state = "running";
          dispatch(this, 'beforeSetup');
          if (this.setup) this.setup();
          dispatch(this, 'afterSetup');
        }
        if (this.state === "running") {
          pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from;
          this.position = pos;
          dispatch(this, 'beforeUpdate');
          if (this.update) this.update(pos);
          dispatch(this, 'afterUpdate');
        }
      };
    })();

    this.event('beforeStart');
    if (!this.options.sync)
      Effect.Queues.get(Object.isString(this.options.queue) ?
        'global' : this.options.queue.scope).add(this);
  },
  loop: function(timePos) {
    if (timePos >= this.startOn) {
      if (timePos >= this.finishOn) {
        this.render(1.0);
        this.cancel();
        this.event('beforeFinish');
        if (this.finish) this.finish();
        this.event('afterFinish');
        return;
      }
      var pos   = (timePos - this.startOn) / this.totalTime,
          frame = (pos * this.totalFrames).round();
      if (frame > this.currentFrame) {
        this.render(pos);
        this.currentFrame = frame;
      }
    }
  },
  cancel: function() {
    if (!this.options.sync)
      Effect.Queues.get(Object.isString(this.options.queue) ?
        'global' : this.options.queue.scope).remove(this);
    this.state = 'finished';
  },
  event: function(eventName) {
    if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
    if (this.options[eventName]) this.options[eventName](this);
  },
  inspect: function() {
    var data = $H();
    for(property in this)
      if (!Object.isFunction(this[property])) data.set(property, this[property]);
    return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
  }
});

Effect.Parallel = Class.create(Effect.Base, {
  initialize: function(effects) {
    this.effects = effects || [];
    this.start(arguments[1]);
  },
  update: function(position) {
    this.effects.invoke('render', position);
  },
  finish: function(position) {
    this.effects.each( function(effect) {
      effect.render(1.0);
      effect.cancel();
      effect.event('beforeFinish');
      if (effect.finish) effect.finish(position);
      effect.event('afterFinish');
    });
  }
});

Effect.Tween = Class.create(Effect.Base, {
  initialize: function(object, from, to) {
    object = Object.isString(object) ? $(object) : object;
    var args = $A(arguments), method = args.last(),
      options = args.length == 5 ? args[3] : null;
    this.method = Object.isFunction(method) ? method.bind(object) :
      Object.isFunction(object[method]) ? object[method].bind(object) :
      function(value) { object[method] = value };
    this.start(Object.extend({ from: from, to: to }, options || { }));
  },
  update: function(position) {
    this.method(position);
  }
});

Effect.Event = Class.create(Effect.Base, {
  initialize: function() {
    this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
  },
  update: Prototype.emptyFunction
});

Effect.Opacity = Class.create(Effect.Base, {
  initialize: function(element) {
    this.element = $(element);
    if (!this.element) throw(Effect._elementDoesNotExistError);

    if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
      this.element.setStyle({zoom: 1});
    var options = Object.extend({
      from: this.element.getOpacity() || 0.0,
      to:   1.0
    }, arguments[1] || { });
    this.start(options);
  },
  update: function(position) {
    this.element.setOpacity(position);
  }
});

Effect.Move = Class.create(Effect.Base, {
  initialize: function(element) {
    this.element = $(element);
    if (!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({
      x:    0,
      y:    0,
      mode: 'relative'
    }, arguments[1] || { });
    this.start(options);
  },
  setup: function() {
    this.element.makePositioned();
    this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
    this.originalTop  = parseFloat(this.element.getStyle('top')  || '0');
    if (this.options.mode == 'absolute') {
      this.options.x = this.options.x - this.originalLeft;
      this.options.y = this.options.y - this.originalTop;
    }
  },
  update: function(position) {
    this.element.setStyle({
      left: (this.options.x  * position + this.originalLeft).round() + 'px',
      top:  (this.options.y  * position + this.originalTop).round()  + 'px'
    });
  }
});


Effect.MoveBy = function(element, toTop, toLeft) {
  return new Effect.Move(element,
    Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
};

Effect.Scale = Class.create(Effect.Base, {
  initialize: function(element, percent) {
    this.element = $(element);
    if (!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({
      scaleX: true,
      scaleY: true,
      scaleContent: true,
      scaleFromCenter: false,
      scaleMode: 'box',        // 'box' or 'contents' or { } with provided values
      scaleFrom: 100.0,
      scaleTo:   percent
    }, arguments[2] || { });
    this.start(options);
  },
  setup: function() {
    this.restoreAfterFinish = this.options.restoreAfterFinish || false;
    this.elementPositioning = this.element.getStyle('position');

    this.originalStyle = { };
    ['top','left','width','height','fontSize'].each( function(k) {
      this.originalStyle[k] = this.element.style[k];
    }.bind(this));

    this.originalTop  = this.element.offsetTop;
    this.originalLeft = this.element.offsetLeft;

    var fontSize = this.element.getStyle('font-size') || '100%';
    ['em','px','%','pt'].each( function(fontSizeType) {
      if (fontSize.indexOf(fontSizeType)>0) {
        this.fontSize     = parseFloat(fontSize);
        this.fontSizeType = fontSizeType;
      }
    }.bind(this));

    this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;

    this.dims = null;
    if (this.options.scaleMode=='box')
      this.dims = [this.element.offsetHeight, this.element.offsetWidth];
    if (/^content/.test(this.options.scaleMode))
      this.dims = [this.element.scrollHeight, this.element.scrollWidth];
    if (!this.dims)
      this.dims = [this.options.scaleMode.originalHeight,
                   this.options.scaleMode.originalWidth];
  },
  update: function(position) {
    var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
    if (this.options.scaleContent && this.fontSize)
      this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
  },
  finish: function(position) {
    if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
  },
  setDimensions: function(height, width) {
    var d = { };
    if (this.options.scaleX) d.width = width.round() + 'px';
    if (this.options.scaleY) d.height = height.round() + 'px';
    if (this.options.scaleFromCenter) {
      var topd  = (height - this.dims[0])/2;
      var leftd = (width  - this.dims[1])/2;
      if (this.elementPositioning == 'absolute') {
        if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
        if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
      } else {
        if (this.options.scaleY) d.top = -topd + 'px';
        if (this.options.scaleX) d.left = -leftd + 'px';
      }
    }
    this.element.setStyle(d);
  }
});

Effect.Highlight = Class.create(Effect.Base, {
  initialize: function(element) {
    this.element = $(element);
    if (!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
    this.start(options);
  },
  setup: function() {

    if (this.element.getStyle('display')=='none') { this.cancel(); return; }

    this.oldStyle = { };
    if (!this.options.keepBackgroundImage) {
      this.oldStyle.backgroundImage = this.element.getStyle('background-image');
      this.element.setStyle({backgroundImage: 'none'});
    }
    if (!this.options.endcolor)
      this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
    if (!this.options.restorecolor)
      this.options.restorecolor = this.element.getStyle('background-color');

    this._base  = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
    this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
  },
  update: function(position) {
    this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
      return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
  },
  finish: function() {
    this.element.setStyle(Object.extend(this.oldStyle, {
      backgroundColor: this.options.restorecolor
    }));
  }
});

Effect.ScrollTo = function(element) {
  var options = arguments[1] || { },
  scrollOffsets = document.viewport.getScrollOffsets(),
  elementOffsets = $(element).cumulativeOffset();

  if (options.offset) elementOffsets[1] += options.offset;

  return new Effect.Tween(null,
    scrollOffsets.top,
    elementOffsets[1],
    options,
    function(p){ scrollTo(scrollOffsets.left, p.round()); }
  );
};

/* ------------- combination effects ------------- */

Effect.Fade = function(element) {
  element = $(element);
  var oldOpacity = element.getInlineOpacity();
  var options = Object.extend({
    from: element.getOpacity() || 1.0,
    to:   0.0,
    afterFinishInternal: function(effect) {
      if (effect.options.to!=0) return;
      effect.element.hide().setStyle({opacity: oldOpacity});
    }
  }, arguments[1] || { });
  return new Effect.Opacity(element,options);
};

Effect.Appear = function(element) {
  element = $(element);
  var options = Object.extend({
  from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
  to:   1.0,

  afterFinishInternal: function(effect) {
    effect.element.forceRerendering();
  },
  beforeSetup: function(effect) {
    effect.element.setOpacity(effect.options.from).show();
  }}, arguments[1] || { });
  return new Effect.Opacity(element,options);
};

Effect.Puff = function(element) {
  element = $(element);
  var oldStyle = {
    opacity: element.getInlineOpacity(),
    position: element.getStyle('position'),
    top:  element.style.top,
    left: element.style.left,
    width: element.style.width,
    height: element.style.height
  };
  return new Effect.Parallel(
   [ new Effect.Scale(element, 200,
      { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
     new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
     Object.extend({ duration: 1.0,
      beforeSetupInternal: function(effect) {
        Position.absolutize(effect.effects[0].element);
      },
      afterFinishInternal: function(effect) {
         effect.effects[0].element.hide().setStyle(oldStyle); }
     }, arguments[1] || { })
   );
};

Effect.BlindUp = function(element) {
  element = $(element);
  element.makeClipping();
  return new Effect.Scale(element, 0,
    Object.extend({ scaleContent: false,
      scaleX: false,
      restoreAfterFinish: true,
      afterFinishInternal: function(effect) {
        effect.element.hide().undoClipping();
      }
    }, arguments[1] || { })
  );
};

Effect.BlindDown = function(element) {
  element = $(element);
  var elementDimensions = element.getDimensions();
  return new Effect.Scale(element, 100, Object.extend({
    scaleContent: false,
    scaleX: false,
    scaleFrom: 0,
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
    restoreAfterFinish: true,
    afterSetup: function(effect) {
      effect.element.makeClipping().setStyle({height: '0px'}).show();
    },
    afterFinishInternal: function(effect) {
      effect.element.undoClipping();
    }
  }, arguments[1] || { }));
};

Effect.SwitchOff = function(element) {
  element = $(element);
  var oldOpacity = element.getInlineOpacity();
  return new Effect.Appear(element, Object.extend({
    duration: 0.4,
    from: 0,
    transition: Effect.Transitions.flicker,
    afterFinishInternal: function(effect) {
      new Effect.Scale(effect.element, 1, {
        duration: 0.3, scaleFromCenter: true,
        scaleX: false, scaleContent: false, restoreAfterFinish: true,
        beforeSetup: function(effect) {
          effect.element.makePositioned().makeClipping();
        },
        afterFinishInternal: function(effect) {
          effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
        }
      });
    }
  }, arguments[1] || { }));
};

Effect.DropOut = function(element) {
  element = $(element);
  var oldStyle = {
    top: element.getStyle('top'),
    left: element.getStyle('left'),
    opacity: element.getInlineOpacity() };
  return new Effect.Parallel(
    [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
      new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
    Object.extend(
      { duration: 0.5,
        beforeSetup: function(effect) {
          effect.effects[0].element.makePositioned();
        },
        afterFinishInternal: function(effect) {
          effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
        }
      }, arguments[1] || { }));
};

Effect.Shake = function(element) {
  element = $(element);
  var options = Object.extend({
    distance: 20,
    duration: 0.5
  }, arguments[1] || {});
  var distance = parseFloat(options.distance);
  var split = parseFloat(options.duration) / 10.0;
  var oldStyle = {
    top: element.getStyle('top'),
    left: element.getStyle('left') };
    return new Effect.Move(element,
      { x:  distance, y: 0, duration: split, afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x:  distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x:  distance*2, y: 0, duration: split*2,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
        effect.element.undoPositioned().setStyle(oldStyle);
  }}); }}); }}); }}); }}); }});
};

Effect.SlideDown = function(element) {
  element = $(element).cleanWhitespace();

  var oldInnerBottom = element.down().getStyle('bottom');
  var elementDimensions = element.getDimensions();
  return new Effect.Scale(element, 100, Object.extend({
    scaleContent: false,
    scaleX: false,
    scaleFrom: window.opera ? 0 : 1,
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
    restoreAfterFinish: true,
    afterSetup: function(effect) {
      effect.element.makePositioned();
      effect.element.down().makePositioned();
      if (window.opera) effect.element.setStyle({top: ''});
      effect.element.makeClipping().setStyle({height: '0px'}).show();
    },
    afterUpdateInternal: function(effect) {
      effect.element.down().setStyle({bottom:
        (effect.dims[0] - effect.element.clientHeight) + 'px' });
    },
    afterFinishInternal: function(effect) {
      effect.element.undoClipping().undoPositioned();
      effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
    }, arguments[1] || { })
  );
};

Effect.SlideUp = function(element) {
  element = $(element).cleanWhitespace();
  var oldInnerBottom = element.down().getStyle('bottom');
  var elementDimensions = element.getDimensions();
  return new Effect.Scale(element, window.opera ? 0 : 1,
   Object.extend({ scaleContent: false,
    scaleX: false,
    scaleMode: 'box',
    scaleFrom: 100,
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
    restoreAfterFinish: true,
    afterSetup: function(effect) {
      effect.element.makePositioned();
      effect.element.down().makePositioned();
      if (window.opera) effect.element.setStyle({top: ''});
      effect.element.makeClipping().show();
    },
    afterUpdateInternal: function(effect) {
      effect.element.down().setStyle({bottom:
        (effect.dims[0] - effect.element.clientHeight) + 'px' });
    },
    afterFinishInternal: function(effect) {
      effect.element.hide().undoClipping().undoPositioned();
      effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
    }
   }, arguments[1] || { })
  );
};


Effect.Squish = function(element) {
  return new Effect.Scale(element, window.opera ? 1 : 0, {
    restoreAfterFinish: true,
    beforeSetup: function(effect) {
      effect.element.makeClipping();
    },
    afterFinishInternal: function(effect) {
      effect.element.hide().undoClipping();
    }
  });
};

Effect.Grow = function(element) {
  element = $(element);
  var options = Object.extend({
    direction: 'center',
    moveTransition: Effect.Transitions.sinoidal,
    scaleTransition: Effect.Transitions.sinoidal,
    opacityTransition: Effect.Transitions.full
  }, arguments[1] || { });
  var oldStyle = {
    top: element.style.top,
    left: element.style.left,
    height: element.style.height,
    width: element.style.width,
    opacity: element.getInlineOpacity() };

  var dims = element.getDimensions();
  var initialMoveX, initialMoveY;
  var moveX, moveY;

  switch (options.direction) {
    case 'top-left':
      initialMoveX = initialMoveY = moveX = moveY = 0;
      break;
    case 'top-right':
      initialMoveX = dims.width;
      initialMoveY = moveY = 0;
      moveX = -dims.width;
      break;
    case 'bottom-left':
      initialMoveX = moveX = 0;
      initialMoveY = dims.height;
      moveY = -dims.height;
      break;
    case 'bottom-right':
      initialMoveX = dims.width;
      initialMoveY = dims.height;
      moveX = -dims.width;
      moveY = -dims.height;
      break;
    case 'center':
      initialMoveX = dims.width / 2;
      initialMoveY = dims.height / 2;
      moveX = -dims.width / 2;
      moveY = -dims.height / 2;
      break;
  }

  return new Effect.Move(element, {
    x: initialMoveX,
    y: initialMoveY,
    duration: 0.01,
    beforeSetup: function(effect) {
      effect.element.hide().makeClipping().makePositioned();
    },
    afterFinishInternal: function(effect) {
      new Effect.Parallel(
        [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
          new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
          new Effect.Scale(effect.element, 100, {
            scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
            sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
        ], Object.extend({
             beforeSetup: function(effect) {
               effect.effects[0].element.setStyle({height: '0px'}).show();
             },
             afterFinishInternal: function(effect) {
               effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
             }
           }, options)
      );
    }
  });
};

Effect.Shrink = function(element) {
  element = $(element);
  var options = Object.extend({
    direction: 'center',
    moveTransition: Effect.Transitions.sinoidal,
    scaleTransition: Effect.Transitions.sinoidal,
    opacityTransition: Effect.Transitions.none
  }, arguments[1] || { });
  var oldStyle = {
    top: element.style.top,
    left: element.style.left,
    height: element.style.height,
    width: element.style.width,
    opacity: element.getInlineOpacity() };

  var dims = element.getDimensions();
  var moveX, moveY;

  switch (options.direction) {
    case 'top-left':
      moveX = moveY = 0;
      break;
    case 'top-right':
      moveX = dims.width;
      moveY = 0;
      break;
    case 'bottom-left':
      moveX = 0;
      moveY = dims.height;
      break;
    case 'bottom-right':
      moveX = dims.width;
      moveY = dims.height;
      break;
    case 'center':
      moveX = dims.width / 2;
      moveY = dims.height / 2;
      break;
  }

  return new Effect.Parallel(
    [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
      new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
      new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
    ], Object.extend({
         beforeStartInternal: function(effect) {
           effect.effects[0].element.makePositioned().makeClipping();
         },
         afterFinishInternal: function(effect) {
           effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
       }, options)
  );
};

Effect.Pulsate = function(element) {
  element = $(element);
  var options    = arguments[1] || { },
    oldOpacity = element.getInlineOpacity(),
    transition = options.transition || Effect.Transitions.linear,
    reverser   = function(pos){
      return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5);
    };

  return new Effect.Opacity(element,
    Object.extend(Object.extend({  duration: 2.0, from: 0,
      afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
    }, options), {transition: reverser}));
};

Effect.Fold = function(element) {
  element = $(element);
  var oldStyle = {
    top: element.style.top,
    left: element.style.left,
    width: element.style.width,
    height: element.style.height };
  element.makeClipping();
  return new Effect.Scale(element, 5, Object.extend({
    scaleContent: false,
    scaleX: false,
    afterFinishInternal: function(effect) {
    new Effect.Scale(element, 1, {
      scaleContent: false,
      scaleY: false,
      afterFinishInternal: function(effect) {
        effect.element.hide().undoClipping().setStyle(oldStyle);
      } });
  }}, arguments[1] || { }));
};

Effect.Morph = Class.create(Effect.Base, {
  initialize: function(element) {
    this.element = $(element);
    if (!this.element) throw(Effect._elementDoesNotExistError);
    var options = Object.extend({
      style: { }
    }, arguments[1] || { });

    if (!Object.isString(options.style)) this.style = $H(options.style);
    else {
      if (options.style.include(':'))
        this.style = options.style.parseStyle();
      else {
        this.element.addClassName(options.style);
        this.style = $H(this.element.getStyles());
        this.element.removeClassName(options.style);
        var css = this.element.getStyles();
        this.style = this.style.reject(function(style) {
          return style.value == css[style.key];
        });
        options.afterFinishInternal = function(effect) {
          effect.element.addClassName(effect.options.style);
          effect.transforms.each(function(transform) {
            effect.element.style[transform.style] = '';
          });
        };
      }
    }
    this.start(options);
  },

  setup: function(){
    function parseColor(color){
      if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
      color = color.parseColor();
      return $R(0,2).map(function(i){
        return parseInt( color.slice(i*2+1,i*2+3), 16 );
      });
    }
    this.transforms = this.style.map(function(pair){
      var property = pair[0], value = pair[1], unit = null;

      if (value.parseColor('#zzzzzz') != '#zzzzzz') {
        value = value.parseColor();
        unit  = 'color';
      } else if (property == 'opacity') {
        value = parseFloat(value);
        if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
          this.element.setStyle({zoom: 1});
      } else if (Element.CSS_LENGTH.test(value)) {
          var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
          value = parseFloat(components[1]);
          unit = (components.length == 3) ? components[2] : null;
      }

      var originalValue = this.element.getStyle(property);
      return {
        style: property.camelize(),
        originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
        targetValue: unit=='color' ? parseColor(value) : value,
        unit: unit
      };
    }.bind(this)).reject(function(transform){
      return (
        (transform.originalValue == transform.targetValue) ||
        (
          transform.unit != 'color' &&
          (isNaN(transform.originalValue) || isNaN(transform.targetValue))
        )
      );
    });
  },
  update: function(position) {
    var style = { }, transform, i = this.transforms.length;
    while(i--)
      style[(transform = this.transforms[i]).style] =
        transform.unit=='color' ? '#'+
          (Math.round(transform.originalValue[0]+
            (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
          (Math.round(transform.originalValue[1]+
            (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
          (Math.round(transform.originalValue[2]+
            (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
        (transform.originalValue +
          (transform.targetValue - transform.originalValue) * position).toFixed(3) +
            (transform.unit === null ? '' : transform.unit);
    this.element.setStyle(style, true);
  }
});

Effect.Transform = Class.create({
  initialize: function(tracks){
    this.tracks  = [];
    this.options = arguments[1] || { };
    this.addTracks(tracks);
  },
  addTracks: function(tracks){
    tracks.each(function(track){
      track = $H(track);
      var data = track.values().first();
      this.tracks.push($H({
        ids:     track.keys().first(),
        effect:  Effect.Morph,
        options: { style: data }
      }));
    }.bind(this));
    return this;
  },
  play: function(){
    return new Effect.Parallel(
      this.tracks.map(function(track){
        var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
        var elements = [$(ids) || $$(ids)].flatten();
        return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
      }).flatten(),
      this.options
    );
  }
});

Element.CSS_PROPERTIES = $w(
  'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
  'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
  'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
  'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
  'fontSize fontWeight height left letterSpacing lineHeight ' +
  'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
  'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
  'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
  'right textIndent top width wordSpacing zIndex');

Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;

String.__parseStyleElement = document.createElement('div');
String.prototype.parseStyle = function(){
  var style, styleRules = $H();
  if (Prototype.Browser.WebKit)
    style = new Element('div',{style:this}).style;
  else {
    String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
    style = String.__parseStyleElement.childNodes[0].style;
  }

  Element.CSS_PROPERTIES.each(function(property){
    if (style[property]) styleRules.set(property, style[property]);
  });

  if (Prototype.Browser.IE && this.include('opacity'))
    styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);

  return styleRules;
};

if (document.defaultView && document.defaultView.getComputedStyle) {
  Element.getStyles = function(element) {
    var css = document.defaultView.getComputedStyle($(element), null);
    return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
      styles[property] = css[property];
      return styles;
    });
  };
} else {
  Element.getStyles = function(element) {
    element = $(element);
    var css = element.currentStyle, styles;
    styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
      results[property] = css[property];
      return results;
    });
    if (!styles.opacity) styles.opacity = element.getOpacity();
    return styles;
  };
}

Effect.Methods = {
  morph: function(element, style) {
    element = $(element);
    new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
    return element;
  },
  visualEffect: function(element, effect, options) {
    element = $(element);
    var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
    new Effect[klass](element, options);
    return element;
  },
  highlight: function(element, options) {
    element = $(element);
    new Effect.Highlight(element, options);
    return element;
  }
};

$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
  'pulsate shake puff squish switchOff dropOut').each(
  function(effect) {
    Effect.Methods[effect] = function(element, options){
      element = $(element);
      Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
      return element;
    };
  }
);

$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
  function(f) { Effect.Methods[f] = Element[f]; }
);

Element.addMethods(Effect.Methods);




Ajax.currentRequests = {};

Ajax.Responders.register({
	onCreate: function(request) {
		if (request.options.onlyLatestOfClass && Ajax.currentRequests[request.options.onlyLatestOfClass]) {

			try { Ajax.currentRequests[request.options.onlyLatestOfClass].transport.abort(); } catch(e) {}
		}

		Ajax.currentRequests[request.options.onlyLatestOfClass] = request;
	},
	onComplete: function(request) {
		if (request.options.onlyLatestOfClass) {

			Ajax.currentRequests[request.options.onlyLatestOfClass] = null;
		}
	}
});

var SavedSearchWidget = Class.create(
{
	initialize: function(params) {
		this.container = params['saved_search_container'];
		this.container.move_direction = 'left';
		this.table = this.container.down('table#saved-search-table');
		this.search_container = params['search_container'];
		this.keyword_search_container = params['keyword_search_container'];
		this.container.style.left = (this.keyword_search_container.getWidth() - this.container.getWidth() || -26) + 'px';
		this.container.left_orig = parseInt(this.container.getStyle('left'));
		this.search_container.style.height = (this.container.getHeight() || 20) + 'px';

		this.button           = params['button'];
		this.button_in        = params['button_in'];
		this.button_out       = params['button_out'];
		this.button.innerHTML = this.button_out;
		this.button.innerHTML = this.button_in;
		this.button.observe('click', this.slide.bind(this));
		this.close = this.container.down('span#saved-search-close');
		this.close.observe('click', this.slide.bind(this));

		this.text_view_results = params['text_view_results'];
		this.text_delete = params['text_delete'];
		this.landing_page = params['landing_page'];

		this.notify_table = this.container.down('#notify_table');
		this.notify_div = this.container.down('#notify_div');
		this.notify_on = this.container.down('input#notify-on');
		this.notify_on.observe('change', this.toggleNotify.bind(this));
		this.notify_on.observe('click', this.toggleNotify.bind(this));
		this.notify_off = this.container.down('input#notify-off');
		this.notify_off.checked = true;
		this.notify_off.observe('change', this.toggleNotify.bind(this));
		this.notify_off.observe('click', this.toggleNotify.bind(this));
		this.notify_freq = this.container.down('select#frequency');

		this.save_search = this.container.down('span#save-search');
		this.save_search.observe('click', this.saveSearch.bind(this));
		this.saving_search = this.container.down('span#saving-search');
		this.saving_search.hide();
		this.saving_search_done = this.container.down('span#saving-search-done');
		this.saving_search_done.hide();
		this.saving_search_error = this.container.down('span#saving-search-error');
		this.saving_search_error.hide();
		this.updating_searches = this.container.down('div#updating-searches');
		this.updating_searches.hide();

		this.keyword_form = $('keyword_form');
		this.searchtitle = this.container.down('input#searchtitle');
		this.search_list = this.container.down('div#search-list');
		this.empty_searches = this.container.down('div#empty-searches');


		var this_outer = this;
		this.searchtitle.observe('keypress', function(event) {
			if(event.keyCode == Event.KEY_RETURN) {
				this_outer.saveSearch();
				Event.stop(event);
			}
		});

		this.duration = 0.25;
		this.my_searches_init = true;



		if (Prototype.Browser.IE || Prototype.Browser.WebKit) Object.extend(String.prototype, {
			escapeHTML: function() {
				var self = arguments.callee;
				self.text.data = this;
				return self.div.innerHTML;
			},
			unescapeHTML: function() {
				var div = new Element('div');
				div.innerHTML = this.stripTags();
				return div.childNodes[0]
					? (div.childNodes.length > 1
					? $A(div.childNodes).inject('', function(memo, node) {
						return memo+node.nodeValue
					})
					: div.childNodes[0].nodeValue)
					: '';
			}
		});

		this.modeSaving = false;
		this.search_container.style.width = this.keyword_search_container.getWidth() + 'px';

		this.init_my_searches = true;
	},

	initMySearches: function() {
		if (this.init_my_searches) {
			this.getSearches();
			this.init_my_searches = false;
		}
	},

	growContainerHorizontal: function() {
		var sc_left = parseInt(this.search_container.getStyle('left'));
		var c_left  = parseInt(this.container.getStyle('left'));
		var ksc_width = parseInt(this.keyword_search_container.getWidth());
		var c_width = parseInt(this.container.getWidth());

		var this_outer = this;
		var effect = new Effect.Morph(this.search_container, {
			style:    'width: ' + (ksc_width + c_width) + 'px',
			duration: this_outer.duration
		});
	},

	shrinkContainerHorizontal: function() {
		var this_outer = this;
		var effect = new Effect.Morph(this.search_container, {
			style:    'width: ' + this.keyword_search_container.getWidth() + 'px',
			duration: this_outer.duration
		});
	},

	resizeContainerVertical: function() {
		this.search_container.style.height = parseInt(this.container.getStyle('top')) + this.table.getHeight() + 'px';
	},

	growContainerVertical: function() {
		this.search_container.style.height = this.keyword_search_container.getHeight() + 'px';
	},

	slide: function() {
		var min_left = this.container.left_orig;
		var delta    = this.container.getWidth() - 10;
		var max_left = min_left + delta;

		if (this.container.currentEffect) {
			this.container.currentEffect.cancel();
			this.search_list.setStyle({ overflow: 'hidden' });
		}
		var curr_left = parseInt(this.container.getStyle('left'));

		var move_x = 0;
		if (curr_left <= min_left || this.container.move_direction == 'left') {
			this.button.innerHTML = this.button_out;
			move_x = max_left - curr_left;
			this.container.move_direction = 'right';
			this.growContainerHorizontal();
		} else if (curr_left >= max_left || this.container.move_direction == 'right') {
			this.button.innerHTML = this.button_in;
			move_x = min_left - curr_left;
			this.container.move_direction = 'left';
			this.shrinkContainerHorizontal();
		}

		var this_outer = this;
		this.container.currentEffect =
			new Effect.Move(this.container, {
				x: move_x, y: 0, mode: 'relative', duration: this_outer.duration,
				beforeStart: function() { this_outer.search_list.setStyle({ overflow: 'hidden' }); },
				afterFinish: function() { this_outer.search_list.setStyle({ overflow: 'auto' }); }
			});
	},

	toggleNotify: function() {
		if (this.notify_on.checked) {
			this.notify_div.show();
			this.resizeContainerVertical();
		} else if (this.notify_off.checked) {
			this.notify_div.hide();
			this.resizeContainerVertical();
		}
	},

	saveSearch: function() {
		var criteria_json = Object.toJSON(this.keyword_form.serialize(true));

		if (this.modeSaving) {
			return;
		}
		this.modeSaving = true;

		this.growContainerVertical();


		var notify_freq = this.notify_on.checked
		                ? this.notify_freq.value
		                : null;

		var this_outer = this;
		var req = new Ajax.Request('/show_component.mhtml', {
			method: 'post',
			parameters: {
				component_path:        'saved_searches.mh',
				action:                'save',
				name:                  this.searchtitle.value,
				notify_freq:           notify_freq,
				search_criteria_json:  criteria_json,
				encoding:              'UTF-8'
			},
			onCreate: function() {
				this_outer.saving_search_done.hide();
				this_outer.saving_search_error.hide();
				this_outer.saving_search.show();
				this_outer.updating_searches.show();
			},
			onSuccess: function(response) {
				var json = response.responseJSON;

				if (json === null) {
					alert("json is null");
				} else if (json.result == 'FAIL') {
					this_outer.saving_search_error.innerHTML = json.content;
					this_outer.saving_search_error.show();
				} else {
					this_outer.searchtitle.value = '';
					this_outer.populateSearches(json.content);
					this_outer.fadeDone(this_outer.saving_search_done);
				}
			},
			onFailure: function() {
				this_outer.saving_search_error.update("Could not connect.");
				this_outer.saving_search_error.show();
			},
			onComplete: function() {
				this_outer.modeSaving = false;
				this_outer.saving_search.hide();
				this_outer.updating_searches.hide();
				this_outer.resizeContainerVertical();
			}
		});
	},

	fadeDone: function(span) {
		span.show();
		if (this.effect != null) {
			this.effect.cancel;
		}
		this.effect = new Effect.Fade(span, {
			duration: 3.0, from: 1, to: 0,
			afterFinish: function() { span.hide(); }
		});
	},

	getSearches: function() {
		var this_outer = this;

		var req = new Ajax.Request('/show_component.mhtml', {
			onlyLatestOfClass: 'SavedSearchWidget.getSearches', // Cancel old, unfinished requests
			method: 'post',
			parameters: {
				component_path: 'saved_searches.mh',
				action:         'list'
			},
			onCreate: function() {
				this_outer.empty_searches.hide();
				this_outer.updating_searches.show();
			},
			onSuccess: function(response) {
				var json = response.responseJSON;
				if (json === null || json.result == 'FAIL') {
					return;
				}

				this_outer.populateSearches(json.content);
			},
			onFailure: function() {
				alert("(= GET_SAVED_SEARCH_FAILED Get saved searches failed. =)");
			},
			onComplete: function() {
				this_outer.updating_searches.hide();
				this_outer.resizeContainerVertical();
			}
		});
	},

	populateSearches: function(content) {
		this.search_list.innerHTML = '';
		this.growContainerVertical();
		var searches = $H(content.searches);
		var sorted_searches = searches.values().sortBy(function(e) {
			return e.name.toLowerCase();
		});

		var this_outer = this;

		sorted_searches.each(function(item) {
			item = new Hash(item);
			var id         = item.get('id');
			var id_div     = 'saved-search-id' + id;
			var id_query   = 'saved-search-query-id' + id;
			var id_delete  = 'saved-search-delete-id' + id;
			var class_link = 'saved-search-text saved-search-link';
			var class_text = 'saved-search-text';
			var class_name = 'saved-search-name';
			var class_desc = 'saved-search-description';

			div_search = new Element('div', { id: id_div });
			var del = new Element('span', { href: '', 'class': class_link }).update(this_outer.text_delete);
			del.observe('click', this_outer.deleteSearch.bind(this_outer, id));

			[	new Element('div', { 'class': class_name }).update(item.get('name')),
				new Element('div', { 'class': class_desc }).update(item.get('description')), 
				new Element('a', { href: '' + this_outer.landing_page + item.get('query'), 'class': class_link }).update(this_outer.text_view_results),
				new Element('span', { 'class': class_text }).update(' | '),
				del,
				new Element('br'),
				new Element('br')
			].each(function(child) { div_search.appendChild(child); });

			this_outer.search_list.appendChild(div_search);
		});

		this.checkEmptySearches();
	},

	deleteSearch: function(id) {
		var div_search = this.search_list.down('div#saved-search-id' + id);
		this.growContainerVertical();
		div_search.hide();

		var this_outer = this;
		var req = new Ajax.Request('/show_component.mhtml', {
			method: 'post',
			parameters: {
				component_path: 'saved_searches.mh',
				action:         'delete',
				id:             id
			},
			onCreate: function() {
				this_outer.updating_searches.show();
			},
			onSuccess: function(response) {
				div_search.remove();
				this_outer.checkEmptySearches();
			},
			onFailure: function() {
				div_search.show();
			},
			onComplete: function() {
				this_outer.resizeContainerVertical();
				this_outer.updating_searches.hide();
			}
		});
	},

	checkEmptySearches: function() {

		if (this.search_list.childElements().length <= 0) {
			this.empty_searches.show();
		} else {
			this.empty_searches.hide();
		}
	}
});
/**
 * Keyword Search Box/Left Nav js
 */
function updateReleaseOptions() {
	if ($('model-released-checkbox').checked) {
		$('exclude-editorial-checkbox').checked = true;
		$('exclude-editorial-checkbox').disabled = true;
		$('exclude-editorial-text').style.color = "#808080";
		$('people-options').style.display = 'block';
	} else {
		$('exclude-editorial-checkbox').checked = false;
		$('exclude-editorial-checkbox').disabled = false;
		$('exclude-editorial-text').style.color = "#282828";
		$('exclude-editorial-container').style.backgroundColor = 'white';
		$('people-options').style.display = 'none';
	}
}
function toggleInputHighlight(e, color) {
	if (e.value && e.value != 'all') {
		e.style.backgroundColor = color || '#e4f1ff';
	} else {
		e.style.backgroundColor = 'white';
	}
}
function toggleCheckboxHighlight(input, containerId) {

	var container = document.getElementById(containerId);
	container = container || $(input).up('.checkbox-option-container');

	if (!container) {
			return;
	}
	
	if (input.checked && !input.disabled) {

		container.style.backgroundColor = '#d3e9ff';
	} else {
		container.style.backgroundColor = 'white';
	}
}

function clearSimilarPhotoCriteria() {
	$('similar-photo-id-input').value = '';
	$('similar-images-container').hide();
}

function togglePeopleOptions() {
	var peopleOptions = $('people-options');
	if ($('model-released-checkbox').checked) {
		peopleOptions.show();	
	} else { 
		peopleOptions.select('select').each( function(selectInput) {
			selectInput.value = '';
			toggleInputHighlight(selectInput);
		} );
		peopleOptions.hide();	
	}
}
var Ss = window.Ss || Ss;

Ss.PopupAnchor = Class.create({
	initialize: function(element, winName, winWidth, winHeight) {
		this.element = element;
		this.winName = winName;
		this.winWidth = winWidth || 800;
		this.winHeight = winHeight || 600;
		

		this.element.observe('click', this.click.bind(this));
	},
	click: function(evt) {
		

			Event.stop(evt);
			

			var winSpecs = this._winSpecs();
			

			var url = this.element.href;
			var name = this.name;
			var features = $H({
					
				height: 	winSpecs.height,
				width: 		winSpecs.width,
				top: 		winSpecs.getTop(),
				left: 		winSpecs.getLeft(),
				menubar: 	'no',
				resizable: 	'yes',
				scrollbars: 'yes'
				
			}).collect(function(feat){ return feat.key + '=' + feat.value; }).join(', ');
			

			var newWin = window.open(url, name, features);
			

			newWin.focus();
			
	},
	_winSpecs: function() {
		

			var cWin = {
				width: 		window.outerWidth,
				height: 	window.outerHeight,
				left: 		(window.screenLeft || window.screenX),
				top: 		(window.screenTop || window.screenY)
			};
			

			return {
				width: 		this.winWidth,
				height: 	this.winHeight,
				getLeft: 	function(){return (cWin.width > this.width ? (cWin.width - this.width)/2 + cWin.left : cWin.left);},
				getTop: 	function(){return (cWin.height > this.height ? (cWin.height - this.height)/2 + cWin.top : cWin.top);}
			};
			
	}
});



