/*
 * jQuery JavaScript Library v1.3.2
 * http://jquery.com/
 *
 * Copyright (c) 2009 John Resig
 * Dual licensed under the MIT and GPL licenses.
 * http://docs.jquery.com/License
 *
 * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
 * Revision: 6246
 */
(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F<J;F++){var G=M[F];if(G.selected){K=o(G).val();if(H){return K}L.push(K)}}return L}return(E.value||"").replace(/\r/g,"")}return g}if(typeof K==="number"){K+=""}return this.each(function(){if(this.nodeType!=1){return}if(o.isArray(K)&&/radio|checkbox/.test(this.type)){this.checked=(o.inArray(this.value,K)>=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G<E;G++){L.call(K(this[G],H),this.length>1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H<I;H++){if((G=arguments[H])!=null){for(var F in G){var K=J[F],L=G[F];if(J===L){continue}if(E&&L&&typeof L==="object"&&!L.nodeType){J[F]=o.extend(E,K||(L.length!=null?[]:{}),L)}else{if(L!==g){J[F]=L}}}}}return J};var b=/z-?index|font-?weight|opacity|zoom|line-?height/i,q=document.defaultView||{},s=Object.prototype.toString;o.extend({noConflict:function(E){l.$=p;if(E){l.jQuery=y}return o},isFunction:function(E){return s.call(E)==="[object Function]"},isArray:function(E){return s.call(E)==="[object Array]"},isXMLDoc:function(E){return E.nodeType===9&&E.documentElement.nodeName!=="HTML"||!!E.ownerDocument&&o.isXMLDoc(E.ownerDocument)},globalEval:function(G){if(G&&/\S/.test(G)){var F=document.getElementsByTagName("head")[0]||document.documentElement,E=document.createElement("script");E.type="text/javascript";if(o.support.scriptEval){E.appendChild(document.createTextNode(G))}else{E.text=G}F.insertBefore(E,F.firstChild);F.removeChild(E)}},nodeName:function(F,E){return F.nodeName&&F.nodeName.toUpperCase()==E.toUpperCase()},each:function(G,K,F){var E,H=0,I=G.length;if(F){if(I===g){for(E in G){if(K.apply(G[E],F)===false){break}}}else{for(;H<I;){if(K.apply(G[H++],F)===false){break}}}}else{if(I===g){for(E in G){if(K.call(G[E],E,G[E])===false){break}}}else{for(var J=G[0];H<I&&K.call(J,H,J)!==false;J=G[++H]){}}}return G},prop:function(H,I,G,F,E){if(o.isFunction(I)){I=I.call(H,F)}return typeof I==="number"&&G=="curCSS"&&!b.test(E)?I+"px":I},className:{add:function(E,F){o.each((F||"").split(/\s+/),function(G,H){if(E.nodeType==1&&!o.className.has(E.className,H)){E.className+=(E.className?" ":"")+H}})},remove:function(E,F){if(E.nodeType==1){E.className=F!==g?o.grep(E.className.split(/\s+/),function(G){return !o.className.has(F,G)}).join(" "):""}},has:function(F,E){return F&&o.inArray(E,(F.className||F).toString().split(/\s+/))>-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+"></"+T+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!O.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!O.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!O.indexOf("<td")||!O.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!O.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||!o.support.htmlSerialize&&[1,"div<div>","</div>"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/<tbody/i.test(S),N=!O.indexOf("<table")&&!R?L.firstChild&&L.firstChild.childNodes:Q[1]=="<table>"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E<F;E++){if(H[E]===G){return E}}return -1},merge:function(H,E){var F=0,G,I=H.length;if(!o.support.getAll){while((G=E[F++])!=null){if(G.nodeType!=8){H[I++]=G}}}else{while((G=E[F++])!=null){H[I++]=G}}return H},unique:function(K){var F=[],E={};try{for(var G=0,H=K.length;G<H;G++){var J=o.data(K[G]);if(!E[J]){E[J]=true;F.push(K[G])}}}catch(I){F=K}return F},grep:function(F,J,E){var G=[];for(var H=0,I=F.length;H<I;H++){if(!E!=!J(F[H],H)){G.push(F[H])}}return G},map:function(E,J){var F=[];for(var G=0,H=E.length;G<H;G++){var I=J(E[G],G);if(I!=null){F[F.length]=I}}return F.concat.apply([],F)}});var C=navigator.userAgent.toLowerCase();o.browser={version:(C.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[0,"0"])[1],safari:/webkit/.test(C),opera:/opera/.test(C),msie:/msie/.test(C)&&!/opera/.test(C),mozilla:/mozilla/.test(C)&&!/(compatible|webkit)/.test(C)};o.each({parent:function(E){return E.parentNode},parents:function(E){return o.dir(E,"parentNode")},next:function(E){return o.nth(E,2,"nextSibling")},prev:function(E){return o.nth(E,2,"previousSibling")},nextAll:function(E){return o.dir(E,"nextSibling")},prevAll:function(E){return o.dir(E,"previousSibling")},siblings:function(E){return o.sibling(E.parentNode.firstChild,E)},children:function(E){return o.sibling(E.firstChild)},contents:function(E){return o.nodeName(E,"iframe")?E.contentDocument||E.contentWindow.document:o.makeArray(E.childNodes)}},function(E,F){o.fn[E]=function(G){var H=o.map(this,F);if(G&&typeof G=="string"){H=o.multiFilter(G,H)}return this.pushStack(o.unique(H),E,G)}});o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(E,F){o.fn[E]=function(G){var J=[],L=o(G);for(var K=0,H=L.length;K<H;K++){var I=(K>0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}});
/*
 * Sizzle CSS Selector Engine - v0.9.3
 *  Copyright 2009, The Dojo Foundation
 *  Released under the MIT, BSD, and GPL Licenses.
 *  More information: http://sizzlejs.com/
 */
(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa<ab.length;aa++){if(ab[aa]===ab[aa-1]){ab.splice(aa--,1)}}}}}return ab};F.matches=function(T,U){return F(T,null,null,U)};F.find=function(aa,T,ab){var Z,X;if(!aa){return[]}for(var W=0,V=I.order.length;W<V;W++){var Y=I.order[W],X;if((X=I.match[Y].exec(aa))){var U=RegExp.leftContext;if(U.substr(U.length-1)!=="\\"){X[1]=(X[1]||"").replace(/\\/g,"");Z=I.find[Y](X,T,ab);if(Z!=null){aa=aa.replace(I.match[Y],"");break}}}}if(!Z){Z=T.getElementsByTagName("*")}return{set:Z,expr:aa}};F.filter=function(ad,ac,ag,W){var V=ad,ai=[],aa=ac,Y,T,Z=ac&&ac[0]&&Q(ac[0]);while(ad&&ac.length){for(var ab in I.filter){if((Y=I.match[ab].exec(ad))!=null){var U=I.filter[ab],ah,af;T=false;if(aa==ai){ai=[]}if(I.preFilter[ab]){Y=I.preFilter[ab](Y,aa,ag,ai,W,Z);if(!Y){T=ah=true}else{if(Y===true){continue}}}if(Y){for(var X=0;(af=aa[X])!=null;X++){if(af){ah=U(af,Y,X,aa);var ae=W^!!ah;if(ag&&ah!=null){if(ae){T=true}else{aa[X]=false}}else{if(ae){ai.push(af);T=true}}}}}if(ah!==g){if(!ag){aa=ai}ad=ad.replace(I.match[ab],"");if(!T){return[]}break}}}if(ad==V){if(T==null){throw"Syntax error, unrecognized expression: "+ad}else{break}}V=ad}return aa};var I=F.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(T){return T.getAttribute("href")}},relative:{"+":function(aa,T,Z){var X=typeof T==="string",ab=X&&!/\W/.test(T),Y=X&&!ab;if(ab&&!Z){T=T.toUpperCase()}for(var W=0,V=aa.length,U;W<V;W++){if((U=aa[W])){while((U=U.previousSibling)&&U.nodeType!==1){}aa[W]=Y||U&&U.nodeName===T?U||false:U===T}}if(Y){F.filter(T,aa,true)}},">":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){var W=Y.parentNode;Z[V]=W.nodeName===U?W:false}}}else{for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){Z[V]=X?Y.parentNode:Y.parentNode===U}}if(X){F.filter(U,Z,true)}}},"":function(W,U,Y){var V=L++,T=S;if(!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("parentNode",U,V,W,X,Y)},"~":function(W,U,Y){var V=L++,T=S;if(typeof U==="string"&&!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("previousSibling",U,V,W,X,Y)}},find:{ID:function(U,V,W){if(typeof V.getElementById!=="undefined"&&!W){var T=V.getElementById(U[1]);return T?[T]:[]}},NAME:function(V,Y,Z){if(typeof Y.getElementsByName!=="undefined"){var U=[],X=Y.getElementsByName(V[1]);for(var W=0,T=X.length;W<T;W++){if(X[W].getAttribute("name")===V[1]){U.push(X[W])}}return U.length===0?null:U}},TAG:function(T,U){return U.getElementsByTagName(T[1])}},preFilter:{CLASS:function(W,U,V,T,Z,aa){W=" "+W[1].replace(/\\/g,"")+" ";if(aa){return W}for(var X=0,Y;(Y=U[X])!=null;X++){if(Y){if(Z^(Y.className&&(" "+Y.className+" ").indexOf(W)>=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return U<T[3]-0},gt:function(V,U,T){return U>T[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W<T;W++){if(Y[W]===Z){return false}}return true}}}},CHILD:function(T,W){var Z=W[1],U=T;switch(Z){case"only":case"first":while(U=U.previousSibling){if(U.nodeType===1){return false}}if(Z=="first"){return true}U=T;case"last":while(U=U.nextSibling){if(U.nodeType===1){return false}}return true;case"nth":var V=W[2],ac=W[3];if(V==1&&ac==0){return true}var Y=W[0],ab=T.parentNode;if(ab&&(ab.sizcache!==Y||!T.nodeIndex)){var X=0;for(U=ab.firstChild;U;U=U.nextSibling){if(U.nodeType===1){U.nodeIndex=++X}}ab.sizcache=Y}var aa=T.nodeIndex-ac;if(V==0){return aa==0}else{return(aa%V==0&&aa/V>=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V<T;V++){U.push(X[V])}}else{for(var V=0;X[V];V++){U.push(X[V])}}}return U}}var G;if(document.documentElement.compareDocumentPosition){G=function(U,T){var V=U.compareDocumentPosition(T)&4?-1:U===T?0:1;if(V===0){hasDuplicate=true}return V}}else{if("sourceIndex" in document.documentElement){G=function(U,T){var V=U.sourceIndex-T.sourceIndex;if(V===0){hasDuplicate=true}return V}}else{if(document.createRange){G=function(W,U){var V=W.ownerDocument.createRange(),T=U.ownerDocument.createRange();V.selectNode(W);V.collapse(true);T.selectNode(U);T.collapse(true);var X=V.compareBoundaryPoints(Range.START_TO_END,T);if(X===0){hasDuplicate=true}return X}}}}(function(){var U=document.createElement("form"),V="script"+(new Date).getTime();U.innerHTML="<input name='"+V+"'/>";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="<a href='#'></a>";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="<p class='TEST'></p>";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="<div class='test e'></div><div class='test'></div>";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1&&!ac){T.sizcache=Y;T.sizset=W}if(T.nodeName===Z){X=T;break}T=T[U]}ad[W]=X}}}function S(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1){if(!ac){T.sizcache=Y;T.sizset=W}if(typeof Z!=="string"){if(T===Z){X=true;break}}else{if(F.filter(Z,[T]).length>0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z<U;Z++){F(T,V[Z],W)}return F.filter(X,W)};o.find=F;o.filter=F.filter;o.expr=F.selectors;o.expr[":"]=o.expr.filters;F.selectors.filters.hidden=function(T){return T.offsetWidth===0||T.offsetHeight===0};F.selectors.filters.visible=function(T){return T.offsetWidth>0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F<E.length){o.event.proxy(G,E[F++])}return this.click(o.event.proxy(G,function(H){this.lastToggle=(this.lastToggle||0)%F;H.preventDefault();return E[this.lastToggle++].apply(this,arguments)||false}))},hover:function(E,F){return this.mouseenter(E).mouseleave(F)},ready:function(E){B();if(o.isReady){E.call(document,o)}else{o.readyList.push(E)}return this},live:function(G,F){var E=o.event.proxy(F);E.guid+=this.selector+G;o(document).bind(i(G,this.selector),this.selector,E);return this},die:function(F,E){o(document).unbind(i(F,this.selector),E?{guid:E.guid+this.selector+F}:null);return this}});function c(H){var E=RegExp("(^|\\.)"+H.type+"(\\.|$)"),G=true,F=[];o.each(o.data(this,"events").live||[],function(I,J){if(E.test(J.type)){var K=o(H.target).closest(J.data)[0];if(K){F.push({elem:K,fn:J})}}});F.sort(function(J,I){return o.data(J.elem,"closest")-o.data(I.elem,"closest")});o.each(F,function(){if(this.fn.call(this.elem,H,this.fn.data)===false){return(G=false)}});return G}function i(F,E){return["live",F,E.replace(/\./g,"`").replace(/ /g,"|")].join(".")}o.extend({isReady:false,readyList:[],ready:function(){if(!o.isReady){o.isReady=true;if(o.readyList){o.each(o.readyList,function(){this.call(document,o)});o.readyList=null}o(document).triggerHandler("ready")}}});var x=false;function B(){if(x){return}x=true;if(document.addEventListener){document.addEventListener("DOMContentLoaded",function(){document.removeEventListener("DOMContentLoaded",arguments.callee,false);o.ready()},false)}else{if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);o.ready()}});if(document.documentElement.doScroll&&l==l.top){(function(){if(o.isReady){return}try{document.documentElement.doScroll("left")}catch(E){setTimeout(arguments.callee,0);return}o.ready()})()}}}o.event.add(l,"load",o.ready)}o.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error").split(","),function(F,E){o.fn[E]=function(G){return G?this.bind(E,G):this.trigger(E)}});o(l).bind("unload",function(){for(var E in o.cache){if(E!=1&&o.cache[E].handle){o.event.remove(o.cache[E].handle.elem)}}});(function(){o.support={};var F=document.documentElement,G=document.createElement("script"),K=document.createElement("div"),J="script"+(new Date).getTime();K.style.display="none";K.innerHTML='   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';var H=K.getElementsByTagName("*"),E=K.getElementsByTagName("a")[0];if(!H||!H.length||!E){return}o.support={leadingWhitespace:K.firstChild.nodeType==3,tbody:!K.getElementsByTagName("tbody").length,objectAll:!!K.getElementsByTagName("object")[0].getElementsByTagName("*").length,htmlSerialize:!!K.getElementsByTagName("link").length,style:/red/.test(E.getAttribute("style")),hrefNormalized:E.getAttribute("href")==="/a",opacity:E.style.opacity==="0.5",cssFloat:!!E.style.cssFloat,scriptEval:false,noCloneEvent:true,boxModel:null};G.type="text/javascript";try{G.appendChild(document.createTextNode("window."+J+"=1;"))}catch(I){}F.insertBefore(G,F.firstChild);if(l[J]){o.support.scriptEval=true;delete l[J]}F.removeChild(G);if(K.attachEvent&&K.fireEvent){K.attachEvent("onclick",function(){o.support.noCloneEvent=false;K.detachEvent("onclick",arguments.callee)});K.cloneNode(true).fireEvent("onclick")}o(function(){var L=document.createElement("div");L.style.width=L.style.paddingLeft="1px";document.body.appendChild(L);o.boxModel=o.support.boxModel=L.offsetWidth===2;document.body.removeChild(L).style.display="none"})})();var w=o.support.cssFloat?"cssFloat":"styleFloat";o.props={"for":"htmlFor","class":"className","float":w,cssFloat:w,styleFloat:w,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",tabindex:"tabIndex"};o.fn.extend({_load:o.fn.load,load:function(G,J,K){if(typeof G!=="string"){return this._load(G)}var I=G.indexOf(" ");if(I>=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("<div/>").append(M.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H<F;H++){var E=o.data(this[H],"olddisplay");this[H].style.display=E||"";if(o.css(this[H],"display")==="none"){var G=this[H].tagName,K;if(m[G]){K=m[G]}else{var I=o("<"+G+" />").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H<F;H++){this[H].style.display=o.data(this[H],"olddisplay")||""}return this}},hide:function(H,I){if(H){return this.animate(t("hide",3),H,I)}else{for(var G=0,F=this.length;G<F;G++){var E=o.data(this[G],"olddisplay");if(!E&&E!=="none"){o.data(this[G],"olddisplay",o.css(this[G],"display"))}}for(var G=0,F=this.length;G<F;G++){this[G].style.display="none"}return this}},_toggle:o.fn.toggle,toggle:function(G,F){var E=typeof G==="boolean";return o.isFunction(G)&&o.isFunction(F)?this._toggle.apply(this,arguments):G==null||E?this.each(function(){var H=E?G:o(this).is(":hidden");o(this)[H?"show":"hide"]()}):this.animate(t("toggle",3),G,F)},fadeTo:function(E,G,F){return this.animate({opacity:G},E,F)},animate:function(I,F,H,G){var E=o.speed(F,H,G);return this[E.queue===false?"each":"queue"](function(){var K=o.extend({},E),M,L=this.nodeType==1&&o(this).is(":hidden"),J=this;for(M in I){if(I[M]=="hide"&&L||I[M]=="show"&&!L){return K.complete.call(this)}if((M=="height"||M=="width")&&this.style){K.display=o.css(this,"display");K.overflow=this.style.overflow}}if(K.overflow!=null){this.style.overflow="hidden"}K.curAnim=o.extend({},I);o.each(I,function(O,S){var R=new o.fx(J,K,O);if(/toggle|show|hide/.test(S)){R[S=="toggle"?L?"show":"hide":S](I)}else{var Q=S.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),T=R.cur(true)||0;if(Q){var N=parseFloat(Q[2]),P=Q[3]||"px";if(P!="px"){J.style[O]=(N||1)+P;T=((N||1)/R.cur(true))*T;J.style[O]=T+P}if(Q[1]){N=((Q[1]=="-="?-1:1)*N)+T}R.custom(T,N,P)}else{R.custom(T,S,"")}}});return true})},stop:function(F,E){var G=o.timers;if(F){this.queue([])}this.each(function(){for(var H=G.length-1;H>=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J<K.length;J++){if(!K[J]()){K.splice(J--,1)}}if(!K.length){clearInterval(n);n=g}},13)}},show:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.show=true;this.custom(this.prop=="width"||this.prop=="height"?1:0,this.cur());o(this.elem).show()},hide:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(H){var G=e();if(H||G>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})();﻿/*
 * jQuery UI 1.5.3
 *
 * Copyright (c) 2008 Paul Bakaus (ui.jquery.com)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI
 */
;(function($) {

$.ui = {
	plugin: {
		add: function(module, option, set) {
			var proto = $.ui[module].prototype;
			for(var i in set) {
				proto.plugins[i] = proto.plugins[i] || [];
				proto.plugins[i].push([option, set[i]]);
			}
		},
		call: function(instance, name, args) {
			var set = instance.plugins[name];
			if(!set) { return; }
			
			for (var i = 0; i < set.length; i++) {
				if (instance.options[set[i][0]]) {
					set[i][1].apply(instance.element, args);
				}
			}
		}	
	},
	cssCache: {},
	css: function(name) {
		if ($.ui.cssCache[name]) { return $.ui.cssCache[name]; }
		var tmp = $('<div class="ui-gen">').addClass(name).css({position:'absolute', top:'-5000px', left:'-5000px', display:'block'}).appendTo('body');
		
		//if (!$.browser.safari)
			//tmp.appendTo('body'); 
		
		//Opera and Safari set width and height to 0px instead of auto
		//Safari returns rgba(0,0,0,0) when bgcolor is not set
		$.ui.cssCache[name] = !!(
			(!(/auto|default/).test(tmp.css('cursor')) || (/^[1-9]/).test(tmp.css('height')) || (/^[1-9]/).test(tmp.css('width')) || 
			!(/none/).test(tmp.css('backgroundImage')) || !(/transparent|rgba\(0, 0, 0, 0\)/).test(tmp.css('backgroundColor')))
		);
		try { $('body').get(0).removeChild(tmp.get(0));	} catch(e){}
		return $.ui.cssCache[name];
	},
	disableSelection: function(el) {
		$(el).attr('unselectable', 'on').css('MozUserSelect', 'none');
	},
	enableSelection: function(el) {
		$(el).attr('unselectable', 'off').css('MozUserSelect', '');
	},
	hasScroll: function(e, a) {
		var scroll = /top/.test(a||"top") ? 'scrollTop' : 'scrollLeft', has = false;
		if (e[scroll] > 0) return true; e[scroll] = 1;
		has = e[scroll] > 0 ? true : false; e[scroll] = 0;
		return has;
	}
};


/** jQuery core modifications and additions **/

var _remove = $.fn.remove;
$.fn.remove = function() {
	$("*", this).add(this).triggerHandler("remove");
	return _remove.apply(this, arguments );
};

// $.widget is a factory to create jQuery plugins
// taking some boilerplate code out of the plugin code
// created by Scott González and Jörn Zaefferer
function getter(namespace, plugin, method) {
	var methods = $[namespace][plugin].getter || [];
	methods = (typeof methods == "string" ? methods.split(/,?\s+/) : methods);
	return ($.inArray(method, methods) != -1);
}

$.widget = function(name, prototype) {
	var namespace = name.split(".")[0];
	name = name.split(".")[1];
	
	// create plugin method
	$.fn[name] = function(options) {
		var isMethodCall = (typeof options == 'string'),
			args = Array.prototype.slice.call(arguments, 1);
		
		if (isMethodCall && getter(namespace, name, options)) {
			var instance = $.data(this[0], name);
			return (instance ? instance[options].apply(instance, args)
				: undefined);
		}
		
		return this.each(function() {
			var instance = $.data(this, name);
			if (isMethodCall && instance && $.isFunction(instance[options])) {
				instance[options].apply(instance, args);
			} else if (!isMethodCall) {
				$.data(this, name, new $[namespace][name](this, options));
			}
		});
	};
	
	// create widget constructor
	$[namespace][name] = function(element, options) {
		var self = this;
		
		this.widgetName = name;
		this.widgetBaseClass = namespace + '-' + name;
		
		this.options = $.extend({}, $.widget.defaults, $[namespace][name].defaults, options);
		this.element = $(element)
			.bind('setData.' + name, function(e, key, value) {
				return self.setData(key, value);
			})
			.bind('getData.' + name, function(e, key) {
				return self.getData(key);
			})
			.bind('remove', function() {
				return self.destroy();
			});
		this.init();
	};
	
	// add widget prototype
	$[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);
};

$.widget.prototype = {
	init: function() {},
	destroy: function() {
		this.element.removeData(this.widgetName);
	},
	
	getData: function(key) {
		return this.options[key];
	},
	setData: function(key, value) {
		this.options[key] = value;
		
		if (key == 'disabled') {
			this.element[value ? 'addClass' : 'removeClass'](
				this.widgetBaseClass + '-disabled');
		}
	},
	
	enable: function() {
		this.setData('disabled', false);
	},
	disable: function() {
		this.setData('disabled', true);
	}
};

$.widget.defaults = {
	disabled: false
};


/** Mouse Interaction Plugin **/

$.ui.mouse = {
	mouseInit: function() {
		var self = this;
	
		this.element.bind('mousedown.'+this.widgetName, function(e) {
			return self.mouseDown(e);
		});
		
		// Prevent text selection in IE
		if ($.browser.msie) {
			this._mouseUnselectable = this.element.attr('unselectable');
			this.element.attr('unselectable', 'on');
		}
		
		this.started = false;
	},
	
	// TODO: make sure destroying one instance of mouse doesn't mess with
	// other instances of mouse
	mouseDestroy: function() {
		this.element.unbind('.'+this.widgetName);
		
		// Restore text selection in IE
		($.browser.msie
			&& this.element.attr('unselectable', this._mouseUnselectable));
	},
	
	mouseDown: function(e) {
		// we may have missed mouseup (out of window)
		(this._mouseStarted && this.mouseUp(e));
		
		this._mouseDownEvent = e;
		
		var self = this,
			btnIsLeft = (e.which == 1),
			elIsCancel = (typeof this.options.cancel == "string" ? $(e.target).parents().add(e.target).filter(this.options.cancel).length : false);
		if (!btnIsLeft || elIsCancel || !this.mouseCapture(e)) {
			return true;
		}
		
		this._mouseDelayMet = !this.options.delay;
		if (!this._mouseDelayMet) {
			this._mouseDelayTimer = setTimeout(function() {
				self._mouseDelayMet = true;
			}, this.options.delay);
		}
		
		if (this.mouseDistanceMet(e) && this.mouseDelayMet(e)) {
			this._mouseStarted = (this.mouseStart(e) !== false);
			if (!this._mouseStarted) {
				e.preventDefault();
				return true;
			}
		}
		
		// these delegates are required to keep context
		this._mouseMoveDelegate = function(e) {
			return self.mouseMove(e);
		};
		this._mouseUpDelegate = function(e) {
			return self.mouseUp(e);
		};
		$(document)
			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
		
		return false;
	},
	
	mouseMove: function(e) {
		// IE mouseup check - mouseup happened when mouse was out of window
		if ($.browser.msie && !e.button) {
			return this.mouseUp(e);
		}
		
		if (this._mouseStarted) {
			this.mouseDrag(e);
			return false;
		}
		
		if (this.mouseDistanceMet(e) && this.mouseDelayMet(e)) {
			this._mouseStarted =
				(this.mouseStart(this._mouseDownEvent, e) !== false);
			(this._mouseStarted ? this.mouseDrag(e) : this.mouseUp(e));
		}
		
		return !this._mouseStarted;
	},
	
	mouseUp: function(e) {
		$(document)
			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
		
		if (this._mouseStarted) {
			this._mouseStarted = false;
			this.mouseStop(e);
		}
		
		return false;
	},
	
	mouseDistanceMet: function(e) {
		return (Math.max(
				Math.abs(this._mouseDownEvent.pageX - e.pageX),
				Math.abs(this._mouseDownEvent.pageY - e.pageY)
			) >= this.options.distance
		);
	},
	
	mouseDelayMet: function(e) {
		return this._mouseDelayMet;
	},
	
	// These are placeholder methods, to be overriden by extending plugin
	mouseStart: function(e) {},
	mouseDrag: function(e) {},
	mouseStop: function(e) {},
	mouseCapture: function(e) { return true; }
};

$.ui.mouse.defaults = {
	cancel: null,
	distance: 1,
	delay: 0
};

})(jQuery);
/*
 * jQuery UI Dialog
 *
 * Copyright (c) 2008 Richard D. Worth (rdworth.org)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 * 
 * http://docs.jquery.com/UI/Dialog
 *
 * Depends:
 *	ui.core.js
 *	ui.draggable.js
 *	ui.resizable.js
 */
(function($) {

var setDataSwitch = {
	dragStart: "start.draggable",
	drag: "drag.draggable",
	dragStop: "stop.draggable",
	maxHeight: "maxHeight.resizable",
	minHeight: "minHeight.resizable",
	maxWidth: "maxWidth.resizable",
	minWidth: "minWidth.resizable",
	resizeStart: "start.resizable",
	resize: "drag.resizable",
	resizeStop: "stop.resizable"
};

$.widget("ui.dialog", {
	init: function() {
		var self = this,
			options = this.options,
			resizeHandles = typeof options.resizable == 'string'
				? options.resizable
				: 'n,e,s,w,se,sw,ne,nw',
			
			uiDialogContent = this.element
				.addClass('ui-dialog-content')
				.wrap('<div/>')
				.wrap('<div/>'),
			
			uiDialogContainer = (this.uiDialogContainer = uiDialogContent.parent()
				.addClass('ui-dialog-container')
				.css({position: 'relative', width: '100%', height: '100%'})),
			
			title = options.title || uiDialogContent.attr('title') || '',
			uiDialogTitlebar = (this.uiDialogTitlebar =
				$('<div class="ui-dialog-titlebar"/>'))
				.append('<span class="ui-dialog-title">' + title + '</span>')
				.append('<a href="#" class="ui-dialog-titlebar-close"><span>X</span></a>')
				.prependTo(uiDialogContainer),
			
			uiDialog = (this.uiDialog = uiDialogContainer.parent())
				.appendTo(document.body)
				.hide()
				.addClass('ui-dialog')
				.addClass(options.dialogClass)
				// add content classes to dialog
				// to inherit theme at top level of element
				.addClass(uiDialogContent.attr('className'))
					.removeClass('ui-dialog-content')
				.css({
					position: 'absolute',
					width: options.width,
					height: options.height,
					overflow: 'hidden',
					zIndex: options.zIndex
				})
				// setting tabIndex makes the div focusable
				// setting outline to 0 prevents a border on focus in Mozilla
				.attr('tabIndex', -1).css('outline', 0).keydown(function(ev) {
					if (options.closeOnEscape) {
						var ESC = 27;
						(ev.keyCode && ev.keyCode == ESC && self.close());
					}
				})
				.mousedown(function() {
					self.moveToTop();
				}),
			
			uiDialogButtonPane = (this.uiDialogButtonPane = $('<div/>'))
				.addClass('ui-dialog-buttonpane').css({ position: 'absolute', bottom: 0 })
				.appendTo(uiDialog);
		
		this.uiDialogTitlebarClose = $('.ui-dialog-titlebar-close', uiDialogTitlebar)
			.hover(
				function() {
					$(this).addClass('ui-dialog-titlebar-close-hover');
				},
				function() {
					$(this).removeClass('ui-dialog-titlebar-close-hover');
				}
			)
			.mousedown(function(ev) {
				ev.stopPropagation();
			})
			.click(function() {
				self.close();
				return false;
			});

		this.uiDialogTitlebar.find("*").add(this.uiDialogTitlebar).each(function() {
			$.ui.disableSelection(this);
		});

		if ($.fn.draggable) {
			uiDialog.draggable({
				cancel: '.ui-dialog-content',
				helper: options.dragHelper,
				handle: '.ui-dialog-titlebar',
				start: function(e, ui) {
					self.moveToTop();
					(options.dragStart && options.dragStart.apply(self.element[0], arguments));
				},
				drag: function(e, ui) {
					(options.drag && options.drag.apply(self.element[0], arguments));
				},
				stop: function(e, ui) {
					(options.dragStop && options.dragStop.apply(self.element[0], arguments));
					$.ui.dialog.overlay.resize();
				}
			});
			(options.draggable || uiDialog.draggable('disable'));
		}
		
		if ($.fn.resizable) {
			uiDialog.resizable({
				cancel: '.ui-dialog-content',
				helper: options.resizeHelper,
				maxWidth: options.maxWidth,
				maxHeight: options.maxHeight,
				minWidth: options.minWidth,
				minHeight: options.minHeight,
				start: function() {
					(options.resizeStart && options.resizeStart.apply(self.element[0], arguments));
				},
				resize: function(e, ui) {
					(options.autoResize && self.size.apply(self));
					(options.resize && options.resize.apply(self.element[0], arguments));
				},
				handles: resizeHandles,
				stop: function(e, ui) {
					(options.autoResize && self.size.apply(self));
					(options.resizeStop && options.resizeStop.apply(self.element[0], arguments));
					$.ui.dialog.overlay.resize();
				}
			});
			(options.resizable || uiDialog.resizable('disable'));
		}
		
		this.createButtons(options.buttons);
		this.isOpen = false;
		
		(options.bgiframe && $.fn.bgiframe && uiDialog.bgiframe());
		(options.autoOpen && this.open());
	},
	
	setData: function(key, value){
		(setDataSwitch[key] && this.uiDialog.data(setDataSwitch[key], value));
		switch (key) {
			case "buttons":
				this.createButtons(value);
				break;
			case "draggable":
				this.uiDialog.draggable(value ? 'enable' : 'disable');
				break;
			case "height":
				this.uiDialog.height(value);
				break;
			case "position":
				this.position(value);
				break;
			case "resizable":
				(typeof value == 'string' && this.uiDialog.data('handles.resizable', value));
				this.uiDialog.resizable(value ? 'enable' : 'disable');
				break;
			case "title":
				$(".ui-dialog-title", this.uiDialogTitlebar).text(value);
				break;
			case "width":
				this.uiDialog.width(value);
				break;
		}
		
		$.widget.prototype.setData.apply(this, arguments);
	},
	
	position: function(pos) {
		var wnd = $(window), doc = $(document),
			pTop = doc.scrollTop(), pLeft = doc.scrollLeft(),
			minTop = pTop;
		
		if ($.inArray(pos, ['center','top','right','bottom','left']) >= 0) {
			pos = [
				pos == 'right' || pos == 'left' ? pos : 'center',
				pos == 'top' || pos == 'bottom' ? pos : 'middle'
			];
		}
		if (pos.constructor != Array) {
			pos = ['center', 'middle'];
		}
		if (pos[0].constructor == Number) {
			pLeft += pos[0];
		} else {
			switch (pos[0]) {
				case 'left':
					pLeft += 0;
					break;
				case 'right':
					pLeft += wnd.width() - this.uiDialog.width();
					break;
				default:
				case 'center':
					pLeft += (wnd.width() - this.uiDialog.width()) / 2;
			}
		}
		if (pos[1].constructor == Number) {
			pTop += pos[1];
		} else {
			switch (pos[1]) {
				case 'top':
					pTop += 0;
					break;
				case 'bottom':
					pTop += wnd.height() - this.uiDialog.height();
					break;
				default:
				case 'middle':
					pTop += (wnd.height() - this.uiDialog.height()) / 2;
			}
		}
		
		// prevent the dialog from being too high (make sure the titlebar
		// is accessible)
		pTop = Math.max(pTop, minTop);
		this.uiDialog.css({top: pTop, left: pLeft});
	},

	size: function() {
		var container = this.uiDialogContainer,
			titlebar = this.uiDialogTitlebar,
			content = this.element,
			tbMargin = parseInt(content.css('margin-top'),10) + parseInt(content.css('margin-bottom'),10),
			lrMargin = parseInt(content.css('margin-left'),10) + parseInt(content.css('margin-right'),10);
		content.height(container.height() - titlebar.outerHeight() - tbMargin);
		content.width(container.width() - lrMargin);
	},
	
	open: function() {
		if (this.isOpen) { return; }
		
		this.overlay = this.options.modal ? new $.ui.dialog.overlay(this) : null;
		(this.uiDialog.next().length > 0) && this.uiDialog.appendTo('body');
		this.position(this.options.position);
		this.uiDialog.show(this.options.show);
		this.options.autoResize && this.size();
		this.moveToTop(true);
		
		// CALLBACK: open
		var openEV = null;
		var openUI = {
			options: this.options
		};
		this.uiDialogTitlebarClose.focus();
		this.element.triggerHandler("dialogopen", [openEV, openUI], this.options.open);
		
		this.isOpen = true;
	},
	
	// the force parameter allows us to move modal dialogs to their correct
	// position on open
	moveToTop: function(force) {
		if ((this.options.modal && !force)
			|| (!this.options.stack && !this.options.modal)) { return this.element.triggerHandler("dialogfocus", [null, { options: this.options }], this.options.focus); }
		
		var maxZ = this.options.zIndex, options = this.options;
		$('.ui-dialog:visible').each(function() {
			maxZ = Math.max(maxZ, parseInt($(this).css('z-index'), 10) || options.zIndex);
		});
		(this.overlay && this.overlay.$el.css('z-index', ++maxZ));
		this.uiDialog.css('z-index', ++maxZ);
		
		this.element.triggerHandler("dialogfocus", [null, { options: this.options }], this.options.focus);
	},
	
	close: function() {
		(this.overlay && this.overlay.destroy());
		this.uiDialog.hide(this.options.hide);

		// CALLBACK: close
		var closeEV = null;
		var closeUI = {
			options: this.options
		};
		this.element.triggerHandler("dialogclose", [closeEV, closeUI], this.options.close);
		$.ui.dialog.overlay.resize();
		
		this.isOpen = false;
	},
	
	destroy: function() {
		(this.overlay && this.overlay.destroy());
		this.uiDialog.hide();
		this.element
			.unbind('.dialog')
			.removeData('dialog')
			.removeClass('ui-dialog-content')
			.hide().appendTo('body');
		this.uiDialog.remove();
	},
	
	createButtons: function(buttons) {
		var self = this,
			hasButtons = false,
			uiDialogButtonPane = this.uiDialogButtonPane;
		
		// remove any existing buttons
		uiDialogButtonPane.empty().hide();
		
		$.each(buttons, function() { return !(hasButtons = true); });
		if (hasButtons) {
			uiDialogButtonPane.show();
			$.each(buttons, function(name, fn) {
				$('<button/>')
					.text(name)
					.click(function() { fn.apply(self.element[0], arguments); })
					.appendTo(uiDialogButtonPane);
			});
		}
	}
});

$.extend($.ui.dialog, {
	defaults: {
		autoOpen: true,
		autoResize: true,
		bgiframe: false,
		buttons: {},
		closeOnEscape: true,
		draggable: true,
		height: 200,
		minHeight: 100,
		minWidth: 150,
		modal: false,
		overlay: {},
		position: 'center',
		resizable: true,
		stack: true,
		width: 300,
		zIndex: 1000
	},
	
	overlay: function(dialog) {
		this.$el = $.ui.dialog.overlay.create(dialog);
	}
});

$.extend($.ui.dialog.overlay, {
	instances: [],
	events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
		function(e) { return e + '.dialog-overlay'; }).join(' '),
	create: function(dialog) {
		if (this.instances.length === 0) {
			// prevent use of anchors and inputs
			// we use a setTimeout in case the overlay is created from an
			// event that we're going to be cancelling (see #2804)
			setTimeout(function() {
				$('a, :input').bind($.ui.dialog.overlay.events, function() {
					// allow use of the element if inside a dialog and
					// - there are no modal dialogs
					// - there are modal dialogs, but we are in front of the topmost modal
					var allow = false;
					var $dialog = $(this).parents('.ui-dialog');
					if ($dialog.length) {
						var $overlays = $('.ui-dialog-overlay');
						if ($overlays.length) {
							var maxZ = parseInt($overlays.css('z-index'), 10);
							$overlays.each(function() {
								maxZ = Math.max(maxZ, parseInt($(this).css('z-index'), 10));
							});
							allow = parseInt($dialog.css('z-index'), 10) > maxZ;
						} else {
							allow = true;
						}
					}
					return allow;
				});
			}, 1);
			
			// allow closing by pressing the escape key
			$(document).bind('keydown.dialog-overlay', function(e) {
				var ESC = 27;
				(e.keyCode && e.keyCode == ESC && dialog.close()); 
			});
			
			// handle window resize
			$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
		}
		
		var $el = $('<div/>').appendTo(document.body)
			.addClass('ui-dialog-overlay').css($.extend({
				borderWidth: 0, margin: 0, padding: 0,
				position: 'absolute', top: 0, left: 0,
				width: this.width(),
				height: this.height()
			}, dialog.options.overlay));
		
		(dialog.options.bgiframe && $.fn.bgiframe && $el.bgiframe());
		
		this.instances.push($el);
		return $el;
	},
	
	destroy: function($el) {
		this.instances.splice($.inArray(this.instances, $el), 1);
		
		if (this.instances.length === 0) {
			$('a, :input').add([document, window]).unbind('.dialog-overlay');
		}
		
		$el.remove();
	},
	
	height: function() {
		if ($.browser.msie && $.browser.version < 7) {
			var scrollHeight = Math.max(
				document.documentElement.scrollHeight,
				document.body.scrollHeight
			);
			var offsetHeight = Math.max(
				document.documentElement.offsetHeight,
				document.body.offsetHeight
			);
			
			if (scrollHeight < offsetHeight) {
				return $(window).height() + 'px';
			} else {
				return scrollHeight + 'px';
			}
		} else {
			return $(document).height() + 'px';
		}
	},
	
	width: function() {
		if ($.browser.msie && $.browser.version < 7) {
			var scrollWidth = Math.max(
				document.documentElement.scrollWidth,
				document.body.scrollWidth
			);
			var offsetWidth = Math.max(
				document.documentElement.offsetWidth,
				document.body.offsetWidth
			);
			
			if (scrollWidth < offsetWidth) {
				return $(window).width() + 'px';
			} else {
				return scrollWidth + 'px';
			}
		} else {
			return $(document).width() + 'px';
		}
	},
	
	resize: function() {
		/* If the dialog is draggable and the user drags it past the
		 * right edge of the window, the document becomes wider so we
		 * need to stretch the overlay. If the user then drags the
		 * dialog back to the left, the document will become narrower,
		 * so we need to shrink the overlay to the appropriate size.
		 * This is handled by shrinking the overlay before setting it
		 * to the full document size.
		 */
		var $overlays = $([]);
		$.each($.ui.dialog.overlay.instances, function() {
			$overlays = $overlays.add(this);
		});
		
		$overlays.css({
			width: 0,
			height: 0
		}).css({
			width: $.ui.dialog.overlay.width(),
			height: $.ui.dialog.overlay.height()
		});
	}
});

$.extend($.ui.dialog.overlay.prototype, {
	destroy: function() {
		$.ui.dialog.overlay.destroy(this.$el);
	}
});

})(jQuery);
/*
 * JQuery Dialog Extended for Photobox
 *
 * Depends:
 *	ui.core.js
 *	ui.draggable.js
 *	ui.resizable.js
 *	ui.dialog.js
 *
 * Author:
 * Antonio Lorusso
 *
 */

//VWD Intellisense References
/// <reference path="ui.dialog.js" />
/// <reference path="ui.core.js" />
/// <reference path="dialog.js" />

(function($) {

$.extend($.ui.dialog.prototype, {

	customise: function(params){

	    /* specific layout customisation */
	    // Get the ui-dialog reference. This is used to narrow-down jQuery dom searches to improve performance.
	    var ui_dialog = $('.ui-dialog')
	    $('.ui-resizable-handle', ui_dialog).remove();
	    $('.ui-dialog-titlebar', ui_dialog).remove();
		ui_dialog
			.addClass('pbx_dialog')
			.attr('id', 'pbx_dialog_window')
			.removeClass('pbx_dialog_content');

		$('.ui-dialog-container:has(#pbx_dialog_'+params.counter+')',ui_dialog)
			.addClass('pbx_shadow')
			.prepend('<div id="pbx_popup_header"><a title="Close" id="pbx_popup_close" class="pbx_dialog_close" href="#">Close</a><div id="pbx_popup_title">' + params.title + '</div></div>')
			.prepend('<b class="pbx_corner_top"><b class="pbx_corner_b1"/><b class="pbx_corner_b2"/><b class="pbx_corner_b3"/><b class="pbx_corner_b4"/></b>')
			.append('<b class="pbx_corner_bottom"><b class="pbx_corner_b4"/><b class="pbx_corner_b3"/><b class="pbx_corner_b2"/><b class="pbx_corner_b1"/></b>');

		/* do not attach the shadow if ie, jQuery 1.3.x compatible */
		if((typeof(jQuery.browser) !== 'undefined'	&& !$.browser.msie) || (typeof(jQuery.support) !== 'undefined' && $.support.opacity))
		{
			$('.ui-dialog-container:has(#pbx_dialog_'+params.counter+')',ui_dialog).append('<span class="pbx_shadow_tr"/><span class="pbx_shadow_right"/><span class="pbx_shadow_br"/><span class="pbx_shadow_bottom"/><span class="pbx_shadow_bl"/>');
		}

		$('.ui-dialog-container:has(#pbx_dialog_'+params.counter+')',ui_dialog).addClass('pbx_dialog_'+params.counter).css({
				'height': 'auto',
				'width': 'auto'
				}); /*important for shadow*/

				/* specific content customisation */
		$('.ui-dialog-content',ui_dialog).removeAttr('style');

		/*Set maximum height to auto*/
		ui_dialog.css({
				'height': 'auto'
				});
		/* force maximum height of 500px and display scrollbar if over */
		/* Scrollbars not actually displayed, so this is commented out. Overflowing dialogs will expand instead.
		if ($('.ui-dialog-content', ui_dialog).height() > 500) {
		    $('.ui-dialog-content', ui_dialog).css({
				'height': '500px',
				'overflow': 'auto'
			});
		}
		*/

		//temporary hacky solution to replace the "close" text with a translation
		$('.pbx_dialog_close', ui_dialog).text($('#pbx_popup_close').text());
		$('.pbx_dialog_close', ui_dialog).attr('title', $('#pbx_popup_close').text());
	},

	hideObjects : function(val)
	{
		$('embed,object').css('visibility',(val == true)?'hidden':'visible');
	},
	/* Function to run after closing */
	postClose : function()
	{
		this.element.html('<div class="pbx_loading"></div>');
	},
	addContent : function(content)
	{
		this.element.html(content);
	}
});

$.extend($.ui.dialog, {
	defaults: {
		autoOpen: true,
		autoResize: true,
		bgiframe: true,
		buttons: {},
		closeOnEscape: true,
		draggable: false,
		minHeight: 100,
		minWidth: 150,
		modal: true,
		overlay: {
			opacity: '0.6',
			backgroundColor: '#E2E2E4'
		},
		position: 'center',
		resizable: false,
		stack: true,
		width: 300,
		zIndex: 1000
	}
});

})(jQuery);
/*
 * jQuery UI Effects 1.7.2
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/
 */
;jQuery.effects || (function($) {

$.effects = {
	version: "1.7.2",

	// Saves a set of properties in a data storage
	save: function(element, set) {
		for(var i=0; i < set.length; i++) {
			if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
		}
	},

	// Restores a set of previously saved properties from a data storage
	restore: function(element, set) {
		for(var i=0; i < set.length; i++) {
			if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
		}
	},

	setMode: function(el, mode) {
		if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
		return mode;
	},

	getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
		// this should be a little more flexible in the future to handle a string & hash
		var y, x;
		switch (origin[0]) {
			case 'top': y = 0; break;
			case 'middle': y = 0.5; break;
			case 'bottom': y = 1; break;
			default: y = origin[0] / original.height;
		};
		switch (origin[1]) {
			case 'left': x = 0; break;
			case 'center': x = 0.5; break;
			case 'right': x = 1; break;
			default: x = origin[1] / original.width;
		};
		return {x: x, y: y};
	},

	// Wraps the element around a wrapper that copies position properties
	createWrapper: function(element) {

		//if the element is already wrapped, return it
		if (element.parent().is('.ui-effects-wrapper'))
			return element.parent();

		//Cache width,height and float properties of the element, and create a wrapper around it
		var props = { width: element.outerWidth(true), height: element.outerHeight(true), 'float': element.css('float') };
		element.wrap('<div class="ui-effects-wrapper" style="font-size:100%;background:transparent;border:none;margin:0;padding:0"></div>');
		var wrapper = element.parent();

		//Transfer the positioning of the element to the wrapper
		if (element.css('position') == 'static') {
			wrapper.css({ position: 'relative' });
			element.css({ position: 'relative'} );
		} else {
			var top = element.css('top'); if(isNaN(parseInt(top,10))) top = 'auto';
			var left = element.css('left'); if(isNaN(parseInt(left,10))) left = 'auto';
			wrapper.css({ position: element.css('position'), top: top, left: left, zIndex: element.css('z-index') }).show();
			element.css({position: 'relative', top: 0, left: 0 });
		}

		wrapper.css(props);
		return wrapper;
	},

	removeWrapper: function(element) {
		if (element.parent().is('.ui-effects-wrapper'))
			return element.parent().replaceWith(element);
		return element;
	},

	setTransition: function(element, list, factor, value) {
		value = value || {};
		$.each(list, function(i, x){
			unit = element.cssUnit(x);
			if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
		});
		return value;
	},

	//Base function to animate from one class to another in a seamless transition
	animateClass: function(value, duration, easing, callback) {

		var cb = (typeof easing == "function" ? easing : (callback ? callback : null));
		var ea = (typeof easing == "string" ? easing : null);

		return this.each(function() {

			var offset = {}; var that = $(this); var oldStyleAttr = that.attr("style") || '';
			if(typeof oldStyleAttr == 'object') oldStyleAttr = oldStyleAttr["cssText"]; /* Stupidly in IE, style is a object.. */
			if(value.toggle) { that.hasClass(value.toggle) ? value.remove = value.toggle : value.add = value.toggle; }

			//Let's get a style offset
			var oldStyle = $.extend({}, (document.defaultView ? document.defaultView.getComputedStyle(this,null) : this.currentStyle));
			if(value.add) that.addClass(value.add); if(value.remove) that.removeClass(value.remove);
			var newStyle = $.extend({}, (document.defaultView ? document.defaultView.getComputedStyle(this,null) : this.currentStyle));
			if(value.add) that.removeClass(value.add); if(value.remove) that.addClass(value.remove);

			// The main function to form the object for animation
			for(var n in newStyle) {
				if( typeof newStyle[n] != "function" && newStyle[n] /* No functions and null properties */
				&& n.indexOf("Moz") == -1 && n.indexOf("length") == -1 /* No mozilla spezific render properties. */
				&& newStyle[n] != oldStyle[n] /* Only values that have changed are used for the animation */
				&& (n.match(/color/i) || (!n.match(/color/i) && !isNaN(parseInt(newStyle[n],10)))) /* Only things that can be parsed to integers or colors */
				&& (oldStyle.position != "static" || (oldStyle.position == "static" && !n.match(/left|top|bottom|right/))) /* No need for positions when dealing with static positions */
				) offset[n] = newStyle[n];
			}

			that.animate(offset, duration, ea, function() { // Animate the newly constructed offset object
				// Change style attribute back to original. For stupid IE, we need to clear the damn object.
				if(typeof $(this).attr("style") == 'object') { $(this).attr("style")["cssText"] = ""; $(this).attr("style")["cssText"] = oldStyleAttr; } else $(this).attr("style", oldStyleAttr);
				if(value.add) $(this).addClass(value.add); if(value.remove) $(this).removeClass(value.remove);
				if(cb) cb.apply(this, arguments);
			});

		});
	}
};


function _normalizeArguments(a, m) {

	var o = a[1] && a[1].constructor == Object ? a[1] : {}; if(m) o.mode = m;
	var speed = a[1] && a[1].constructor != Object ? a[1] : (o.duration ? o.duration : a[2]); //either comes from options.duration or the secon/third argument
		speed = $.fx.off ? 0 : typeof speed === "number" ? speed : $.fx.speeds[speed] || $.fx.speeds._default;
	var callback = o.callback || ( $.isFunction(a[1]) && a[1] ) || ( $.isFunction(a[2]) && a[2] ) || ( $.isFunction(a[3]) && a[3] );

	return [a[0], o, speed, callback];
	
}

//Extend the methods of jQuery
$.fn.extend({

	//Save old methods
	_show: $.fn.show,
	_hide: $.fn.hide,
	__toggle: $.fn.toggle,
	_addClass: $.fn.addClass,
	_removeClass: $.fn.removeClass,
	_toggleClass: $.fn.toggleClass,

	// New effect methods
	effect: function(fx, options, speed, callback) {
		return $.effects[fx] ? $.effects[fx].call(this, {method: fx, options: options || {}, duration: speed, callback: callback }) : null;
	},

	show: function() {
		if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])))
			return this._show.apply(this, arguments);
		else {
			return this.effect.apply(this, _normalizeArguments(arguments, 'show'));
		}
	},

	hide: function() {
		if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])))
			return this._hide.apply(this, arguments);
		else {
			return this.effect.apply(this, _normalizeArguments(arguments, 'hide'));
		}
	},

	toggle: function(){
		if(!arguments[0] ||
			(arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])) ||
			($.isFunction(arguments[0]) || typeof arguments[0] == 'boolean')) {
			return this.__toggle.apply(this, arguments);
		} else {
			return this.effect.apply(this, _normalizeArguments(arguments, 'toggle'));
		}
	},

	addClass: function(classNames, speed, easing, callback) {
		return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
	},
	removeClass: function(classNames,speed,easing,callback) {
		return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
	},
	toggleClass: function(classNames,speed,easing,callback) {
		return ( (typeof speed !== "boolean") && speed ) ? $.effects.animateClass.apply(this, [{ toggle: classNames },speed,easing,callback]) : this._toggleClass(classNames, speed);
	},
	morph: function(remove,add,speed,easing,callback) {
		return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
	},
	switchClass: function() {
		return this.morph.apply(this, arguments);
	},

	// helper functions
	cssUnit: function(key) {
		var style = this.css(key), val = [];
		$.each( ['em','px','%','pt'], function(i, unit){
			if(style.indexOf(unit) > 0)
				val = [parseFloat(style), unit];
		});
		return val;
	}
});

/*
 * jQuery Color Animations
 * Copyright 2007 John Resig
 * Released under the MIT and GPL licenses.
 */

// We override the animation for all of these color styles
$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'], function(i,attr){
		$.fx.step[attr] = function(fx) {
				if ( fx.state == 0 ) {
						fx.start = getColor( fx.elem, attr );
						fx.end = getRGB( fx.end );
				}

				fx.elem.style[attr] = "rgb(" + [
						Math.max(Math.min( parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0],10), 255), 0),
						Math.max(Math.min( parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1],10), 255), 0),
						Math.max(Math.min( parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2],10), 255), 0)
				].join(",") + ")";
			};
});

// Color Conversion functions from highlightFade
// By Blair Mitchelmore
// http://jquery.offput.ca/highlightFade/

// Parse strings looking for color tuples [255,255,255]
function getRGB(color) {
		var result;

		// Check if we're already dealing with an array of colors
		if ( color && color.constructor == Array && color.length == 3 )
				return color;

		// Look for rgb(num,num,num)
		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
				return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];

		// Look for rgb(num%,num%,num%)
		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
				return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];

		// Look for #a0b1c2
		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
				return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];

		// Look for #fff
		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
				return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];

		// Look for rgba(0, 0, 0, 0) == transparent in Safari 3
		if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
				return colors['transparent'];

		// Otherwise, we're most likely dealing with a named color
		return colors[$.trim(color).toLowerCase()];
}

function getColor(elem, attr) {
		var color;

		do {
				color = $.curCSS(elem, attr);

				// Keep going until we find an element that has color, or we hit the body
				if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
						break;

				attr = "backgroundColor";
		} while ( elem = elem.parentNode );

		return getRGB(color);
};

// Some named colors to work with
// From Interface by Stefan Petre
// http://interface.eyecon.ro/

var colors = {
	aqua:[0,255,255],
	azure:[240,255,255],
	beige:[245,245,220],
	black:[0,0,0],
	blue:[0,0,255],
	brown:[165,42,42],
	cyan:[0,255,255],
	darkblue:[0,0,139],
	darkcyan:[0,139,139],
	darkgrey:[169,169,169],
	darkgreen:[0,100,0],
	darkkhaki:[189,183,107],
	darkmagenta:[139,0,139],
	darkolivegreen:[85,107,47],
	darkorange:[255,140,0],
	darkorchid:[153,50,204],
	darkred:[139,0,0],
	darksalmon:[233,150,122],
	darkviolet:[148,0,211],
	fuchsia:[255,0,255],
	gold:[255,215,0],
	green:[0,128,0],
	indigo:[75,0,130],
	khaki:[240,230,140],
	lightblue:[173,216,230],
	lightcyan:[224,255,255],
	lightgreen:[144,238,144],
	lightgrey:[211,211,211],
	lightpink:[255,182,193],
	lightyellow:[255,255,224],
	lime:[0,255,0],
	magenta:[255,0,255],
	maroon:[128,0,0],
	navy:[0,0,128],
	olive:[128,128,0],
	orange:[255,165,0],
	pink:[255,192,203],
	purple:[128,0,128],
	violet:[128,0,128],
	red:[255,0,0],
	silver:[192,192,192],
	white:[255,255,255],
	yellow:[255,255,0],
	transparent: [255,255,255]
};

/*
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 *
 * Uses the built in easing capabilities added In jQuery 1.1
 * to offer multiple easing options
 *
 * TERMS OF USE - jQuery Easing
 *
 * Open source under the BSD License.
 *
 * Copyright 2008 George McGinley Smith
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 *
 * Neither the name of the author nor the names of contributors may be used to endorse
 * or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
*/

// t: current time, b: begInnIng value, c: change In value, d: duration
$.easing.jswing = $.easing.swing;

$.extend($.easing,
{
	def: 'easeOutQuad',
	swing: function (x, t, b, c, d) {
		//alert($.easing.default);
		return $.easing[$.easing.def](x, t, b, c, d);
	},
	easeInQuad: function (x, t, b, c, d) {
		return c*(t/=d)*t + b;
	},
	easeOutQuad: function (x, t, b, c, d) {
		return -c *(t/=d)*(t-2) + b;
	},
	easeInOutQuad: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	easeInCubic: function (x, t, b, c, d) {
		return c*(t/=d)*t*t + b;
	},
	easeOutCubic: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	},
	easeInOutCubic: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	},
	easeInQuart: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t + b;
	},
	easeOutQuart: function (x, t, b, c, d) {
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	easeInOutQuart: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	},
	easeInQuint: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t*t + b;
	},
	easeOutQuint: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	easeInOutQuint: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	},
	easeInSine: function (x, t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	easeOutSine: function (x, t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},
	easeInOutSine: function (x, t, b, c, d) {
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	easeInExpo: function (x, t, b, c, d) {
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},
	easeOutExpo: function (x, t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	easeInOutExpo: function (x, t, b, c, d) {
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	},
	easeInCirc: function (x, t, b, c, d) {
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},
	easeOutCirc: function (x, t, b, c, d) {
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},
	easeInOutCirc: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	},
	easeInElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	},
	easeOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},
	easeInOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
	},
	easeInBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	easeOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},
	easeInOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	},
	easeInBounce: function (x, t, b, c, d) {
		return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
	},
	easeOutBounce: function (x, t, b, c, d) {
		if ((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
	},
	easeInOutBounce: function (x, t, b, c, d) {
		if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
		return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
	}
});

/*
 *
 * TERMS OF USE - EASING EQUATIONS
 *
 * Open source under the BSD License.
 *
 * Copyright 2001 Robert Penner
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 *
 * Neither the name of the author nor the names of contributors may be used to endorse
 * or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

})(jQuery);
/*
 * jQuery UI Effects Highlight 1.7.2
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Highlight
 *
 * Depends:
 *	effects.core.js
 */
(function($) {

$.effects.highlight = function(o) {

	return this.queue(function() {

		// Create element
		var el = $(this), props = ['backgroundImage','backgroundColor','opacity'];

		// Set options
		var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
		var color = o.options.color || "#ffff99"; // Default highlight color
		var oldColor = el.css("backgroundColor");

		// Adjust
		$.effects.save(el, props); el.show(); // Save & Show
		el.css({backgroundImage: 'none', backgroundColor: color}); // Shift

		// Animation
		var animation = {backgroundColor: oldColor };
		if (mode == "hide") animation['opacity'] = 0;

		// Animate
		el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
			if(mode == "hide") el.hide();
			$.effects.restore(el, props);
		if (mode == "show" && $.browser.msie) this.style.removeAttribute('filter');
			if(o.callback) o.callback.apply(this, arguments);
			el.dequeue();
		}});

	});

};

})(jQuery);
/**
 * jQuery BASE64 functions
 *
 * 	<code>
 * 		Encodes the given data with base64.
 * 		String $.base64Encode ( String str )
 *		<br />
 * 		Decodes a base64 encoded data.
 * 		String $.base64Decode ( String str )
 * 	</code>
 *
 * Encodes and Decodes the given data in base64.
 * This encoding is designed to make binary data survive transport through transport layers that are not 8-bit clean, such as mail bodies.
 * Base64-encoded data takes about 33% more space than the original data.
 * This javascript code is used to encode / decode data using base64 (this encoding is designed to make binary data survive transport through transport layers that are not 8-bit clean). Script is fully compatible with UTF-8 encoding. You can use base64 encoded data as simple encryption mechanism.
 * If you plan using UTF-8 encoding in your project don't forget to set the page encoding to UTF-8 (Content-Type meta tag).
 * This function orginally get from the WebToolkit and rewrite for using as the jQuery plugin.
 *
 * Example
 * 	Code
 * 		<code>
 * 			$.base64Encode("I'm Persian.");
 * 		</code>
 * 	Result
 * 		<code>
 * 			"SSdtIFBlcnNpYW4u"
 * 		</code>
 * 	Code
 * 		<code>
 * 			$.base64Decode("SSdtIFBlcnNpYW4u");
 * 		</code>
 * 	Result
 * 		<code>
 * 			"I'm Persian."
 * 		</code>
 *
 * @alias Muhammad Hussein Fattahizadeh < muhammad [AT] semnanweb [DOT] com >
 * @link http://www.semnanweb.com/jquery-plugin/base64.html
 * @see http://www.webtoolkit.info/
 * @license http://www.gnu.org/licenses/gpl.html [GNU General Public License]
 * @param {jQuery} {base64Encode:function(input))
 * @param {jQuery} {base64Decode:function(input))
 * @return string
 */

(function($){

	var keyString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

	var uTF8Encode = function(string) {
		string = string.replace(/\x0d\x0a/g, "\x0a");
		var output = "";
		for (var n = 0; n < string.length; n++) {
			var c = string.charCodeAt(n);
			if (c < 128) {
				output += String.fromCharCode(c);
			} else if ((c > 127) && (c < 2048)) {
				output += String.fromCharCode((c >> 6) | 192);
				output += String.fromCharCode((c & 63) | 128);
			} else {
				output += String.fromCharCode((c >> 12) | 224);
				output += String.fromCharCode(((c >> 6) & 63) | 128);
				output += String.fromCharCode((c & 63) | 128);
			}
		}
		return output;
	};

	var uTF8Decode = function(input) {
		var string = "";
		var i = 0;
		var c = c1 = c2 = 0;
		while ( i < input.length ) {
			c = input.charCodeAt(i);
			if (c < 128) {
				string += String.fromCharCode(c);
				i++;
			} else if ((c > 191) && (c < 224)) {
				c2 = input.charCodeAt(i+1);
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			} else {
				c2 = input.charCodeAt(i+1);
				c3 = input.charCodeAt(i+2);
				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}
		}
		return string;
	}

	$.extend({
		base64Encode: function(input) {
			var output = "";
			var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
			var i = 0;
			input = uTF8Encode(input);
			while (i < input.length) {
				chr1 = input.charCodeAt(i++);
				chr2 = input.charCodeAt(i++);
				chr3 = input.charCodeAt(i++);
				enc1 = chr1 >> 2;
				enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
				enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
				enc4 = chr3 & 63;
				if (isNaN(chr2)) {
					enc3 = enc4 = 64;
				} else if (isNaN(chr3)) {
					enc4 = 64;
				}
				output = output + keyString.charAt(enc1) + keyString.charAt(enc2) + keyString.charAt(enc3) + keyString.charAt(enc4);
			}
			return output;
		},
		base64Decode: function(input) {
			var output = "";
			var chr1, chr2, chr3;
			var enc1, enc2, enc3, enc4;
			var i = 0;
			input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
			while (i < input.length) {
				enc1 = keyString.indexOf(input.charAt(i++));
				enc2 = keyString.indexOf(input.charAt(i++));
				enc3 = keyString.indexOf(input.charAt(i++));
				enc4 = keyString.indexOf(input.charAt(i++));
				chr1 = (enc1 << 2) | (enc2 >> 4);
				chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
				chr3 = ((enc3 & 3) << 6) | enc4;
				output = output + String.fromCharCode(chr1);
				if (enc3 != 64) {
					output = output + String.fromCharCode(chr2);
				}
				if (enc4 != 64) {
					output = output + String.fromCharCode(chr3);
				}
			}
			output = uTF8Decode(output);
			return output;
		}
	});
})(jQuery);
/*!*
 * @filename include.jquery.js
 * @name jQuery Include File
 * @type jQuery
 * @projectDescription Include a file (css and js) in a head of the document and execute
 * @date 08/07/2008
 * @version 1.0
 * @cat Ajax
 * @require
 * @author Alex
 * @param required none url String|Array The address of the plugin that will be inserted.
 * You can pass a indexed array of url
 * @param optional none callback Function The function to be executed after the file has loaded
 * @example
 * $.include('/foo/test/file.js');
 * @desc load the current script
 * @example
 * var files = ['test.js','another.js','onemore.js'];
 * $.include(files,function(){
 * 		//execute some code after all scripts are completed
 * });
 * @desc load all the script inside the array
 * @return false | Element (object)
 */

(function($) {

	$.extend({
		// You can change the base path to be applied in all imports
		ImportBasePath: '',
		// Associative array storing waiting tasks and their callback
		__WaitingTasks: {},
		// Called when a single file is loaded successfully - update and check WaitingTasks to see if it's ok to load callback
		__loadedSuccessfully: function(taskId){
			if (taskId in $.__WaitingTasks){
				if (($.__WaitingTasks[taskId].loading -= 1) < 1){
					var callback = $.__WaitingTasks[taskId].task;
					if(typeof callback=='function') { callback() }
				}
			}
		},
		//pass a file name and return a array with file name and extension
		fileinfo:	function(data){
			data = data.replace(/^\s|\s$|\?[0-9]+$/g, "");
			var m;
			if (/\.\w+$/.test(data)) {
				m = data.match(/([^\/\\]+)\.(\w+)$/);
				if (m) {
					if (m[2] == 'js') {
						return {
							filename: m[1],
							ext: m[2],
							tag: 'script'
						};
					}
					else
						if (m[2] == 'css') {
							return {
								filename: m[1],
								ext: m[2],
								tag: 'link'
							};
						}
						else {
							return {
								filename: m[1],
								ext: m[2],
								tag: null
							};
						}
				}
				else {
					return {
						filename: null,
						ext: null
					};
				}
			} else {
				m = data.match(/([^\/\\]+)$/);
				if (m) {
					return {
						filename: m[1],
						ext: null,
						tag: null
					};
				}
				else {
					return {
						filename: null,
						ext: null,
						tag: null
					};
				}
			}
		},
		//Check if the file that is been included already exist and return a Boolean value
		fileExist: function(filename,filetype,attrCheck) {
			var elementsArray = document.getElementsByTagName(filetype);
			for(var i=0;i<elementsArray.length;i++) {
				if(elementsArray[i].getAttribute(attrCheck)==$.ImportBasePath+filename) {
					return true;
				}
			}
			return false;
		},
		//Create the element depending of the file type and return the element (Object)
		createElement: function(filename,filetype) {
			switch(filetype) {
			case 'script' :
				if (!$.fileExist(filename, filetype, 'src')) {
					var scriptTag = document.createElement(filetype);
					scriptTag.setAttribute('language', 'javascript');
					scriptTag.setAttribute('type', 'text/javascript');
					scriptTag.setAttribute('src', $.ImportBasePath + filename);
					return scriptTag;
				} else {
					return false;
				}
				break;
			case 'link' :
				if (!$.fileExist(filename, filetype, 'href')) {
					var styleTag = document.createElement(filetype);
					styleTag.setAttribute('type', 'text/css');
					styleTag.setAttribute('rel', 'stylesheet');
					styleTag.setAttribute('href', $.ImportBasePath + filename);
					return styleTag;
				} else {
					return false;
				}
				break;

			default :
				return false;
			break;
			}
		},
		cssReady: function(index, taskId) {
			function check() {
				if(document.styleSheets[index]){
					window.clearInterval(checkInterval);
					$.__loadedSuccessfully(taskId);
				}
			}
			var checkInterval = window.setInterval(check,200);
		},
		//The main function to insert the file
		include: function(file,callback) {
			var headerTag = document.getElementsByTagName('head')[0];
			var fileArray = [];
			//if file is string, give a single index element
			typeof file=='string' ? fileArray[0] = file : fileArray = file;	
			// Create a unique id using the current time
			var taskId = Math.random();
			$.__WaitingTasks[taskId] = {'loading': fileArray.length, 'task': callback};
			//go through all the files
			for (var i = 0; i < fileArray.length; i++) {
				var elementTag = $.fileinfo(fileArray[i]).tag;
				var el = [];
				if (elementTag !== null) {
					el[i] = $.createElement(fileArray[i], elementTag);
					if (el[i]) {
						headerTag.appendChild(el[i]);
						if (elementTag == 'link') {
							$.cssReady(i, taskId);
						}
						else 
						{
								// Webkit
								if (/WebKit/i.test(navigator.userAgent)) {
									$(document).ready(function(){
										var _timer = setInterval(function(){
											if (/loaded|complete/.test(document.readyState)) {
												clearInterval(_timer);
												$.__loadedSuccessfully(taskId); // call of the call
											}
										}, 100);
									});
								};
								// Mozilla
								el[i].onload = function(){
									$(document).ready(function(){ $.__loadedSuccessfully(taskId); });
								};
								// IE
								el[i].onreadystatechange = function(){
									if (/loaded|complete/.test(this.readyState)) {
										$(document).ready(function(){ $.__loadedSuccessfully(taskId); });
									}
								};
						}	
					}else{
						$.__loadedSuccessfully(taskId);
					}
				} else {
					return false;
				}
			}
		}
	});

})(jQuery);
/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-07-21 18:44:59 -0500 (Sat, 21 Jul 2007) $
 * $Rev: 2446 $
 *
 * Version 2.1.1
 */

(function($){

/**
 * The bgiframe is chainable and applies the iframe hack to get 
 * around zIndex issues in IE6. It will only apply itself in IE6 
 * and adds a class to the iframe called 'bgiframe'. The iframe
 * is appeneded as the first child of the matched element(s) 
 * with a tabIndex and zIndex of -1.
 * 
 * By default the plugin will take borders, sized with pixel units,
 * into account. If a different unit is used for the border's width,
 * then you will need to use the top and left settings as explained below.
 *
 * NOTICE: This plugin has been reported to cause perfromance problems
 * when used on elements that change properties (like width, height and
 * opacity) a lot in IE6. Most of these problems have been caused by 
 * the expressions used to calculate the elements width, height and 
 * borders. Some have reported it is due to the opacity filter. All 
 * these settings can be changed if needed as explained below.
 *
 * @example $('div').bgiframe();
 * @before <div><p>Paragraph</p></div>
 * @result <div><iframe class="bgiframe".../><p>Paragraph</p></div>
 *
 * @param Map settings Optional settings to configure the iframe.
 * @option String|Number top The iframe must be offset to the top
 * 		by the width of the top border. This should be a negative 
 *      number representing the border-top-width. If a number is 
 * 		is used here, pixels will be assumed. Otherwise, be sure
 *		to specify a unit. An expression could also be used. 
 * 		By default the value is "auto" which will use an expression 
 * 		to get the border-top-width if it is in pixels.
 * @option String|Number left The iframe must be offset to the left
 * 		by the width of the left border. This should be a negative 
 *      number representing the border-left-width. If a number is 
 * 		is used here, pixels will be assumed. Otherwise, be sure
 *		to specify a unit. An expression could also be used. 
 * 		By default the value is "auto" which will use an expression 
 * 		to get the border-left-width if it is in pixels.
 * @option String|Number width This is the width of the iframe. If
 *		a number is used here, pixels will be assume. Otherwise, be sure
 * 		to specify a unit. An experssion could also be used.
 *		By default the value is "auto" which will use an experssion
 * 		to get the offsetWidth.
 * @option String|Number height This is the height of the iframe. If
 *		a number is used here, pixels will be assume. Otherwise, be sure
 * 		to specify a unit. An experssion could also be used.
 *		By default the value is "auto" which will use an experssion
 * 		to get the offsetHeight.
 * @option Boolean opacity This is a boolean representing whether or not
 * 		to use opacity. If set to true, the opacity of 0 is applied. If
 *		set to false, the opacity filter is not applied. Default: true.
 * @option String src This setting is provided so that one could change 
 *		the src of the iframe to whatever they need.
 *		Default: "javascript:false;"
 *
 * @name bgiframe
 * @type jQuery
 * @cat Plugins/bgiframe
 * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 */
$.fn.bgIframe = $.fn.bgiframe = function(s) {
	// This is only for IE6
	if ( $.browser.msie && /6.0/.test(navigator.userAgent) ) {
		s = $.extend({
			top     : 'auto', // auto == .currentStyle.borderTopWidth
			left    : 'auto', // auto == .currentStyle.borderLeftWidth
			width   : 'auto', // auto == offsetWidth
			height  : 'auto', // auto == offsetHeight
			opacity : true,
			src     : 'javascript:false;'
		}, s || {});
		var prop = function(n){return n&&n.constructor==Number?n+'px':n;},
		    html = '<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+
		               'style="display:block;position:absolute;z-index:-1;'+
			               (s.opacity !== false?'filter:Alpha(Opacity=\'0\');':'')+
					       'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+
					       'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+
					       'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+
					       'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+
					'"/>';
		return this.each(function() {
			if ( $('> iframe.bgiframe', this).length == 0 )
				this.insertBefore( document.createElement(html), this.firstChild );
		});
	}
	return this;
};

})(jQuery);/**
 * Interface Elements for jQuery
 * utility function
 *
 * http://interface.eyecon.ro
 *
 * Copyright (c) 2006 Stefan Petre
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 *
 */

jQuery.iUtil = {
	getPos : function (e)
	{
		var pos = jQuery.iUtil.getPositionLite(e);
		var size = jQuery.iUtil.getSizeLite(e);
		return {x:pos.x, y:pos.y, w:size.wb, h:size.hb};
	},
	getPosition : function(e)
	{
		var x = 0;
		var y = 0;
		var es = e.style;
		var restoreStyles = false;
		if (jQuery(e).css('display') == 'none') {
			var oldVisibility = es.visibility;
			var oldPosition = es.position;
			restoreStyles = true;
			es.visibility = 'hidden';
			es.display = 'block';
			es.position = 'absolute';
		}
		var el = e;
		while (el){
			x += el.offsetLeft + (el.currentStyle && !jQuery.browser.opera ?parseInt(el.currentStyle.borderLeftWidth)||0:0);
			y += el.offsetTop + (el.currentStyle && !jQuery.browser.opera ?parseInt(el.currentStyle.borderTopWidth)||0:0);
			el = el.offsetParent;
		}
		el = e;
		while (el && el.tagName  && el.tagName.toLowerCase() != 'body')
		{
			x -= el.scrollLeft||0;
			y -= el.scrollTop||0;
			el = el.parentNode;
		}
		if (restoreStyles == true) {
			es.display = 'none';
			es.position = oldPosition;
			es.visibility = oldVisibility;
		}
		return {x:x, y:y};
	},
	getPositionLite : function(el)
	{
		var x = 0, y = 0;
		while(el) {
			x += el.offsetLeft || 0;
			y += el.offsetTop || 0;
			el = el.offsetParent;
		}
		return {x:x, y:y};
	},
	getSize : function(e)
	{
		var w = jQuery.css(e,'width');
		var h = jQuery.css(e,'height');
		var wb = 0;
		var hb = 0;
		var es = e.style;
		if (jQuery(e).css('display') != 'none') {
			wb = e.offsetWidth;
			hb = e.offsetHeight;
		} else {
			var oldVisibility = es.visibility;
			var oldPosition = es.position;
			es.visibility = 'hidden';
			es.display = 'block';
			es.position = 'absolute';
			wb = e.offsetWidth;
			hb = e.offsetHeight;
			es.display = 'none';
			es.position = oldPosition;
			es.visibility = oldVisibility;
		}
		return {w:w, h:h, wb:wb, hb:hb};
	},
	getSizeLite : function(el)
	{
		return {
			wb:el.offsetWidth||0,
			hb:el.offsetHeight||0
		};
	},
	getClient : function(e)
	{
		var h, w, de;
		if (e) {
			w = e.clientWidth;
			h = e.clientHeight;
		} else {
			de = document.documentElement;
			w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
			h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
		}
		return {w:w,h:h};
	},
	getScroll : function (e)
	{
		var t=0, l=0, w=0, h=0, iw=0, ih=0;
		if (e && e.nodeName.toLowerCase() != 'body') {
			t = e.scrollTop;
			l = e.scrollLeft;
			w = e.scrollWidth;
			h = e.scrollHeight;
			iw = 0;
			ih = 0;
		} else  {
			if (document.documentElement) {
				t = document.documentElement.scrollTop;
				l = document.documentElement.scrollLeft;
				w = document.documentElement.scrollWidth;
				h = document.documentElement.scrollHeight;
			} else if (document.body) {
				t = document.body.scrollTop;
				l = document.body.scrollLeft;
				w = document.body.scrollWidth;
				h = document.body.scrollHeight;
			}
			iw = self.innerWidth||document.documentElement.clientWidth||document.body.clientWidth||0;
			ih = self.innerHeight||document.documentElement.clientHeight||document.body.clientHeight||0;
		}
		return { t: t, l: l, w: w, h: h, iw: iw, ih: ih };
	},
	getMargins : function(e, toInteger)
	{
		var el = jQuery(e);
		var t = el.css('marginTop') || '';
		var r = el.css('marginRight') || '';
		var b = el.css('marginBottom') || '';
		var l = el.css('marginLeft') || '';
		if (toInteger)
			return {
				t: parseInt(t)||0,
				r: parseInt(r)||0,
				b: parseInt(b)||0,
				l: parseInt(l)
			};
		else
			return {t: t, r: r,	b: b, l: l};
	},
	getPadding : function(e, toInteger)
	{
		var el = jQuery(e);
		var t = el.css('paddingTop') || '';
		var r = el.css('paddingRight') || '';
		var b = el.css('paddingBottom') || '';
		var l = el.css('paddingLeft') || '';
		if (toInteger)
			return {
				t: parseInt(t)||0,
				r: parseInt(r)||0,
				b: parseInt(b)||0,
				l: parseInt(l)
			};
		else
			return {t: t, r: r,	b: b, l: l};
	},
	getBorder : function(e, toInteger)
	{
		var el = jQuery(e);
		var t = el.css('borderTopWidth') || '';
		var r = el.css('borderRightWidth') || '';
		var b = el.css('borderBottomWidth') || '';
		var l = el.css('borderLeftWidth') || '';
		if (toInteger)
			return {
				t: parseInt(t)||0,
				r: parseInt(r)||0,
				b: parseInt(b)||0,
				l: parseInt(l)||0
			};
		else
			return {t: t, r: r,	b: b, l: l};
	},
	getPointer : function(event)
	{
		var x = event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)) || 0;
		var y = event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop)) || 0;
		return {x:x, y:y};
	},
	traverseDOM : function(nodeEl, func)
	{
		func(nodeEl);
		nodeEl = nodeEl.firstChild;
		while(nodeEl){
			jQuery.iUtil.traverseDOM(nodeEl, func);
			nodeEl = nodeEl.nextSibling;
		}
	},
	purgeEvents : function(nodeEl)
	{
		jQuery.iUtil.traverseDOM(
			nodeEl,
			function(el)
			{
				for(var attr in el){
					if(typeof el[attr] === 'function') {
						el[attr] = null;
					}
				}
			}
		);
	},
	centerEl : function(el, axis)
	{
		var clientScroll = jQuery.iUtil.getScroll();
		var windowSize = jQuery.iUtil.getSize(el);
		if (!axis || axis == 'vertically')
			jQuery(el).css(
				{
					top: clientScroll.t + ((Math.max(clientScroll.h,clientScroll.ih) - clientScroll.t - windowSize.hb)/2) + 'px'
				}
			);
		if (!axis || axis == 'horizontally')
			jQuery(el).css(
				{
					left:	clientScroll.l + ((Math.max(clientScroll.w,clientScroll.iw) - clientScroll.l - windowSize.wb)/2) + 'px'
				}
			);
	},
	fixPNG : function (el, emptyGIF) {
		var images = jQuery('img[src*="png"]', el||document), png;
		images.each( function() {
			png = this.src;				
			this.src = emptyGIF;
			this.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + png + "')";
		});
	}
};

// Helper function to support older browsers!
[].indexOf || (Array.prototype.indexOf = function(v, n){
	n = (n == null) ? 0 : n;
	var m = this.length;
	for (var i=n; i<m; i++)
		if (this[i] == v)
			return i;
	return -1;
});
/**
 * Interface Elements for jQuery
 * Draggable
 *
 * http://interface.eyecon.ro
 *
 * Copyright (c) 2006 Stefan Petre
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 */
/**
 * Create a draggable element with a number of advanced options including callback, Google Maps type draggables,
 * reversion, ghosting, and grid dragging.
 *
 * @name Draggable
 * @descr Creates draggable elements that can be moved across the page.
 * @param Hash hash A hash of parameters. All parameters are optional.
 * @option String handle (optional) The jQuery selector matching the handle that starts the draggable
 * @option DOMElement handle (optional) The DOM Element of the handle that starts the draggable
 * @option Boolean revert (optional) When true, on stop-drag the element returns to initial position
 * @option Boolean ghosting (optional) When true, a copy of the element is moved
 * @option Integer zIndex (optional) zIndex depth for the element while it is being dragged
 * @option Float opacity (optional) A number between 0 and 1 that indicates the opacity of the element while being dragged
 * @option Integer grid (optional) (optional) A number of pixels indicating the grid that the element should snap to
 * @option Array grid (optional) A number of x-pixels and y-pixels indicating the grid that the element should snap to
 * @option Integer fx (optional) Duration for the effect (like ghosting or revert) applied to the draggable
 * @option String containment (optional) Define the zone where the draggable can be moved. 'parent' moves it inside parent
 *                           element, while 'document' prevents it from leaving the document and forcing additional
 *                           scrolling
 * @option Array containment An 4-element array (left, top, width, height) indicating the containment of the element
 * @option String axis (optional) Set an axis: vertical (with 'vertically') or horizontal (with 'horizontally')
 * @option Function onStart (optional) Callback function triggered when the dragging starts
 * @option Function onStop (optional) Callback function triggered when the dragging stops
 * @option Function onChange (optional) Callback function triggered when the dragging stop *and* the element was moved at least
 *                          one pixel
 * @option Function onDrag (optional) Callback function triggered while the element is dragged. Receives two parameters: x and y
 *                        coordinates. You can return an object with new coordinates {x: x, y: y} so this way you can
 *                        interact with the dragging process (for instance, build your containment)
 * @option Boolean insideParent Forces the element to remain inside its parent when being dragged (like Google Maps)
 * @option Integer snapDistance (optional) The element is not moved unless it is dragged more than snapDistance. You can prevent
 *                             accidental dragging and keep regular clicking enabled (for links or form elements,
 *                             for instance)
 * @option Object cursorAt (optional) The dragged element is moved to the cursor position with the offset specified. Accepts value
 *                        for top, left, right and bottom offset. Basically, this forces the cursor to a particular
 *                        position during the entire drag operation.
 * @option Boolean autoSize (optional) When true, the drag helper is resized to its content, instead of the dragged element's sizes
 * @option String frameClass (optional) When is set the cloned element is hidden so only a frame is dragged
 * @type jQuery
 * @cat Plugins/Interface
 * @author Stefan Petre
 */

jQuery.iDrag =	{
	helper : null,
	dragged: null,
	destroy : function()
	{
		return this.each(
			function ()
			{
				if (this.isDraggable) {
					this.dragCfg.dhe.unbind('mousedown', jQuery.iDrag.draginit);
					this.dragCfg = null;
					this.isDraggable = false;
					if(jQuery.browser.msie) {
						this.unselectable = "off";
					} else {
						this.style.MozUserSelect = '';
						this.style.KhtmlUserSelect = '';
						this.style.userSelect = '';
					}
				}
			}
		);
	},
	draginit : function (e,self,fromselect)
	{
		if(window.event)
		{
			if(window.event.button != 1)	return;						// if not a left click
		}
		else
		{
			if(e.which != 1)	return;									// if not a left click
		}

		if(!self)
		{
			var self = this;
		}
		if (jQuery.iDrag.dragged != null) {
			jQuery.iDrag.dragstop(e);
			return false;
		}
		var elm = self.dragElem;
		jQuery(document)
			.bind('mousemove', jQuery.iDrag.dragmove)
			.bind('mouseup', jQuery.iDrag.dragstop);
		elm.dragCfg.pointer = jQuery.iUtil.getPointer(e);
		elm.dragCfg.currentPointer = elm.dragCfg.pointer;
		elm.dragCfg.init = false;
		elm.dragCfg.fromHandler = self != self.dragElem;
		elm.fromselect = fromselect ? true:false;

		jQuery.iDrag.dragged = elm;
		if (elm.dragCfg.si && self != self.dragElem) {
				parentPos = jQuery.iUtil.getPosition(elm.parentNode);
				sliderSize = jQuery.iUtil.getSize(elm);
				sliderPos = {
					x : parseInt(jQuery.css(elm,'left')) || 0,
					y : parseInt(jQuery.css(elm,'top')) || 0
				};
				dx = elm.dragCfg.currentPointer.x - parentPos.x - sliderSize.wb/2 - sliderPos.x;
				dy = elm.dragCfg.currentPointer.y - parentPos.y - sliderSize.hb/2 - sliderPos.y;
				jQuery.iSlider.dragmoveBy(elm, [dx, dy]);
		}
		return jQuery.selectKeyHelper||false;
	},

	dragstart : function(e)
	{
		var elm = jQuery.iDrag.dragged;
		elm.dragCfg.init = true;

		var dEs = elm.style;

		elm.dragCfg.oD = jQuery.css(elm,'display');
		elm.dragCfg.oP = jQuery.css(elm,'position');
		if (!elm.dragCfg.initialPosition)
			elm.dragCfg.initialPosition = elm.dragCfg.oP;

		elm.dragCfg.oR = {
			x : parseInt(jQuery.css(elm,'left')) || 0,
			y : parseInt(jQuery.css(elm,'top')) || 0
		};
		elm.dragCfg.diffX = 0;
		elm.dragCfg.diffY = 0;
		if (jQuery.browser.msie) {
			var oldBorder = jQuery.iUtil.getBorder(elm, true);
			elm.dragCfg.diffX = oldBorder.l||0;
			elm.dragCfg.diffY = oldBorder.t||0;
		}

		elm.dragCfg.oC = jQuery.extend(
			jQuery.iUtil.getPosition(elm),
			jQuery.iUtil.getSize(elm)
		);
		if (elm.dragCfg.oP != 'relative' && elm.dragCfg.oP != 'absolute') {
			dEs.position = 'relative';
		}

		jQuery.iDrag.helper.empty();
		var clonedEl = $(elm).clone(true).get(0);

		jQuery(clonedEl).css(
			{
				display:	'block',
				left:		'0px',
				top: 		'0px'
			}
		);
		clonedEl.style.marginTop = '0';
		clonedEl.style.marginRight = '0';
		clonedEl.style.marginBottom = '0';
		clonedEl.style.marginLeft = '0';
		jQuery.iDrag.helper.append(clonedEl);

		var dhs = jQuery.iDrag.helper.get(0).style;

		if (elm.dragCfg.autoSize) {
			dhs.width = 'auto';
			dhs.height = 'auto';
		} else {
			dhs.height = elm.dragCfg.oC.hb + 'px';
			dhs.width = elm.dragCfg.oC.wb + 'px';
		}

		dhs.display = 'block';
		dhs.marginTop = '0px';
		dhs.marginRight = '0px';
		dhs.marginBottom = '0px';
		dhs.marginLeft = '0px';

		//remeasure the clone to check if the size was changed by user's functions
		jQuery.extend(
			elm.dragCfg.oC,
			jQuery.iUtil.getSize(clonedEl)
		);

		if (elm.dragCfg.cursorAt) {
			if (elm.dragCfg.cursorAt.left) {
				elm.dragCfg.oR.x += elm.dragCfg.pointer.x - elm.dragCfg.oC.x - elm.dragCfg.cursorAt.left;
				elm.dragCfg.oC.x = elm.dragCfg.pointer.x - elm.dragCfg.cursorAt.left;
			}
			if (elm.dragCfg.cursorAt.top) {
				elm.dragCfg.oR.y += elm.dragCfg.pointer.y - elm.dragCfg.oC.y - elm.dragCfg.cursorAt.top;
				elm.dragCfg.oC.y = elm.dragCfg.pointer.y - elm.dragCfg.cursorAt.top;
			}
			if (elm.dragCfg.cursorAt.right) {
				elm.dragCfg.oR.x += elm.dragCfg.pointer.x - elm.dragCfg.oC.x -elm.dragCfg.oC.hb + elm.dragCfg.cursorAt.right;
				elm.dragCfg.oC.x = elm.dragCfg.pointer.x - elm.dragCfg.oC.wb + elm.dragCfg.cursorAt.right;
			}
			if (elm.dragCfg.cursorAt.bottom) {
				elm.dragCfg.oR.y += elm.dragCfg.pointer.y - elm.dragCfg.oC.y - elm.dragCfg.oC.hb + elm.dragCfg.cursorAt.bottom;
				elm.dragCfg.oC.y = elm.dragCfg.pointer.y - elm.dragCfg.oC.hb + elm.dragCfg.cursorAt.bottom;
			}
		}
		elm.dragCfg.nx = elm.dragCfg.oR.x;
		elm.dragCfg.ny = elm.dragCfg.oR.y;

		if (elm.dragCfg.insideParent || elm.dragCfg.containment == 'parent') {
			parentBorders = jQuery.iUtil.getBorder(elm.parentNode, true);
			elm.dragCfg.oC.x = elm.offsetLeft + (jQuery.browser.msie ? 0 : jQuery.browser.opera ? -parentBorders.l : parentBorders.l);
			elm.dragCfg.oC.y = elm.offsetTop + (jQuery.browser.msie ? 0 : jQuery.browser.opera ? -parentBorders.t : parentBorders.t);
			jQuery(elm.parentNode).append(jQuery.iDrag.helper.get(0));
		}
		if (elm.dragCfg.containment) {
			jQuery.iDrag.getContainment(elm);
			elm.dragCfg.onDragModifier.containment = jQuery.iDrag.fitToContainer;
		}

		if (elm.dragCfg.si) {
			jQuery.iSlider.modifyContainer(elm);
		}

		dhs.left = elm.dragCfg.oC.x - elm.dragCfg.diffX + 'px';
		dhs.top = elm.dragCfg.oC.y - elm.dragCfg.diffY + 'px';
		//resize the helper to fit the clone
		dhs.width = elm.dragCfg.oC.wb + 'px';
		dhs.height = elm.dragCfg.oC.hb + 'px';

		jQuery.iDrag.dragged.dragCfg.prot = false;

		if (elm.dragCfg.gx) {
			elm.dragCfg.onDragModifier.grid = jQuery.iDrag.snapToGrid;
		}
		if (elm.dragCfg.zIndex != false) {
			jQuery.iDrag.helper.css('zIndex', elm.dragCfg.zIndex);
		}
		if (elm.dragCfg.opacity) {
			jQuery.iDrag.helper.css('opacity', elm.dragCfg.opacity);
			if (window.ActiveXObject) {
				jQuery.iDrag.helper.css('filter', 'alpha(opacity=' + elm.dragCfg.opacity * 100 + ')');
			}
		}

		if(elm.dragCfg.frameClass) {
			jQuery.iDrag.helper.addClass(elm.dragCfg.frameClass);
			jQuery.iDrag.helper.get(0).firstChild.style.display = 'none';
		}
		if (elm.dragCfg.onStart)
			elm.dragCfg.onStart.apply(elm, [clonedEl, elm.dragCfg.oR.x, elm.dragCfg.oR.y]);
		if (jQuery.iDrop && jQuery.iDrop.count > 0 ){
			jQuery.iDrop.highlight(elm);
		}
		if (elm.dragCfg.ghosting == false) {
			dEs.display = 'none';
		}
		return false;
	},

	getContainment : function(elm)
	{
		if (elm.dragCfg.containment.constructor == String) {
			if (elm.dragCfg.containment == 'parent') {
				elm.dragCfg.cont = jQuery.extend(
					{x:0,y:0},
					jQuery.iUtil.getSize(elm.parentNode)
				);
				var contBorders = jQuery.iUtil.getBorder(elm.parentNode, true);
				elm.dragCfg.cont.w = elm.dragCfg.cont.wb - contBorders.l - contBorders.r;
				elm.dragCfg.cont.h = elm.dragCfg.cont.hb - contBorders.t - contBorders.b;
			} else if (elm.dragCfg.containment == 'document') {
				var clnt = jQuery.iUtil.getClient();
				elm.dragCfg.cont = {
					x : 0,
					y : 0,
					w : clnt.w,
					h : clnt.h
				};
			}
		} else if (elm.dragCfg.containment.constructor == Array) {
			elm.dragCfg.cont = {
				x : parseInt(elm.dragCfg.containment[0])||0,
				y : parseInt(elm.dragCfg.containment[1])||0,
				w : parseInt(elm.dragCfg.containment[2])||0,
				h : parseInt(elm.dragCfg.containment[3])||0
			};
		}
		elm.dragCfg.cont.dx = elm.dragCfg.cont.x - elm.dragCfg.oC.x;
		elm.dragCfg.cont.dy = elm.dragCfg.cont.y - elm.dragCfg.oC.y;
	},

	hidehelper : function(dragged)
	{
		if (dragged.dragCfg.insideParent || dragged.dragCfg.containment == 'parent') {
			jQuery('body', document).append(jQuery.iDrag.helper.get(0));
		}
		jQuery.iDrag.helper.empty().hide().css('opacity', 1);
		if (window.ActiveXObject) {
			jQuery.iDrag.helper.css('filter', 'alpha(opacity=100)');
		}
	},

	dragstop : function(e)
	{
		jQuery(document)
			.unbind('mousemove', jQuery.iDrag.dragmove)
			.unbind('mouseup', jQuery.iDrag.dragstop);

		if (jQuery.iDrag.dragged == null) {
			return;
		}
		var dragged = jQuery.iDrag.dragged;

		jQuery.iDrag.dragged = null;

		if (dragged.dragCfg.init == false)
		{
			if(!dragged.fromselect && pbx.selectable.controlkey)
			{
				if(!pbx.selectable.current)
				{
					pbx.selectable.current = dragged.parentNode;
				}
				pbx.selectable.unselect(dragged, pbx.selectable.current);
				pbx.selectable.stop(e);
			}
			return false;
		}

		if (dragged.dragCfg.so == true) {
			jQuery(dragged).css('position', dragged.dragCfg.oP);
		}

		var dEs = dragged.style;

		if (dragged.si) {
			alert('fgds');
			jQuery.iDrag.helper.css('cursor', 'move');
		}
		if(dragged.dragCfg.frameClass) {
			jQuery.iDrag.helper.removeClass(dragged.dragCfg.frameClass);
		}

		if (dragged.dragCfg.revert == false) {
			if (dragged.dragCfg.fx > 0) {
				if (!dragged.dragCfg.axis || dragged.dragCfg.axis == 'horizontally') {
					var x = new jQuery.fx(dragged,{duration:dragged.dragCfg.fx}, 'left');
					x.custom(dragged.dragCfg.oR.x,dragged.dragCfg.nRx);
				}
				if (!dragged.dragCfg.axis || dragged.dragCfg.axis == 'vertically') {
					var y = new jQuery.fx(dragged,{duration:dragged.dragCfg.fx}, 'top');
					y.custom(dragged.dragCfg.oR.y,dragged.dragCfg.nRy);
				}
			} else if(!dragged.dragCfg.so) {
				if (!dragged.dragCfg.axis || dragged.dragCfg.axis == 'horizontally')
					dragged.style.left = dragged.dragCfg.nRx + 'px';
				if (!dragged.dragCfg.axis || dragged.dragCfg.axis == 'vertically')
					dragged.style.top = dragged.dragCfg.nRy - (dragged.dragCfg.scrollOffset?$(window).scrollTop():0) + 'px';
			}
			jQuery.iDrag.hidehelper(dragged);
			if (dragged.dragCfg.ghosting == false) {
				jQuery(dragged).css('display', dragged.dragCfg.oD);
			}
		} else if (dragged.dragCfg.fx > 0) {
			dragged.dragCfg.prot = true;
			var dh = false;
			if(jQuery.iDrop && jQuery.iSort && dragged.dragCfg.so) {
				dh = jQuery.iUtil.getPosition(jQuery.iSort.helper.get(0));
			}
			jQuery.iDrag.helper.animate(
				{
					left : dh ? dh.x : dragged.dragCfg.oC.x,
					top : dh ? dh.y : dragged.dragCfg.oC.y
				},
				dragged.dragCfg.fx,
				function()
				{
					dragged.dragCfg.prot = false;
					if (dragged.dragCfg.ghosting == false) {
						dragged.style.display = dragged.dragCfg.oD;
					}
					jQuery.iDrag.hidehelper(dragged);
				}
			);
		} else {
			jQuery.iDrag.hidehelper(dragged);
			if (dragged.dragCfg.ghosting == false) {
				jQuery(dragged).css('display', dragged.dragCfg.oD);
			}
		}

		if (jQuery.iDrop && jQuery.iDrop.count > 0 ){
			jQuery.iDrop.checkdrop(dragged);
		}
		if (jQuery.iSort && dragged.dragCfg.so) {
			jQuery.iSort.check(dragged);
		}
		if (dragged.dragCfg.onChange && (dragged.dragCfg.nRx != dragged.dragCfg.oR.x || dragged.dragCfg.nRy != dragged.dragCfg.oR.y)){
			dragged.dragCfg.onChange.apply(dragged, dragged.dragCfg.lastSi||[0,0,dragged.dragCfg.nRx,dragged.dragCfg.nRy]);
		}
		if (dragged.dragCfg.onStop)
			dragged.dragCfg.onStop.apply(dragged);
		return false;
	},

	snapToGrid : function(x, y, dx, dy)
	{
		if (dx != 0)
			dx = parseInt((dx + (this.dragCfg.gx * dx/Math.abs(dx))/2)/this.dragCfg.gx) * this.dragCfg.gx;
		if (dy != 0)
			dy = parseInt((dy + (this.dragCfg.gy * dy/Math.abs(dy))/2)/this.dragCfg.gy) * this.dragCfg.gy;
		return {
			dx : dx,
			dy : dy,
			x: 0,
			y: 0
		};
	},

	fitToContainer : function(x, y, dx, dy)
	{
		dx = Math.min(
				Math.max(dx,this.dragCfg.cont.dx),
				this.dragCfg.cont.w + this.dragCfg.cont.dx - this.dragCfg.oC.wb
			);
		dy = Math.min(
				Math.max(dy,this.dragCfg.cont.dy),
				this.dragCfg.cont.h + this.dragCfg.cont.dy - this.dragCfg.oC.hb
			);

		return {
			dx : dx,
			dy : dy,
			x: 0,
			y: 0
		}
	},

	dragmove : function(e)
	{
		if (jQuery.iDrag.dragged == null || jQuery.iDrag.dragged.dragCfg.prot == true) {
			return;
		}

		var dragged = jQuery.iDrag.dragged;

		dragged.dragCfg.currentPointer = jQuery.iUtil.getPointer(e);
		if (dragged.dragCfg.init == false) {
			distance = Math.sqrt(Math.pow(dragged.dragCfg.pointer.x - dragged.dragCfg.currentPointer.x, 2) + Math.pow(dragged.dragCfg.pointer.y - dragged.dragCfg.currentPointer.y, 2));
			if (distance < dragged.dragCfg.snapDistance){
				return;
			} else {
				jQuery.iDrag.dragstart(e);
			}
		}

		var dx = dragged.dragCfg.currentPointer.x - dragged.dragCfg.pointer.x;
		var dy = dragged.dragCfg.currentPointer.y - dragged.dragCfg.pointer.y + (dragged.dragCfg.scrollOffset?$(window).scrollTop():0);

		for (var i in dragged.dragCfg.onDragModifier) {
			var newCoords = dragged.dragCfg.onDragModifier[i].apply(dragged, [dragged.dragCfg.oR.x + dx, dragged.dragCfg.oR.y + dy, dx, dy]);
			if (newCoords && newCoords.constructor == Object) {
				dx = i != 'user' ? newCoords.dx : (newCoords.x - dragged.dragCfg.oR.x);
				dy = i != 'user' ? newCoords.dy : (newCoords.y - dragged.dragCfg.oR.y);
			}
		}

		dragged.dragCfg.nx = dragged.dragCfg.oC.x + dx - dragged.dragCfg.diffX;
		dragged.dragCfg.ny = dragged.dragCfg.oC.y + dy - dragged.dragCfg.diffY;

		if (dragged.dragCfg.si && (dragged.dragCfg.onSlide || dragged.dragCfg.onChange)) {
			jQuery.iSlider.onSlide(dragged, dragged.dragCfg.nx, dragged.dragCfg.ny);
		}



		if (!dragged.dragCfg.axis || dragged.dragCfg.axis == 'horizontally') {
			dragged.dragCfg.nRx = dragged.dragCfg.oR.x + dx;
			jQuery.iDrag.helper.get(0).style.left = dragged.dragCfg.nx + 'px';
		}
		if (!dragged.dragCfg.axis || dragged.dragCfg.axis == 'vertically') {
			dragged.dragCfg.nRy = dragged.dragCfg.oR.y + dy;
			jQuery.iDrag.helper.get(0).style.top = dragged.dragCfg.ny + 'px';
		}
		if(dragged.dragCfg.onDrag)
			dragged.dragCfg.onDrag.apply(dragged, [dragged.dragCfg.oR.x + dx, dragged.dragCfg.oR.y + dy]);
		if (jQuery.iDrop && jQuery.iDrop.count > 0 ){
			jQuery.iDrop.checkhover(dragged);
		}
		return false;
	},

	build : function(o)
	{
		if (!jQuery.iDrag.helper) {
			jQuery('body',document).append('<div id="pbx_draghelper"></div>');
			jQuery.iDrag.helper = jQuery('#pbx_draghelper');
			var el = jQuery.iDrag.helper.get(0);
			var els = el.style;
			els.position = 'absolute';
			els.display = 'none';
			//els.cursor = 'move';
			els.listStyle = 'none';
			els.overflow = 'hidden';
			if (window.ActiveXObject) {
				el.unselectable = "on";
			} else {
				els.mozUserSelect = 'none';
				els.userSelect = 'none';
				els.KhtmlUserSelect = 'none';
				//els.cursor = '-moz-grabbing !important';
			}
		}
		if (!o) {
			o = {};
		}
		return this.each(
			function()
			{
				if (this.isDraggable || !jQuery.iUtil)
					return;
				if (window.ActiveXObject && navigator.userAgent.match(/MSIE (\d+?\.\d+?);/)[1] == '6.0')
				{
					this.onselectstart = function(){return false;};
					this.ondragstart = function(){return false;};
				}
				var el = this;
				var dhe = o.handle ? jQuery(this).find(o.handle) : jQuery(this);
				if(jQuery.browser.msie) {
					dhe.each(
						function()
						{
							this.unselectable = "on";
						}
					);
				} else {
					dhe.css('-moz-user-select', 'none');
					dhe.css('user-select', 'none');
					dhe.css('-khtml-user-select', 'none');
				}
				this.dragCfg = {
					dhe: dhe,
					revert : o.revert ? true : false,
					ghosting : o.ghosting ? true : false,
					so : o.so ? o.so : false,
					si : o.si ? o.si : false,
					insideParent : o.insideParent ? o.insideParent : false,
					zIndex : o.zIndex ? parseInt(o.zIndex)||0 : false,
					opacity : o.opacity ? parseFloat(o.opacity) : false,
					fx : parseInt(o.fx)||null,
					hpc : o.hpc ? o.hpc : false,
					onDragModifier : {},
					pointer : {},
					onStart : o.onStart && o.onStart.constructor == Function ? o.onStart : false,
					onStop : o.onStop && o.onStop.constructor == Function ? o.onStop : false,
					onChange : o.onChange && o.onChange.constructor == Function ? o.onChange : false,
					axis : /vertically|horizontally/.test(o.axis) ? o.axis : false,
					snapDistance : o.snapDistance ? parseInt(o.snapDistance)||0 : 0,
					scrollOffset : o.scrollOffset ? true : false,
					cursorAt: o.cursorAt ? o.cursorAt : false,
					autoSize : o.autoSize ? true : false,
					frameClass : o.frameClass || false
				};
				if (o.onDragModifier && o.onDragModifier.constructor == Function)
					this.dragCfg.onDragModifier.user = o.onDragModifier;
				if (o.onDrag && o.onDrag.constructor == Function)
					this.dragCfg.onDrag = o.onDrag;
				if (o.containment && ((o.containment.constructor == String && (o.containment == 'parent' || o.containment == 'document')) || (o.containment.constructor == Array && o.containment.length == 4) )) {
					this.dragCfg.containment = o.containment;
				}
				if(o.fractions) {
					this.dragCfg.fractions = o.fractions;
				}
				if(o.grid){
					if(typeof o.grid == 'number'){
						this.dragCfg.gx = parseInt(o.grid)||1;
						this.dragCfg.gy = parseInt(o.grid)||1;
					} else if (o.grid.length == 2) {
						this.dragCfg.gx = parseInt(o.grid[0])||1;
						this.dragCfg.gy = parseInt(o.grid[1])||1;
					}
				}
				if (o.onSlide && o.onSlide.constructor == Function) {
					this.dragCfg.onSlide = o.onSlide;
				}

				this.isDraggable = true;
				dhe.each(
					function(){
						this.dragElem = el;
					}
				);
				dhe.bind('mousedown', jQuery.iDrag.draginit);
			}
		)
	}
};

/**
 * Destroy an existing draggable on a collection of elements
 *
 * @name DraggableDestroy
 * @descr Destroy a draggable
 * @type jQuery
 * @cat Plugins/Interface
 * @example $('#drag2').DraggableDestroy();
 */

jQuery.fn.extend(
	{
		DraggableDestroy : jQuery.iDrag.destroy,
		Draggable : jQuery.iDrag.build,
		DragInit : jQuery.iDrag.draginit
	}
);
/**
 * Interface Elements for jQuery
 * Droppables
 * 
 * http://interface.eyecon.ro
 * 
 * Copyright (c) 2006 Stefan Petre
 * Dual licensed under the MIT (MIT-LICENSE.txt) 
 * and GPL (GPL-LICENSE.txt) licenses.
 *   
 *
 */

/**
 * With the Draggables plugin, Droppable allows you to create drop zones for draggable elements.
 *
 * @name Droppable
 * @cat Plugins/Interface
 * @param Hash options A hash of options
 * @option String accept The class name for draggables to get accepted by the droppable (mandatory)
 * @option String activeclass When an acceptable draggable is moved, the droppable gets this class
 * @option String hoverclass When an acceptable draggable is inside the droppable, the droppable gets
 *                           this class
 * @option String tolerance  Choose from 'pointer', 'intersect', or 'fit'. The pointer options means
 *                           that the pointer must be inside the droppable in order for the draggable
 *                           to be dropped. The intersect option means that the draggable must intersect
 *                           the droppable. The fit option means that the entire draggable must be
 *                           inside the droppable.
 * @option Function onDrop   When an acceptable draggable is dropped on a droppable, this callback is
 *                           called. It passes the draggable DOMElement as a parameter.
 * @option Function onHover  When an acceptable draggable is hovered over a droppable, this callback
 *                           is called. It passes the draggable DOMElement as a parameter.
 * @option Function onOut    When an acceptable draggable leaves a droppable, this callback is called.
 *                           It passes the draggable DOMElement as a parameter.
 * @example                  $('#dropzone1').Droppable(
 *                             {
 *                               accept : 'dropaccept', 
 *                               activeclass: 'dropzoneactive', 
 *                               hoverclass:	'dropzonehover',
 *                               ondrop:	function (drag) {
 *                                              alert(this); //the droppable
 *                                              alert(drag); //the draggable
 *                                        },
 *                               fit: true
 *                             }
 *                           )
 */

jQuery.iDrop = {
	fit : function (zonex, zoney, zonew, zoneh)
	{
		return 	zonex <= jQuery.iDrag.dragged.dragCfg.nx && 
				(zonex + zonew) >= (jQuery.iDrag.dragged.dragCfg.nx + jQuery.iDrag.dragged.dragCfg.oC.w) &&
				zoney <= jQuery.iDrag.dragged.dragCfg.ny && 
				(zoney + zoneh) >= (jQuery.iDrag.dragged.dragCfg.ny + jQuery.iDrag.dragged.dragCfg.oC.h) ? true :false;
	},
	intersect : function (zonex, zoney, zonew, zoneh)
	{
		return 	! ( zonex > (jQuery.iDrag.dragged.dragCfg.nx + jQuery.iDrag.dragged.dragCfg.oC.w)
				|| (zonex + zonew) < jQuery.iDrag.dragged.dragCfg.nx 
				|| zoney > (jQuery.iDrag.dragged.dragCfg.ny + jQuery.iDrag.dragged.dragCfg.oC.h) 
				|| (zoney + zoneh) < jQuery.iDrag.dragged.dragCfg.ny
				) ? true :false;
	},
	pointer : function (zonex, zoney, zonew, zoneh)
	{
		return	zonex < jQuery.iDrag.dragged.dragCfg.currentPointer.x
				&& (zonex + zonew) > jQuery.iDrag.dragged.dragCfg.currentPointer.x 
				&& zoney < jQuery.iDrag.dragged.dragCfg.currentPointer.y 
				&& (zoney + zoneh) > jQuery.iDrag.dragged.dragCfg.currentPointer.y
				? true :false;
	},
	overzone : false,
	highlighted : {},
	count : 0,
	zones : {},
	
	highlight : function (elm)
	{
		if (jQuery.iDrag.dragged == null) {
			return;
		}
		var i;
		jQuery.iDrop.highlighted = {};
		var oneIsSortable = false;
		for (i in jQuery.iDrop.zones) {
			if (jQuery.iDrop.zones[i] != null) {
				var iEL = jQuery.iDrop.zones[i].get(0);
				if (jQuery(jQuery.iDrag.dragged).is('.' + iEL.dropCfg.a)) {
					if (iEL.dropCfg.m == false) {
						iEL.dropCfg.p = jQuery.extend(
							jQuery.iUtil.getPositionLite(iEL),
							jQuery.iUtil.getSizeLite(iEL)
						);//jQuery.iUtil.getPos(iEL);
						iEL.dropCfg.m = true;
					}
					if (iEL.dropCfg.ac) {
						jQuery.iDrop.zones[i].addClass(iEL.dropCfg.ac);
					}
					jQuery.iDrop.highlighted[i] = jQuery.iDrop.zones[i];
					//if (jQuery.iSort && jQuery.iDrag.dragged.dragCfg.so) {
					if (jQuery.iSort && iEL.dropCfg.s && jQuery.iDrag.dragged.dragCfg.so) {
						iEL.dropCfg.el = jQuery('.' + iEL.dropCfg.a, iEL);
						elm.style.display = 'none';
						jQuery.iSort.measure(iEL);
						iEL.dropCfg.os = jQuery.iSort.serialize(jQuery.attr(iEL, 'id')).hash;
						elm.style.display = elm.dragCfg.oD;
						oneIsSortable = true;
					}
					if (iEL.dropCfg.onActivate) {
						iEL.dropCfg.onActivate.apply(jQuery.iDrop.zones[i].get(0), [jQuery.iDrag.dragged]);
					}
				}
			}
		}
		//if (jQuery.iSort && jQuery.iDrag.dragged.dragCfg.so) {
		if (oneIsSortable) {
			jQuery.iSort.start();
		}
	},
	/**
	 * remeasure the droppable
	 * 
	 * useful when the positions/dimensions for droppables 
	 * are changed while dragging a element
	 * 
	 * this works for sortables too but with a greate processor 
	 * penality because remeasures each sort items too
	 */
	remeasure : function()
	{
		jQuery.iDrop.highlighted = {};
		for (i in jQuery.iDrop.zones) {
			if (jQuery.iDrop.zones[i] != null) {
				var iEL = jQuery.iDrop.zones[i].get(0);
				if (jQuery(jQuery.iDrag.dragged).is('.' + iEL.dropCfg.a)) {
					iEL.dropCfg.p = jQuery.extend(
						jQuery.iUtil.getPositionLite(iEL),
						jQuery.iUtil.getSizeLite(iEL)
					);
					if (iEL.dropCfg.ac) {
						jQuery.iDrop.zones[i].addClass(iEL.dropCfg.ac);
					}
					jQuery.iDrop.highlighted[i] = jQuery.iDrop.zones[i];
					
					if (jQuery.iSort && iEL.dropCfg.s && jQuery.iDrag.dragged.dragCfg.so) {
						iEL.dropCfg.el = jQuery('.' + iEL.dropCfg.a, iEL);
						elm.style.display = 'none';
						jQuery.iSort.measure(iEL);
						elm.style.display = elm.dragCfg.oD;
					}
				}
			}
		}
	},
	
	checkhover : function (e)
	{
		if (jQuery.iDrag.dragged == null) {
			return;
		}
		jQuery.iDrop.overzone = false;
		var i;
		var applyOnHover = false;
		var hlt = 0;
		for (i in jQuery.iDrop.highlighted)
		{
			var iEL = jQuery.iDrop.highlighted[i].get(0);
			if ( 
					jQuery.iDrop.overzone == false
					 && 
					jQuery.iDrop[iEL.dropCfg.t](
					 	iEL.dropCfg.p.x, 
						iEL.dropCfg.p.y, 
						iEL.dropCfg.p.wb, 
						iEL.dropCfg.p.hb
					)
					 
			) {
				if (iEL.dropCfg.hc && iEL.dropCfg.h == false) {
					jQuery.iDrop.highlighted[i].addClass(iEL.dropCfg.hc);
				}
				//chec if onHover function has to be called
				if (iEL.dropCfg.h == false &&iEL.dropCfg.onHover) {
					applyOnHover = true;
				}
				iEL.dropCfg.h = true;
				jQuery.iDrop.overzone = iEL;
				//if(jQuery.iSort && jQuery.iDrag.dragged.dragCfg.so) {
				if(jQuery.iSort && iEL.dropCfg.s && jQuery.iDrag.dragged.dragCfg.so) {
					jQuery.iSort.helper.get(0).className = iEL.dropCfg.shc;
					jQuery.iSort.checkhover(iEL);
				}
				hlt ++;
			} else if(iEL.dropCfg.h == true) {
				//onOut function
				if (iEL.dropCfg.onOut) {
					iEL.dropCfg.onOut.apply(iEL, [e, jQuery.iDrag.helper.get(0).firstChild, iEL.dropCfg.fx]);
				}
				if (iEL.dropCfg.hc) {
					jQuery.iDrop.highlighted[i].removeClass(iEL.dropCfg.hc);
				}
				iEL.dropCfg.h = false;
			}
		}
		if (jQuery.iSort && !jQuery.iDrop.overzone && jQuery.iDrag.dragged.so) {
			jQuery.iSort.helper.get(0).style.display = 'none';
			//jQuery('body').append(jQuery.iSort.helper.get(0));
		}
		//call onhover
		if(applyOnHover) {
			jQuery.iDrop.overzone.dropCfg.onHover.apply(jQuery.iDrop.overzone, [e, jQuery.iDrag.helper.get(0).firstChild]);
		}
	},
	checkdrop : function (e)
	{
		var i;
		for (i in jQuery.iDrop.highlighted) {
			var iEL = jQuery.iDrop.highlighted[i].get(0);
			if (iEL.dropCfg.ac) {
				jQuery.iDrop.highlighted[i].removeClass(iEL.dropCfg.ac);
			}
			if (iEL.dropCfg.hc) {
				jQuery.iDrop.highlighted[i].removeClass(iEL.dropCfg.hc);
			}
			if(iEL.dropCfg.s) {
				jQuery.iSort.changed[jQuery.iSort.changed.length] = i;
			}
			if (iEL.dropCfg.onDrop && iEL.dropCfg.h == true) {
				iEL.dropCfg.h = false;
				iEL.dropCfg.onDrop.apply(iEL, [e, iEL.dropCfg.fx]);
			}
			iEL.dropCfg.m = false;
			iEL.dropCfg.h  = false;
		}
		jQuery.iDrop.highlighted = {};
	},
	destroy : function()
	{
		return this.each(
			function()
			{
				if (this.isDroppable) {
					if (this.dropCfg.s) {
						id = jQuery.attr(this,'id');
						jQuery.iSort.collected[id] = null;
						jQuery('.' + this.dropCfg.a, this).DraggableDestroy();
					}
					jQuery.iDrop.zones['d' + this.idsa] = null;
					this.isDroppable = false;
					this.f = null;
				}
			}
		);
	},
	build : function (o)
	{
		return this.each(
			function()
			{
				if (this.isDroppable == true || !o.accept || !jQuery.iUtil || !jQuery.iDrag){
					return;
				}
				this.dropCfg = {
					a : o.accept,
					ac: o.activeclass||false, 
					hc:	o.hoverclass||false,
					shc: o.helperclass||false,
					onDrop:	o.ondrop||o.onDrop||false,
					onHover: o.onHover||o.onhover||false,
					onOut: o.onOut||o.onout||false,
					onActivate: o.onActivate||false,
					t: o.tolerance && ( o.tolerance == 'fit' || o.tolerance == 'intersect') ? o.tolerance : 'pointer',
					fx: o.fx ? o.fx : false,
					m: false,
					h: false
				};
				if (o.sortable == true && jQuery.iSort) {
					id = jQuery.attr(this,'id');
					jQuery.iSort.collected[id] = this.dropCfg.a;
					this.dropCfg.s = true;
					if(o.onChange) {
						this.dropCfg.onChange = o.onChange;
						this.dropCfg.os = jQuery.iSort.serialize(id).hash;
					}
				}
				this.isDroppable = true;
				this.idsa = parseInt(Math.random() * 10000);
				jQuery.iDrop.zones['d' + this.idsa] = jQuery(this);
				jQuery.iDrop.count ++;
			}
		);
	}
};

/**
 * Destroy an existing droppable on a collection of elements
 * 
 * @name DroppableDestroy
 * @descr Destroy a droppable
 * @type jQuery
 * @cat Plugins/Interface
 * @example $('#drag2').DroppableDestroy();
 */

jQuery.fn.extend(
	{
		DroppableDestroy : jQuery.iDrop.destroy,
		Droppable : jQuery.iDrop.build
	}
);

 
/**
 * Recalculate all Droppables
 *
 * @name $.recallDroppables
 * @type jQuery
 * @cat Plugins/Interface
 * @example $.recallDroppable();
 */

jQuery.recallDroppables = jQuery.iDrop.remeasure;(function($)
{
	var helper,		// the tooltip element
		tTitle,		// it's title part
		tBody,		// it's body part
		tUrl,		// it's url part
		current,	// the current tooltipped element
		oldTitle,	// the title of the current element, used for restoring
		tID,		// timeout id for delayed tooltips
		position;	// position of the helper (optionnal, accepteed: 'under')

	/*
	 * the public plugin method
	 */
	$.fn.tooltip = function(settings)
	{
		settings = $.extend({}, arguments.callee.defaults, settings);	// setup configuration

		if(!$('div#' + settings.container).length)
		{
			// create the helper, h3 for title, div for url
			var helper_tmp = $('<div id="' + settings.container + '"><h3></h3><p class="body"></p><p class="url"></p></div>')
				.hide()													// hide it at first
				.css({ position: 'absolute', zIndex: "5000" })			// move to top and position absolute, to let it follow the mouse
				.appendTo('body');										// add to document
		}

		var obj = settings.children ? $(this).children(settings.children):$(this);
		obj.each(	function()	// save settings into each element
				{
					this.tSettings = settings;
				})
		// bind events
		.bind("mouseover", save)
		.bind(settings.event, handle);
		return this;
	};

	$.fn.tooltipDestroy = function(settings)
	{
		helper = $('div#' + settings.container);
		helper.find('div#' + settings.container + '_content').html('');
		hide();
		settings = $.extend({}, $(this).tooltip.defaults, settings);	// setup configuration
		var obj = settings.children ? $(this).children(settings.children):$(this);
		obj.unbind("mouseover", save).unbind(settings.event, handle);
		return this;
	};

	/*
	 * main event handler to start showing tooltips
	 */
	function handle(event)
	{
		if(eval(this.tSettings.flag_active) === false || !pbx.performDisableCheck($(this)))
		{
			hide();
			return;
		}
		position = this.tSettings.position;
		if( this.tSettings.delay)				// show helper, either with timeout or on instant
		{
			tID = setTimeout(show, this.tSettings.delay);
		}
		else
		{
			show();
		}
		if(this.tSettings.track)				// if selected, update the helper position when the mouse moves
		{
			$('body').bind('mousemove', update);
		}
		update(event,this.tSettings.track);							// update at least once

		if(this.tSettings.track == true)
		{
			$(this).bind('mouseout', dohide);		// hide the helper when the mouse moves out of the element
		}
		$(this).bind('click', dohide);			// hide the helper when the mouse moves out of the element

	}

	/*
	 * save elements title before the tooltip is displayed
	 */
	function save()
	{
		helper = $('div#' + this.tSettings.container);
		// save references to title and url elements
		tTitle = $('h3', helper);
		tBody = $('.body', helper);
		tUrl = $('.url', helper);
		tLink = $('.pbx_bubble_link', helper);

		if(eval(this.tSettings.flag_active) == false)
		{
			hide();
			return;
		}
		if(this == current)		// if this is the current source, or it has no title (occurs with click event), stop
		{
			return;
		}
		current = this;							// save current

		var source = $(this),
		settings = this.tSettings;

		if(!title && settings.showTitle)
		{
			// save title, remove from element and set to helper
			var title = oldTitle = source.attr('title');
			source.attr('title','');
			if(title)
			{
				tTitle.html(title);
			}
			else // stops old titles being used
			{
				tTitle.html('');
			}

		}
		if(settings.link)
		{
			tLink.attr('href', source.attr('href'));
		}
		if(settings.showBody)
		{

			tBody.empty();
			if(!settings.content)
			{
				tBody.append($(this).next().html());
				tBody.append($(this).next('*.tooltip_content').html());
			}
			else
			{
				tBody.append(settings.content(this));
			}
			if(tBody.html())
			{
				tBody.show();
				if(settings.track == true)
				{
					helper.bind("mouseover",
						function()
						{
							helper.over = true;
							helper.bind("mouseout",
								function(e)
								{
									helper.over = false;
									helper.unbind("mouseout");
									dohide();
								}
							);
						}
					);
				}
				//IE6 Hacks
				if(pbx.is_ie6)
				{
					$('select#pbx_customer_whereheard').css("visibility","hidden");    // register page
					$('select#pbx_album_cover_select').css("visibility","hidden");     // album details popup
				}
			}
			else
			{
				helper.unbind("mouseover");
				helper.unbind("mouseout");
				tBody.hide();
			}
		}

		// if element has href or src, add and show it, otherwise hide it
		var href = (source.attr('href') || source.attr('src'));
		if( settings.showURL && href )
		{
			tUrl.html(href.replace('http://', '')).show();
		}
		else
		{
			tUrl.hide();
		}

		if(settings.extraClass)							// add an optional class for this tip
		{
			helper.addClass(settings.extraClass);
		}

		if (settings.fixPNG && $.browser.msie )			// fix PNG background for IE
		{
			helper.each(
				function ()
				{
					if (this.currentStyle.backgroundImage != 'none')
					{
						var image = this.currentStyle.backgroundImage;
						image = image.substring(5, image.length - 2);
						$(this).css({
							'backgroundImage': 'none',
							'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
						});
					}
				}
			);
		}
	}

	/*
	 * delete timeout and show helper
	 */
	function show()
	{
		tID = null;
		helper.show();
		update();
	}

	/*
	 * callback for mousemove
	 * updates the helper position, removes itself when no current element
	 */
	function update(event,track)
	{
		if(current == null)									// if no current element is available, remove this listener
		{
			$('body').unbind('mousemove', update);
			return;
		}

		var left = helper[0].offsetLeft;
		var top = helper[0].offsetTop;
		if(event)											// position the helper 15 pixel to bottom right, starting from mouse position
		{
			if(!position)
			{
				left = event.pageX + 15;
/*
				if ((helper[0].clientWidth + left) > $(document).width())
				{
					left = null;
					right = helper[0].clientWidth;
				}
*/
				top = event.pageY + 15;
			}
			else
			{
				switch(position)
				{
					case 'under' :
						pos = $.iUtil.getPos(current);
						left = pos.x - 2;
						top = pos.y + pos.h + 2;
						break;

					case 'upper' :
						pos = $.iUtil.getPos(current);
						left = pos.x - (pos.w/2) - 5;
						top = pos.y + (pos.h/2) + 10;
						break;
						
					case 'bubble2' :
						pos = $.iUtil.getPos(current);
						left = pos.x + (pos.w/2) - 5;
						var height = helper.height();
						if(height == 'auto')
						{
							height = helper[0].offsetHeight;
						}
						top = pos.y + (pos.h/2) - 20.5 - parseInt(height);
						break;
				}
			}
			helper.css({
				left: left + 'px',
				top: top + 'px'
			});
		}

		var v = viewport(),
			h = helper[0];
		while(v.x + v.cx < h.offsetLeft + h.offsetWidth)		// check horizontal position
		{
			//left -= h.offsetWidth + 20;
			left -= 10;
			helper.css({left: left + 'px'});
		}
		if(v.y + v.cy < h.offsetTop + h.offsetHeight)		// check vertical position
		{
			top -= h.offsetHeight + 20;
			helper.css({top: top + 'px'});
		}

	}

	function viewport()
	{
		var e = document.documentElement || {},
			b = document.body || {},
			w = window;
		function min()
		{
			var v = Infinity;
			for( var i = 0;  i < arguments.length;  i++ )
			{
				var n = arguments[i];
				if( n && n < v ) v = n;
			}
			return v;
		}
		return {
			x: w.pageXOffset || e.scrollLeft || b.scrollLeft || 0,
			y: w.pageYOffset || e.scrollTop || b.scrollTop || 0,
			cx: min( e.clientWidth, b.clientWidth, w.innerWidth ),
			cy: min( e.clientHeight, b.clientHeight, w.innerHeight )
		};
	}

	function dohide()
	{
		// alert(helper.over);
		if(current && current.tSettings.delay_hide)				// hide helper, either with timeout or on instant
		{
			tID = setTimeout(hide, current.tSettings.delay_hide);
		}
		else
		{
			hide();
		}
	}

	/*
	 * hide helper and restore added classes and the title
	 */
	function hide()
	{
		if(helper.over)
		{
			return;
		}
		if(tID)												// clear timeout if possible
		{
			clearTimeout(tID);
		}
		helper.hide();

		if(current)
		{
			if(current.tSettings.extraClass )						// remove optional class
			{
				helper.removeClass( current.tSettings.extraClass);
			}
			if(current.tSettings.track == true)
			{
				helper.unbind("mouseover");
			}

			if(oldTitle)
			{
				$(current).attr('title', oldTitle);					// restore title and remove this listener
			}
			$(current).unbind('mouseout', hide);
			// IE6 Hacks
			if(pbx.is_ie6)
			{
				$('select#pbx_customer_whereheard').css("visibility","visible");    // registration page
				$('select#pbx_album_cover_select').css("visibility","visible");     // album details popup
			}

			if( current.tSettings.fixPNG && $.browser.msie )		// remove PNG background fix for IE
			{
				helper.each(
					function()
					{
						$(this).css({'filter': '', backgroundImage: ''});
					}
				);
			}
			current = null;										// no more current element
		}
	}

	// define global defaults, editable by client
	$.fn.tooltip.defaults = {
		container	: 'pbx_tooltip',
		children	: 'a',
		delay		: 0,
		delay_hide	: 0,
		event		: "mouseover",
		track		: true,
		showURL		: false,
		showTitle	: true,
		showBody	: true,
		extraClass	: null,
		fixPNG		: false
	};
})(jQuery);
//
//    Copyright (C) 2000, 2001, 2002  Virtual Cowboys info@virtualcowboys.nl
//
//		Author: Ruben Daniels <ruben@virtualcowboys.nl>
//		Version: 0.91
//		Date: 29-08-2001
//		Site: www.vcdn.org/Public/XMLRPC/
//
//    This program is free software; you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation; either version 2 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program; if not, write to the Free Software
//    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/*Object.prototype.toXMLRPC = function(){
	 // for compatibility with jQuery! ==================
	 // When the document first loads, JQuery initialises all objects, including the Window
	 // object, so we need to catch the Window object or it will break the xmlrpc library!
	if (this == '[object Window]') return;
	try
	{
		this.valueOf();
	}
	catch(e)
	{
		return;
	}
	// ================

	var wo = this.valueOf();
	if(wo.toXMLRPC == this.toXMLRPC){
		retstr = "<struct>";
		//alert('THIS:' + this + "\n" + 'TYPEOF:' + typeof this + 'TOSTRING:' + this.toString());
		for(prop in this){
			if(typeof wo[prop] != "function"){
				retstr += "<member><name>" + prop + "</name><value>" + XMLRPC.getXML(wo[prop]) + "</value></member>";
			}
		}
		retstr += "</struct>";

		return retstr;
	}
	else{
		return wo.toXMLRPC();
	}
}*/

String.prototype.toXMLRPC = function(){
	//<![CDATA[***your text here***]]>
	return "<string><![CDATA[" + this.replace(/\]\]/g, "] ]") + "]]></string>";//.replace(/</g, "&lt;").replace(/&/g, "&amp;")
};

Number.prototype.toXMLRPC = function(){
	if(this == parseInt(this)){
		return "<int>" + this + "</int>";
	}
	else if(this == parseFloat(this)){
		return "<double>" + this + "</double>";
	}
	else{
		return false.toXMLRPC();
	}
};

Boolean.prototype.toXMLRPC = function(){
	if(this == true) return "<boolean>1</boolean>";
	else return "<boolean>0</boolean>";
};

Date.prototype.toXMLRPC = function(){
	//Could build in possibilities to express dates
	//in weeks or other iso8601 possibillities
	//hmmmm ????
	//19980717T14:08:55
	return "<dateTime.iso8601>" + doYear(this.getUTCYear()) + doZero(this.getMonth()) + doZero(this.getUTCDate()) + "T" + doZero(this.getHours()) + ":" + doZero(this.getMinutes()) + ":" + doZero(this.getSeconds()) + "</dateTime.iso8601>";

	function doZero(nr) {
		nr = String("0" + nr);
		return nr.substr(nr.length-2, 2);
	}

	function doYear(year) {
		if(year > 9999 || year < 0)
			XMLRPC.handleError(new Error("Unsupported year: " + year));

		year = String("0000" + year);
		return year.substr(year.length-4, 4);
	}
};

Array.prototype.toXMLRPC = function(){
	var retstr = "<array><data>";
	for(var i=0;i<this.length;i++){
		retstr += "<value>" + XMLRPC.getXML(this[i]) + "</value>";
	}
	return retstr + "</data></array>";
};

function VirtualService(servername, oRPC){
	this.version = '0.91';
	this.URL = servername;
	this.multicall = false;
	this.autoroute = true;
	this.onerror = null;

	this.rpc = oRPC;
	this.receive = {};

	this.purge = function(receive){
		return this.rpc.purge(this, receive);
	};

	this.revert = function(){
		this.rpc.revert(this);
	};

	this.add = function(name, alias, receive){
		this.rpc.validateMethodName();if(this.rpc.stop){this.rpc.stop = false;return false}
		if(receive) this.receive[name] = receive;
		this[(alias || name)] = new Function('var args = new Array(), i;for(i=0;i<arguments.length;i++){args.push(arguments[i]);};return this.call("' + name + '", args);');
		return true;
	};

	//internal function for sending data
	this.call = function(name, args){
		var info = this.rpc.send(this.URL, name, args, this.receive[name], this.multicall, this.autoroute);

		if(info){
			if(!this.multicall) this.autoroute = info[0];
			return info[1];
		}
		else{
			if(this.onerror) this.onerror(XMLRPC.lastError);
			return false;
		}
	};
}


var XMLRPC = {
	routeServer : "/xxx",
	autoroute : true,
	multicall : false,

	services : {},
	stack : {},
	queue : new Array(),
	timers : new Array(),
	timeout : 30000,

	ontimeout : null,

	getService : function(serviceName){
		//serviceNames cannot contain / or .
		if(/[\/\.]/.test(serviceName)){
			return new VirtualService(serviceName, this);
		}
		else if(this.services[serviceName]){
			return this.services[serviceName];
		}
		else{
			try{
				var ct = eval(serviceName);
				this.services[serviceName] = new ct(this);
			}
			catch(e){
				return false;
			}
		}
	},

	purge : function(modConst, receive){
		if(this.stack[modConst.URL].length){
			var info = this.send(modConst.URL, "system.multicall", [this.stack[modConst.URL]], receive, false, modConst.autoroute);
			modConst.autoroute = info[0];
			this.revert(modConst);

			if(info){
				modConst.autoroute = info[0];
				return info[1];
			}
			else{
				if(modConst.onerror) modConst.onerror(this.lastError);
				return false;
			}
		}
	},

	revert : function(modConst){
		this.stack[modConst.URL] = new Array();
	},

	call : function(){
		//[optional info || receive, servername,] functionname, args......
		var args = new Array(), i, a = arguments;
		var servername, methodname, receive, service, info, autoroute, multicall;

		if(typeof a[0] == "object"){
			receive = a[0][0];
			servername = a[0][1].URL;
			methodname = a[1];
			multicall = (a[0][1].supportsMulticall && a[0][1].multicall);
			autoroute = a[0][1].autoroute;
			service = a[0][1];
		}
		else if(typeof a[0] == "function"){
			i = 3;
			receive = a[0];
			servername = a[1];
			methodname = a[2];
		}
		else{
			i = 2;
			servername = a[0];
			methodname = a[1];
		}

		for(i=i;i<a.length;i++){
			args.push(a[i]);
		}

		info = this.send(servername, methodname, args, receive, multicall, autoroute);
		if(info){
			(service || this).autoroute = info[0];
			return info[1];
		}
		else{
			if(service && service.onerror) service.onerror(this.lastError);
			return false;
		}

	},

	/***
	* Perform typematching on 'vDunno' and return a boolean value corresponding
	* to the result of the evaluation-match of the mask-value stated in the 2nd argument.
	* The 2nd argument is optional (none will be treated as a 0-mask) or a sum of
	* several masks as follows:
	* type/s    ->  mask/s
	* --------------------
	* undefined ->  0/1 [default]
	* number    ->  2
	* boolean   ->  4
	* string    ->  8
	* function  -> 16
	* object    -> 32
	* --------------------
	* Examples:
	* Want [String] only: (eqv. (typeof(vDunno) == 'string') )
	*  Soya.Common.typematch(unknown, 8)
	* Anything else than 'undefined' acceptable:
	*  Soya.Common.typematch(unknown)
	* Want [Number], [Boolean] or [Function]:
	*  Soya.Common.typematch(unknown, 2 + 4 + 16)
	* Want [Number] only:
	*  Soya.Common.typematch(unknown, 2)
	**/
	typematch : function (vDunno, nCase){
		var nMask;
		switch(typeof(vDunno)){
			case 'number'  : nMask = 2;  break;
			case 'boolean' : nMask = 4;  break;
			case 'string'  : nMask = 8;  break;
			case 'function': nMask = 16; break;
			case 'object'  : nMask = 32; break;
			default	     : nMask = 1;  break;
		}
		return Boolean(nMask & (nCase || 62));
	},

	getNode : function(data, tree){
		var nc = 0;//nodeCount
		//node = 1
		if(data != null){
			for(i=0;i<data.childNodes.length;i++){
				if(data.childNodes[i].nodeType == 1){
					if(nc == tree[0]){
						data = data.childNodes[i];
						if(tree.length > 1){
							tree.shift();
							data = this.getNode(data, tree);
						}
						return data;
					}
					nc++
				}
			}
		}

		return false;
	},

	toObject : function(data){
		var ret, i;
		switch(data.tagName){
			case "string":
				return (data.firstChild) ? new String(data.firstChild.nodeValue) : "";
				break;
			case "int":
			case "i4":
			case "double":
				return (data.firstChild) ? new Number(data.firstChild.nodeValue) : 0;
				break;
			case "dateTime.iso8601":
				/*
				Have to read the spec to be able to completely
				parse all the possibilities in iso8601
				07-17-1998 14:08:55
				19980717T14:08:55
				*/

				var sn = (isIE) ? "-" : "/";

				if(/^(\d{4})(\d{2})(\d{2})T(\d{2}):(\d{2}):(\d{2})/.test(data.firstChild.nodeValue)){;//data.text)){
	      		return new Date(RegExp.$2 + sn + RegExp.$3 + sn +
	      							RegExp.$1 + " " + RegExp.$4 + ":" +
	      							RegExp.$5 + ":" + RegExp.$6);
	      	}
	    		else{
	    			return new Date();
	    		}

				break;
			case "array":
				data = this.getNode(data, [0]);

				if(data && data.tagName == "data"){
					ret = new Array();

					var i = 0;
					while(child = this.getNode(data, [i++])){
      				ret.push(this.toObject(child));
					}

					return ret;
				}
				else{
					this.handleError(new Error("Malformed XMLRPC Message1"));
					return false;
				}
				break;
			case "struct":
				ret = {};

				var i = 0;
				while(child = this.getNode(data, [i++])){
					if(child.tagName == "member"){
						ret[this.getNode(child, [0]).firstChild.nodeValue] = this.toObject(this.getNode(child, [1]));
					}
					else{
						this.handleError(new Error("Malformed XMLRPC Message2"));
						return false;
					}
				}
				ret['callBabel'] = pbx.babel._callBabelInstance;
				return ret;
				break;
			case "boolean":
				return Boolean(isNaN(parseInt(data.firstChild.nodeValue)) ? (data.firstChild.nodeValue == "true") : parseInt(data.firstChild.nodeValue));

				break;
			case "base64":
				return this.decodeBase64(data.firstChild.nodeValue);
				break;
			case "value":
				child = this.getNode(data, [0]);
				return (!child) ? ((data.firstChild) ? new String(data.firstChild.nodeValue) : "") : this.toObject(child);

				break;
			default:
				this.handleError(new Error("Malformed XMLRPC Message: " + data.tagName));
				return false;
				break;
		}
	},

	/*** Decode Base64 ******
	* Original Idea & Code by thomas@saltstorm.net
	* from Soya.Encode.Base64 [http://soya.saltstorm.net]
	**/
	decodeBase64 : function(sEncoded){
		// Input must be dividable with 4.
		if(!sEncoded || (sEncoded.length % 4) > 0)
		  return sEncoded;

		/* Use NN's built-in base64 decoder if available.
		   This procedure is horribly slow running under NN4,
		   so the NN built-in equivalent comes in very handy. :) */

		else if(typeof(atob) != 'undefined')
		  return atob(sEncoded);

	  	var nBits, i, sDecoded = '';
	  	var base64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
		sEncoded = sEncoded.replace(/\W|=/g, '');

		for(i=0; i < sEncoded.length; i += 4){
			nBits =
				(base64.indexOf(sEncoded.charAt(i))   & 0xff) << 18 |
				(base64.indexOf(sEncoded.charAt(i+1)) & 0xff) << 12 |
				(base64.indexOf(sEncoded.charAt(i+2)) & 0xff) <<  6 |
				base64.indexOf(sEncoded.charAt(i+3)) & 0xff;
			sDecoded += String.fromCharCode(
				(nBits & 0xff0000) >> 16, (nBits & 0xff00) >> 8, nBits & 0xff);
		}

		// not sure if the following statement behaves as supposed under
		// all circumstances, but tests up til now says it does.

		return sDecoded.substring(0, sDecoded.length -
		 ((sEncoded.charCodeAt(i - 2) == 61) ? 2 :
		  (sEncoded.charCodeAt(i - 1) == 61 ? 1 : 0)));
	},

	getObject : function(type, message){
		var obj;
		if(type == "HTTP"){
			if(isIE)
				obj = new ActiveXObject("microsoft.XMLHTTP");
			else
				obj = new XMLHttpRequest();
		}
		else if(type == "XMLDOM"){
			if(isIE){
				obj = new ActiveXObject("microsoft.XMLDOM");
				obj.loadXML(message)
			}else {
				obj = new DOMParser();
				obj = obj.parseFromString(message, "text/xml");
			}

		}
		else{
			this.handleError(new Error("Unknown Object"));
		}

		return obj;
	},

	objectToXMLRPC: function(obj){
		// for compatibility with jQuery! ==================
		// When the document first loads, JQuery initialises all objects, including the Window
		// object, so we need to catch the Window object or it will break the xmlrpc library!
		if (obj == '[object Window]') return;
		try
		{
			obj.valueOf();
		}
		catch(e)
		{
			return;
		}
		// ================
		var wo = obj.valueOf();
		if(wo.toXMLRPC == obj.toXMLRPC){
			retstr = "<struct>";
			//alert('THIS:' + this + "\n" + 'TYPEOF:' + typeof this + 'TOSTRING:' + this.toString());
			for(prop in obj){
				if(typeof wo[prop] != "function"){
					retstr += "<member><name>" + prop + "</name><value>" + XMLRPC.getXML(wo[prop]) + "</value></member>";
				}
			}
			retstr += "</struct>";

			return retstr;
		}
		else{
			return wo.toXMLRPC();
		}
	},

	validateMethodName : function(name){
		/*do Checking:

		The string may only contain identifier characters,
		upper and lower-case A-Z, the numeric characters, 0-9,
		underscore, dot, colon and slash.

		*/
		if(/^[A-Za-z0-9\._\/:]+$/.test(name))
			return true;
		else
			this.handleError(new Error("Incorrect method name"));
	},

	getXML : function(obj){
		if(typeof obj == "function"){
			this.handleError(new Error("Cannot Parse functions"));
		}else if(obj == null || obj == undefined || (typeof obj == "number" && !isFinite(obj)))
			return false.toXMLRPC();
		else if (obj.toXMLRPC)
			return obj.toXMLRPC();
		else
			return XMLRPC.objectToXMLRPC(obj);
	},

	handleError : function(e){
		if(!this.onerror || !this.onerror(e)){
			//alert("An error has occured: " + e.message);
			throw e;
		}
		this.stop = true;
		this.lastError = e;
	},

	cancel : function(id){
		//You can only cancel a request when it was executed async (I think)
		if(!this.queue[id]) return false;

		this.queue[id][0].abort();
		return true;
	},

	send : function(serverAddress, functionName, args, receive, multicall, autoroute){

		var id, http;
		//default is sync
		this.validateMethodName();
		if(this.stop){this.stop = false; return false;}

		//setting up multicall
		multicall = (multicall != null) ? multicall : this.multicall;

		if(multicall){
			if(!this.stack[serverAddress]) this.stack[serverAddress] = new Array();
			this.stack[serverAddress].push({methodName : functionName, params : args});
			return true;
		}

		//creating http object
		var http = this.getObject("HTTP");
		//setting some things for async/sync transfers
		if(!receive){
			async = false;
		}
		else{
			async = true;
			/* The timer functionality is implemented instead of
				the onreadystatechange event because somehow
				the calling of this event crashed IE5.x
			*/
			id = this.queue.push([http, receive, null, new Date()])-1;

			this.queue[id][2] = new Function("var id='" + id + "';var dt = new Date(new Date().getTime() - XMLRPC.queue[id][3].getTime());diff = parseInt(dt.getSeconds()*1000 + dt.getMilliseconds());if(diff > XMLRPC.timeout){if(XMLRPC.ontimeout) XMLRPC.ontimeout(); clearInterval(XMLRPC.timers[id]);XMLRPC.cancel(id);return};if(XMLRPC.queue[id][0].readyState == 4){XMLRPC.queue[id][0].onreadystatechange = function(){};XMLRPC.receive(id);clearInterval(XMLRPC.timers[id])}");
			this.timers[id] = setInterval("XMLRPC.queue[" + id + "][2]()", 20);
		}

		//setting up the routing
		autoroute = (autoroute || this.autoroute);
		autoroute = 'active';
		//'active' is only set when direct sending the message has failed
		var srv = (autoroute == "active") ? this.routeServer : serverAddress;

		try {
			http.open('POST', srv, async);
			http.setRequestHeader("User-Agent", "vcXMLRPC v0.91 (" + navigator.userAgent + ")");
			//http.setRequestHeader("Host", srv.replace(/^https?:\/{2}([:\[\]\-\w\.]+)\/?.*/, '$1'));
			//http.setRequestHeader("Host", srv);
			http.setRequestHeader("Content-type", "text/xml");
			if(autoroute == "active"){
				http.setRequestHeader("X-Proxy-Request", serverAddress);
				http.setRequestHeader("X-Compress-Response", "gzip");
			}
		}
		catch(e){
		alert(e.message);
			if(autoroute == true){
				//Access has been denied, Routing call.
				autoroute = "active";
				if(id){
					delete this.queue[id];
					clearInterval(this.timers[id]);
				}
				return this.send(serverAddress, functionName, args, receive, multicall, autoroute);
			}

			//Routing didn't work either..Throwing error
			this.handleError(new Error("Could not sent XMLRPC Message (Reason: Access Denied on client)"));
			if(this.stop){this.stop = false;return false}
		}

		//Construct the message
		var message = '<?xml version="1.0"?><methodCall><methodName>' + functionName + '</methodName><params>';
   	for(i=0;i<args.length;i++){
   		message += '<param><value>' + this.getXML(args[i]) + '</value></param>';
		}
		message += '</params></methodCall>';

		var xmldom = this.getObject('XMLDOM', message);
		if(self.DEBUG) alert(message);
		try{
			//send message
			http.send(xmldom);
		}
		catch(e){
			//Most likely the message timed out(what happend to your internet connection?)
			this.handleError(new Error("XMLRPC Message not Sent(Reason: " + e.message + ")"));
			if(this.stop){this.stop = false;return false}
		}

		if(!async && receive)
			return [autoroute, receive(this.processResult(http))];
		else if(receive)
			return [autoroute, id];
		else
			return [autoroute, this.processResult(http)];
	},

	receive : function(id){
		//Function for handling async transfers..
		if(this.queue[id]){
			try
			{
				var data = this.processResult(this.queue[id][0]);
				this.queue[id][1](data);
				delete this.queue[id];
			}
			catch(e)
			{
				this.queue[id][1](data, e);
				delete this.queue[id];
			}
		}
		else{
			this.handleError(new Error("Error while processing queue"));
		}
	},

	processResult : function(http){
		if(self.DEBUG) alert(http.responseText);
		if(http.status == 200){
			//getIncoming message
		   dom = http.responseXML;

		   if(dom){
		   	var rpcErr, main;

		   	//Check for XMLRPC Errors
		   	rpcErr = dom.getElementsByTagName("fault");
		   	if(rpcErr.length > 0){
		   		rpcErr = this.toObject(rpcErr[0].firstChild);
		   		this.handleError(new Error(rpcErr.faultCode, rpcErr.faultString));
		   		return false
		   	}

		   	//handle method result
		   	main = dom.getElementsByTagName("param");
		      if(main.length == 0) this.handleError(new Error("Malformed XMLRPC Message1"));
				var data;
				var meta = this.toObject(this.getNode(main[0], [0]));
				data = this.toObject(this.getNode(main[1], [0]));



				//handle receiving
				if(this.onreceive) this.onreceive(data);
				return {'response':data, 'meta':meta['__meta']};
		   }
		   else{
		  		this.handleError(new Error("Malformed XMLRPC Message2"));
			}
		}
		else{
			this.handleError(new Error("HTTP Exception: (" + http.status + ") " + http.statusText + "\n\n" + http.responseText));
		}
	}
};



//Smell something
ver = navigator.appVersion;
app = navigator.appName;
isNS = Boolean(navigator.productSub);
isOpera = Boolean(app == 'Opera');
//moz_can_do_http = (parseInt(navigator.productSub) >= 20010308)
isIE = (ver.indexOf("MSIE") != -1) ? 1 : 0;
isOTHER = (!isNS && !isIE && !isOpera) ? 1 : 0;
var pbx =
{
	is_ie6			:	null,
	is_ie7			:	null,
	is_safari		:	null,
	top_menu		:	null,
	hideselect		:	null,
	overlay			:	null,
	ellipse_offset	:	null,
	dropdown		:
	{
		delay		: 0,
		delay_hide	: 500,
		track		: true,
		showTitle	: false,
		position	: 'under',
		extraClass	: 'pbx_dropdown'
	},
	bubble			:
	{
		container	: 'pbx_bubble',
		track		: false,
		showTitle	: false,
		position	: 'upper',
		link		: true
	},
	bubble2			:
	{
		container	: 'pbx_bubble2',
		track		: false,
		showTitle	: false,
		position	: 'bubble2',
		link		: true
	},
	tooltip_fixed	:
	{
		track		: true,
		position	: 'under',
		showTitle	: false,
		delay		: 0,
		delay_hide	: 500,
		event		: "mousemove"
	},

	/*
	 * init()
	 * initialisation of all javascript effect after page have been loaded
	 */
	init							:	function()
	{
		pbx.js_settings = pbx.obj.js_settings || new Object;

		pbx.update_images('body');

		pbx.is_ie6 = ($.browser.msie && navigator.userAgent.match(/MSIE (\d+?\.\d+?)/)[1] == '6.0');
		pbx.is_ie7 = ($.browser.msie && navigator.userAgent.match(/MSIE (\d+?\.\d+?)/)[1] == '7.0');
		pbx.is_safari = ($.browser.safari);
		pbx.login_error = $('span#pbx_login_error').length;
		pbx.account_suspended = $('span#pbx_account_suspended_error').length;
		pbx.hideselect = $('iframe#pbx_hideselect');

		pbx.is_cupid = $('iframe#pbx_cupid_holder').length;
		pbx.is_myphotobox = $('div#pbx_account_album').length;
		pbx.is_frontpage = $('div#pbx_frontpage_main').length;
		pbx.is_wizard = $('form.pbx_wizard').length;

		// run the action
		$.live('a.pbx_ajax', 'click', pbx.action);

		$.live('a.pbx_dialog', 'click',
			function(e)
			{
				var params = new Object;
				params.params = pbx.get_params_from_url(this.href);
				if(params.params === false)
				{
					params.params = {};
				}
				params.title = this.title || this.innerHTML;
				params.component = this.pathname.replace(/^([^\/])/,'/$1');
				params.width = params.params.width*1;
				params.height = params.params.height*1;
				pbx.dialog.open(params);
				e.preventDefault();
			}
		);

		$.live('a.pbx_donothing', 'click', pbx.do_nothing);

		$.live('a.pbx_comingsoon', 'click',
			function(e)
			{
				pbx.popup.open({ _this : this, settings : 'pbx_popup_comingsoon' });
				e.preventDefault();
			}
		);

		$.live('a.pbx_bookmark', 'click',
			function(e)
			{
				pbx.addBookmark(this.title,this.href);
				e.preventDefault();
			}
		);

		$('div#pbx_header').find('span.pbx_auto_ellipse').each(pbx.applyAutoEllispe);
		if(!pbx.js_settings.no_ellipse)
		{
			$('div#pbx_content').find('span.pbx_auto_ellipse').each(pbx.applyAutoEllispe);
		}
		$('div#pbx_footer').find('span.pbx_auto_ellipse').each(pbx.applyAutoEllispe);

		/* Hover effect used on inputs disguised as links */
		$.live('span.pbx_button_link', 'mouseover',
			function() {
				$(this).addClass('pbx_button_link_hover');
			}
		);
		$.live('span.pbx_button_link', 'mouseout',
			function() {
				$(this).removeClass('pbx_button_link_hover');
			}
		);

		/* cart popup */
		$('a#pbx_basket_link').mouseover(
			function()
			{
				if(!pbx.ordering) // hack to stop this firing if we are ordering, see babel.js order code
				{
					pbx.performDisableCheck($('div#pbx_popup_cart'), function(_this) { $(_this).fadeIn("medium") });
				}
			}
		);
		$.live('a#pbx_popup_cart_close', 'click',
			function()
			{
				$('div#pbx_popup_cart').unbind('mouseover').unbind('mouseout');
				$('div#pbx_popup_cart').fadeOut('medium');
				setTimeout(
					function()
					{
						$('div#pbx_popup_cart').hover(function() { clearTimeout(pbx.hideCart) },
							function()
							{
								pbx.hideCart = setTimeout(
									function()
									{
										$('div#pbx_popup_cart').fadeOut('medium');
									},
								2000 );
							}
						);
					},
				1000 );
			}
		);

		$('div#pbx_popup_cart').hover(function() { clearTimeout(pbx.hideCart) },
			function()
			{
				pbx.hideCart = setTimeout(
					function()
					{
						$('div#pbx_popup_cart').fadeOut('slow');
					},
				2000 );
			}
		);

		var links_to_cupid = $('a.pbx_create');
		if(links_to_cupid.length)
		{
			var url = window.location.toString();
			var params_url = pbx.get_params_from_url(url);			// split the url to get the settings passed by
			if(params_url)
			{
				links_to_cupid.each(
					function()
					{
						var link_to_cupid = $(this);
						var params = new Array();
						$.each(params_url,
							function(i,n)
							{
								params.push(i + "=" + n);
							}
						);
						var current_href = link_to_cupid.attr('href');
						link_to_cupid.attr('href', current_href + (current_href.indexOf('?') != -1 ? '&' : '?') + params.join('&'));
					}
				);
			}
		}

		if(!pbx.babel.session.loggedIn())
		{
			$('*.pbx_login_needed').live('click',
				function()
				{
					pbx.popup.open({ _this : this, settings : 'pbx_popup_signin', registerpopup : true });
					return false;
				}
			);
		}

		$('a#pbx_passwordforgotten,a.pbx_passwordforgotten').live('click',
			function()
			{
				var href =	 $("a#pbx_passwordforgotten_popup").attr('href');
				var valid_email = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
				if (!$('input#pbx_login_email').val().match(valid_email))
				{
					$('input#pbx_login_email').val('');
				}

				var params_url = pbx.get_params_from_url(href);
				var href = "?";

				params_url.password_confirmation = true;
				params_url.email = $('input#pbx_login_email').val();

				$.each(params_url,
					function(key, value)
					{
						href += key + "=" + value + "&";
					}
				);

				$("a#pbx_passwordforgotten_popup").attr('href',href);
				pbx.popup.timer = setTimeout("$('a#pbx_passwordforgotten_popup').click()",200);
			}
		);

		pbx.loading = $('div#pbx_load');
		pbx.subtoolbar = $('div#pbx_subtoolbar');
		pbx.overlay = $('div#pbx_overlay');
		$('div.pbx_tooltip').tooltip();
		$('span.pbx_tooltip').tooltip();
		$('*.pbx_tooltip_fixed').tooltip(pbx.tooltip_fixed);
		$('*.pbx_dropdown').tooltip(pbx.dropdown);
		$('a.pbx_external').live('click', pbx.external);
		$('select.pbx_order_select_product').updateProduct();

		$('input.pbx_input_default_content[alt]')
			.bind('focus',
				function()
				{
					if(this.value == this.alt)
					{
						$(this).val('').removeClass('pbx_inactive');
					}
				}
			)
			.bind('blur',
				function()
				{
					if(this.value == '' || this.value == this.alt)
					{
						$(this).addClass('pbx_inactive').val(this.alt);
					}
				}
			)
			.blur();

		if(pbx.login_error || pbx.account_suspended)
		{
			$('a#pbx_signin').trigger('click');
		}

		if($('div.pbx_loggedin_bubble').length == 1 && !pbx.is_myphotobox && !pbx.is_cupid)
		{
			pbx.bubble_show('a#pbx_myphotobox_menu', '200px', 10000);
		}

		pbx.init_menu_iframe();

		if(pbx.is_frontpage)
		{
			var images = $("div#pbx_fp_main_image").children('img');	// get all images for the slideshow
			var image = images.not('.pbx_invisible');					// get the visible image
			pbx.fp_description = $('div#pbx_fp_main_image em');			// get the description holder
			pbx.fp_description_text = pbx.fp_description.children('span');
			if (images > 0)							// Ensure there is a slide show before continuing
			{
				$("div#pbx_fp_main_image").bind('mouseover',				// on mouse move on the image's container
					function(e)
					{
						pbx.fp_imghovered = true;
						if(pbx.fp_description_text.html().length)
						{
							pbx.show_photo_desc(e,true);						// show photo description
						}
					}
				);

				$("body#pbx").bind('mouseover',				// on mouse move outside of the image's container
					function(e)
					{
						pbx.fp_imghovered = false;
						if(pbx.fp_description_text.html().length)
						{
							pbx.show_photo_desc(e,false);						// hide photo description
						}
					}
				);
				pbx.fp_description_text.html(image.attr('alt'));					// set the description of the first image
			}
			if(images.length>1)											// if there's more than 1 image, start the slideshow's timer
			{
				pbx.frontpage_timer = setTimeout("pbx.slidephoto()", 10000);
			}
		}
		if(pbx.is_wizard)
		{
			pbx.wizard.init();
		}

		if (typeof(pbx_page_requires_cookie) != 'undefined')
		{
			pbx.checkCookie();
		}

		/* bind self select boxes */
		$('.pbx_selfselect').live('click', function(event) { $(event.target).select(); })

		if($('#pbx_load.pbx_preload').length > 0)
		{
			pbx.show_loading(false);
			pbx.show_overlay(false);
		}
		// set the variable pbx_loadInProgress in order to know that loading is finished
		pbx_loadInProgress = false;

		/* disable any slideshow link if no slideshow application is available */
		if(pbx.config.piclensOff == 1 && pbx.config.flashSlideshowOff == 1)
		{
			$('.pbx_slideshow').unbind().bind('click', function(){
				return false;
			});
		}
	},
	slidephoto						:	function()
	{
		clearTimeout(pbx.frontpage_timer);										// stop the timer temporarily
		var images = $("div#pbx_fp_main_image").children('img');							// get all images
		var image = images.not('.pbx_invisible');								// get the current image visible
		var new_image = image.next('img');										// get the one just after
		if(new_image[0] === undefined)											// or the first one in the list
		{
			new_image = $(images[0]);
		}
		if(new_image[0].longDesc)												// if the next image havnt been loaded yet, load it!
		{
			new_image[0].src = new_image[0].longDesc;
			new_image.removeAttr('longdesc');
		}

		pbx.fadeout_isrunning = true;
		image.fadeOut(900,
			function()
			{
				$(this).addClass('pbx_invisible').removeAttr('style');
				pbx.fp_description_text.html(new_image.attr('alt'));
				pbx.fadeout_isrunning = false;
			}
		);

		pbx.fadein_isrunning = true;
		new_image
			.removeClass('pbx_invisible')
			.fadeIn(900,
				function()
				{
					pbx.frontpage_timer = setTimeout("pbx.slidephoto()", 10000);
					pbx.fadein_isrunning = false;
				}
			);
	},
	show_photo_desc					:	function(e,status)
	{
		if(!(pbx.fadeout_isrunning || pbx.fadein_isrunning || pbx.fp_description_isrunning))
		{
			if(status)
			{
				if(pbx.fp_description.css('display') != 'block')
				{
					pbx.fp_description_isrunning = true;
					pbx.fp_description.slideDown(200, function(){ pbx.fp_description_isrunning = false; });
				}
			}
			else
			{
				if(pbx.fp_description.css('display') == 'block')
				{
					pbx.fp_description_isrunning = true;
					pbx.fp_description.slideUp(200, function(){ pbx.fp_description_isrunning = false; });
				}
			}
		}
		if(e)
		{
			if(window.event)
			{
				window.event.cancelBubble = true;
				window.event.returnValue = false;
			}
			else
			{
				e.preventDefault();
				e.stopPropagation();
			}
		}
		return false;
	},
	toggle_rightmenu				:	function(params, e, exp, status)
	{
		if(!exp)
		{
			menu = $(params._this);
		}
		else
		{
			menu = $(exp);
		}
		menuitems = menu.siblings('span').toggleClass('pbx_icon_fold')
						.parent()
						.parent()
						.children('dd:not(.pbx_hidden)');
		if(!status)
		{
			menuitems.slideToggle('fast');
		}
		else
		{
			eval("menuitems.slide" + status + "('fast')");
		}
	},
	open_toolbar					:	function(onCompleatFunction)
	{
		if(pbx.subtoolbar.css('display') == 'none')
		{
			pbx.subtoolbar.slideDown('fast', onCompleatFunction);
			return true;
		}
		return false;
	},
	close_toolbar					:	function(onCompleatFunction)
	{
		if(pbx.subtoolbar.css('display') == 'block')
		{
			pbx.subtoolbar.slideUp('fast', onCompleatFunction);
			return true;
		}
		return false;
	},
	hide_dropdown					:	function()
	{
		$('div#pbx_tooltip').trigger('mouseout');
	},
	bubble_show						:	function(link, content_width, timeline, type)
	{
		var selector = "div#pbx_bubble";
		var params = pbx.bubble;
		if(type == "up")
		{
			selector = "div#pbx_bubble2";
			params = pbx.bubble2;
		}
		var bubble = $(selector);
		bubble.css('width',content_width);
		$(link)
			.parent()
			.tooltip(params)
			.end()
			.trigger('mouseover');

		$("a#pbx_bubble_close, a#pbx_bubble2_close").bind('click',
			function()
			{
				bubble.unbind('mouseover').unbind('mouseout');
				pbx.bubble_hide(link, false);
				return false;
			}
		);

		if (timeline)
		{
			bubble.bind('mouseover',
				function()
				{
					clearTimeout(pbx.bubble_timeout);
				}
			);
			bubble.bind('mouseout',
				function(e)
				{
					clearTimeout(pbx.bubble_timeout);
					pbx.bubble_timeout = setTimeout('pbx.bubble_hide(\'' + link + '\', true)',timeline);
				}
			);
			clearTimeout(pbx.bubble_timeout);
			pbx.bubble_timeout = setTimeout('pbx.bubble_hide(\'' + link + '\', true)',timeline);
		}
	},
	bubble_hide						:	function(link, fade)
	{
		clearTimeout(pbx.bubble_timeout);
		$("a#pbx_bubble_close, a#pbx_bubble2_close").unbind('click');
		if(fade)
		{
			$('div#pbx_bubble:visible, div#pbx_bubble2:visible')
				.fadeOut('slow',
					function()
					{
						$(link).parent().tooltipDestroy(pbx.bubble).tooltipDestroy(pbx.bubble2);
						return false;
					}
				);
		}
		else
		{
			$(link).parent().tooltipDestroy(pbx.bubble).tooltipDestroy(pbx.bubble2);
			return false;
		}
	},
	menu_photocount_update			:	function(album_id, i)
	{
		try
		{
			var photo_count = $('#album_photocount_' + album_id);
			var old_count = photo_count.html();
			var old_count = (old_count.substring(1,old_count.length - 1)) * 1;
			var new_count = old_count + i;
			photo_count.html('(' + new_count + ')');
		}
		catch(e)			// in case of photos have been moved to a new album which is not already on the menu
		{
			return;
		}
	},
	menu_album_tree_refresh			:	function(onCompleat)
	{
		// refresh the album tree only if the html element is present in the album menu
		if ($('span#pbx_menu_album_refresh').length)
		{
			$.ajax(	{ 	type		: 	"POST",
						url			: 	"/includes/ajax/nav/header/menu/album",
						success		: 	function(result)
										{
											var album_tree_root = $('#pbx_menu_album_tree_root');
											album_tree_root.parent().append(result);
											album_tree_root.remove();
											//$('.pbx_auto_ellipse').each(pbx.applyAutoEllispe);
											if(onCompleat)
											{
												onCompleat();
											}
										}
					}	);
		}
	},

	menu_album_name_update			:	function(id, text)
	{
		$('a#pbx_menu_album_' + id)
			.html(
				'<em id="album_photocount_' + id + '">'
				+ $('a#pbx_menu_album_' + id).find('em').html()
				+ '</em><span class="pbx_icon pbx_icon_hover"/>'
				+ pbx.prepareAutoEllipseField(text, 160))
			.attr('title',text)
			.find('span.pbx_auto_ellipse')
			.each(pbx.applyAutoEllispe);
	},
	copy_photos						:	function(album_destination, photo_ids)
	{
		album_destination.callBabel('AddPhotos', {photo_ids: photo_ids});
		pbx.menu_photocount_update(album_destination.id, photo_ids.length);
	},
	move_photos						:	function(original_album, destination_album, photos_id)
	{
		original_album.callBabel('MovePhotosToAlbum', {destination_album_id: destination_album.id, photo_ids: photos_id});
		pbx.menu_photocount_update(original_album.id, photos_id.length * -1);
		pbx.menu_photocount_update(destination_album.id, photos_id.length);
	},
	submitOfferCode :	function(func)
	{
		try
		{
			var offercode = pbx.credits.currentOfferCode = $('input#pbx_offercode_input').val();
			if(offercode)
			{
				var offer_message = pbx.babel.AddOffer(offercode);
				if (offer_message)
				{
					var extra_message = ''
					if (offer_message.offer_type == 2 && offer_message.discount_applied == 0 && offer_message.message_source == 'terms')
					{
						extra_message = $('span#pbx_offer_correct_not_applied').html();
					}
					pbx.popup.genericOK.open(offercode, offer_message.message.toString() + extra_message,
						function()
						{
							if (offer_message.offer_type > 0 && typeof func == 'function')
							{
								func(offer_message);
							}
						}
					);
				}
			}
		}
		catch (e)
		{
			alert(e);
		}
		return false;
	},
	/*
	 * get_params_from_url()
	 * transform http://server/file?this=that&this=moo&foo=bar in :
	 * array( 'this' => array('that' , 'moo'), 'foo'=> 'bar')
	 */
	get_params_from_url				:	function(url)
	{
		url = url.replace(/#$/, '');
		url = url.split('?');
		if(url.length > 1)
		{
			var parts = url[1].split('&');
			var params = new Object();
			for (var i=0; i<parts.length; i++)
			{
				var paramData = parts[i].split('=');
				var key = paramData[0];
				if (typeof params[key] == "array")
				{
					params[key].push(paramData[1]);
				}
				else if (params[key])
				{
					var newData = new Array(params[key], paramData[1]);
					params[key] = newData;
				}
				else
				{
					params[key] = paramData[1];
				}
			}
			return params;
		}
		else
		{
			return false;
		}
	},
	/*
	 * action()
	 * function called by a click on the link
	 */
	action							:	function(e,a,params)
	{
		var to_run = '';
		if(this.href)
		{
			a = this;
		}
		else if(e && e.href)
		{
			a = e;
		}
		// If the action button is diabled, return without doing anything.
		if($(a).is('.pbx_disabled,.pbx_disable_big'))
		{
			return false;
		}
		if(!params)
		{
			var params = pbx.get_params_from_url(a.href);			// split the url to get the settings passed by
			params._this = a;										// add this to the params object (which will be passed to the function)
		}
		if((typeof params.action) == 'undefined')
		{
			window.location = a.href;
			return;
		}

		var cat = "";
		if(params.cat)
		{
			cat = params.cat + ".";
		}
		if(params.perform)
		{
			if(params.perform.substr(0,4) == 'pbx.')
			{
				to_run = params.perform + '(params,"' + params.action + '")';
			}
			else
			{
				to_run = 'pbx.' + cat + params.perform + '(params,"' + params.action + '")';
			}
		}
		else
		{
			to_run = 'pbx.' + cat + params.action + '(params, e)';
		}
		if(params.action && params.action.substr(0,10)=='pbx_flickr')
		{
			to_run = to_run.substr(4,to_run.length);
		}
		try
		{
			eval(to_run);
			pbx.action_button_busy(e, this, false);
		}
		catch(e)
		{
			alert(e);
			pbx.action_button_busy(e, this, false);
		}
		if(params.callback)
		{
			try
			{
				if(params.callback.substr(0,4) == 'pbx.')
				{
					to_run = params.callback + '()';
				}
				else
				{
					to_run = 'pbx.' + cat + params.callback + '()';
				}
				eval(to_run);
				pbx.action_button_busy(e, this, false);
			}
			catch(e)
			{
				alert(e);
				pbx.action_button_busy(e, this, false);
			}
		}
		if (e)
		{
			if (e.preventDefault)
			{
			e.preventDefault();
			}
		}
	},

	/**
	 * Sets the height and width of the menu iFrames to the same size as the containing ul element
	 */
	init_menu_iframe: function()
	{
		var theLi, newHeightm, newWidth;
		$('iframe.pbx_menu_iframe').each(function(){
				theLi = this.parentNode;
				newHeight = theLi.offsetTop;
				newWidth = theLi.offsetWidth;
				this.style.height = (newHeight || '0') + 'px'
				this.style.width  = (newWidth  || '0') + 'px';
			});
	},

	/*
	 * show_hideselect()
	 * should be used by IE6 only
	 * displaying a iframe that is 100% width and 100% height to hide select dropdown
	 */
	show_hideselect					:	function(status)
	{
		if(status)
		{
			var height = document.documentElement.scrollHeight;
			var width = document.documentElement.scrollWidth;
			pbx.hideselect.css({ display:'block', width: width+'px', height: height+'px'});
			$(window).resize(pbx.hideselect_size);
		}
		else
		{
			pbx.hideselect.css('display','none');
			$(window).unbind('resize');
		}
	},

	hideselect_size : function ()
	{
		if(!pbx.is_ie6) return;
		var height = document.documentElement.scrollHeight;
		var width = document.documentElement.scrollWidth;
		pbx.hideselect.css({ width: width+'px', height: height+'px'});
	},
	/*
	 * show_overlay()
	 * displaying the overlay on the top of the current screen
	 * onclose	:	callback function to be executed on click on the overlay
	 */
	show_overlay					:	function(status, onclick)
	{
		if(status == true && pbx.overlay.css('display') == 'none')
		{
			var height = document.documentElement.scrollHeight;
			var width = document.documentElement.scrollWidth;
			pbx.overlay.css({ display:'block', width: width+'px', height: height+'px'});
			if(typeof onclick == 'function')
			{
				pbx.overlay.bind('click', function(){ onclick(); });
			}
			pbx.set_activex_vis(false);
			$(window).resize(pbx.hideselect_size);
		}
		else if(status == false)
		{
			pbx.overlay.css('display','none').unbind('click');
			pbx.set_activex_vis(true);
			$(window).unbind('resize');
		}
		// special hacks for IE
		if(pbx.is_ie6)
		{
			pbx.show_hideselect(status);			// put an iframe to cover select dropdowns
		}
	},
	overlay_size : function ()
	{
		var height = document.documentElement.scrollHeight;
		var width = document.documentElement.scrollWidth;
		pbx.overlay.css({ width: width+'px', height: height+'px'});
		if(pbx.is_ie6) pbx.hideselect_size();
	},
	set_activex_vis : function(doShow)
	{
		var val = doShow ? 'visible' : 'hidden';
		$('.pbx_overlay_hide').css('visibility', val);
	},
	/*
	 * show_loading()
	 * displaying the loading animation
	 * works only if the overlay have been displayed first
	 */
	show_loading					:	function(status, element, callback)
	{
		if(status == true && pbx.loading.is(':hidden'))
		{
			// IE hack for preload div
			if(pbx.is_ie6 && $('div#pbx_preload')[0])
			{
				$('div#pbx_preload').css({'z-index': '102'});
			}
			// load contents
			if(element && element[0].nodeType)
			{
				$(pbx.loading).find('div#pbx_loading_content').html($(element).html());
			}
			else
			{
				$(pbx.loading).find('div#pbx_loading_content').html($('div#pbx_loading').html());
			}
			// position the loading div in the middle and show
			pbx.loading.show();
			var pos_top =  ( ( pbx.is_ie6 ? $(window).scrollTop() : 0) + ($(window).height() - pbx.loading[0].offsetHeight) / 2 );
			var pos_left = ( ( pbx.is_ie6 ? $(window).scrollLeft(): 0) + ($(window).width()  - pbx.loading[0].offsetWidth) / 2 );
			pbx.loading.css({top: pos_top+'px', left: pos_left+'px'});
			// Run the callback
			if(typeof callback == 'function')
			{
				callback(pbx.loading);
			}
		}
		else if(status == false)
		{
			pbx.loading.hide();
			if(pbx.is_ie6 && $('div#pbx_preload')[0])
			{
				$('div#pbx_preload').css({'z-index': '-1'});
			}
		}
	},
	/* Load a generic 'feature comming soon' popup */
	load_comingSoon : function(theTitle)
	{
		var params = {
			settings : "pbx_popup_comingsoon",
			_this : {
				title : theTitle || "Coming Soon"
			}
		};

		pbx.popup.open(params);
	},
	/* error codes for validate function */
	VALIDATE_OK : 1,
	VALIDATE_ERROR : 0,
	VALIDATE_PASSWORD_CHARSNOTALLOWED : -1,
	VALIDATE_PASSWORD_TOOSHORT : -2,
	VALIDATE_PASSWORD_NOTCONFORM : -3,
	/* Use this to check validity of inputs.
	 * Input is tha value to check, type is the type of pattern to match ('string' is default)
	 * returns codes above */
	validate : function(input, type, params)
	{
		type = type || 'string';
		var output = pbx.VALIDATE_ERROR;
		var pattern = null;
		switch(type)
		{
			case 'email' :
				input = input.replace(/^\s+/, "");
				input = input.replace(/\s+$/, "");
				pattern = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
				if(input.match(pattern)) output = pbx.VALIDATE_OK;
				break;
			case 'date' :
				pattern = /(0[1-9]|[12][0-9]|3[01])+\/(0[1-9]|1[012])+\/(19|20)\d\d/;
				if(input.match(pattern)) output = pbx.VALIDATE_OK;
				break;
			case 'no'	:
				pattern = /^[a-zA-Z0-9^\*\(\)\[\]\+\.\,\-\_\ \/\?\:\;\'\"\`\~\\\#\$\xA3\%\^\&\<\>]+$/;
				if(input.match(pattern)) output = pbx.VALIDATE_OK;
				break;
			case 'special_char'	:
				pattern = /^[^\*\(\)\[\]\+\.\,\/\?\:\;\'\"\`\~\\\#\$\xA3\%\^\&\<\>]+$/;   //meet this then error
				if(input.match(pattern)) output = pbx.VALIDATE_OK;
				break;
			case 'lastname_char'	:
				pattern = /^[^\*\(\)\[\]\+\.\,\_\/\?\:\;\`\~\\\#\$\xA3\%\^\<\>]+$/;
				if(input.match(pattern)) output = pbx.VALIDATE_OK;
				break;
			case 'password'	:
				//param for checking length
				minLength = (typeof(params) != 'undefined' && typeof(params.minLength) != 'undefined') ? params.minLength : 6;
				//param for checking hard password
				hard = (typeof(params) != 'undefined' && typeof(params.hard) != 'undefined') ? true : false;
				pattern = (typeof(params) != 'undefined' && typeof(params.pattern) != 'undefined') ? params.pattern : /^\w*$/;
				if(!input.match(pattern)) output = pbx.VALIDATE_PASSWORD_CHARSNOTALLOWED;
				else if (input.length < minLength) output = pbx.VALIDATE_PASSWORD_TOOSHORT;
				else if (hard==true && !((input.search(/[a-zA-Z]+/) > -1)&&(input.search(/[0-9]+/) > -1))) output = pbx.VALIDATE_PASSWORD_NOTCONFORM;
				else output = pbx.VALIDATE_OK;
				break;
			case 'string' :	// wrap to default
			default:
				output = input.replace(/[\&]+/gi, '&amp;').replace(/[\<]+/gi, '&lt;').replace(/[\>]+/gi, '&gt;');
				break;
		}
		return output;
	},

	/* validate_email_list
	 * Validates a commer deliminated list of emails.
	 * returns an object with attributes error_list, valid_list and is_valid.
	 */
	validate_email_list : function(input)
	{
		var output =
		{
			error_list : new Array(),
			valid_list : new Array(),
			is_valid : true
		}
		if (input.match(/^\s*$/))
		{
			output.is_valid = false;
		}
		else
		{
			var emailList = input.split(/[\s,;]+/);
			emailList.sort()

			var i = 0;
			do
			{
				if(i+1 != emailList.length && emailList[i] === emailList[i+1])
				{
					emailList.splice(i+1, 1);
					continue;
				}

				if (emailList[i] != '')
				{
					if (pbx.validate(emailList[i], 'email'))
					{
						output.valid_list.push(emailList[i]);
					}
					else
					{
						output.error_list.push(emailList[i]);
						output.is_valid = false;
					}
				}
				else
				{
					output.is_valid = false;
				}
				i++;
			} while (i < emailList.length)
		}
		return output;
	},

	paginate	:	function(selector, page, nbpages, href_pattern, nblinks, label)
	{
		if(!nblinks)
		{
			nblinks = 3;
		}
		page = parseInt(page);
		nbpages = parseInt(nbpages);
		nblinks = parseInt(nblinks);
		var paginator = $(selector);
		var label_span = paginator.children('span.pbx_paginator_label');
		var first_link = paginator.children('a.pbx_paginator_first');
		var first_span = paginator.children('span.pbx_paginator_first');
		var previous_link = paginator.children('a.pbx_paginator_previous');
		var previous_span = paginator.children('span.pbx_paginator_previous');
		var next_link = paginator.children('a.pbx_paginator_next');
		var next_span = paginator.children('span.pbx_paginator_next');
		var last_link = paginator.children('a.pbx_paginator_last');
		var last_span = paginator.children('span.pbx_paginator_last');
		var count_pattern = paginator.children('span.pbx_paginator_count_pattern').filter(':first');
		var count_pattern_link = count_pattern.children('a');
		var count_pattern_span = count_pattern.children('span');
		var count = paginator.children('span.pbx_paginator_count').empty();
		var separator = paginator.children('span.pbx_paginator_separator').filter(':first');
		var title = count_pattern_link.attr('title');

		if(nbpages < 2)
		{
			if(label)
			{
				label_span.addClass('pbx_hidden');
			}
			first_link.addClass('pbx_hidden');
			first_span.addClass('pbx_hidden');
			previous_link.addClass('pbx_hidden');
			previous_span.addClass('pbx_hidden');
			next_link.addClass('pbx_hidden');
			next_span.addClass('pbx_hidden');
			last_link.addClass('pbx_hidden');
			last_span.addClass('pbx_hidden');
			count.addClass('pbx_hidden');
		}
		else
		{
			if(label)
			{
				label_span.removeClass('pbx_hidden');
			}
			count.removeClass('pbx_hidden');

			// redifining the links href
			first_link.attr('href', href_pattern.replace('[#]', 1));
			previous_link.attr('href', href_pattern.replace('[#]', parseInt(page)-1));
			next_link.attr('href', href_pattern.replace('[#]', parseInt(page)+1));
			last_link.attr('href', href_pattern.replace('[#]', parseInt(nbpages)));

			// display the pages numbers
			var start = 1;
			var end = nbpages;
			if (nbpages > nblinks)
			{
				var toShow = Math.floor(nblinks/2);
				if((page - toShow) <= 0) 				// set the end from start
				{
					end = (toShow * 2) + 1;
				}
				else if ((page + toShow) >= nbpages) 	// set the start from end
				{
					start = nbpages - (toShow * 2);
				}
				else									// set start and end from page
				{
					start = page - toShow;
					end = page + toShow;
				}
			}
			var current_page;
			for(i = start; i <= end; i++)
			{
				current_page = null;
				if(i == page)
				{
					current_page = count_pattern_span.clone();
					current_page.html(i);
				}
				else
				{
					current_page = count_pattern_link.clone();
					current_page.html(i);
					current_page.attr('title', title.replace('[#]', i));
					current_page.attr('href', href_pattern.replace('[#]', i));
				}

				count.append(current_page)
				if(i < end)
				{
					count.append(separator);
				}
			};

			// if it's the first page, disable previous and first but enable next and last
			if(page == 1)
			{
				first_link.addClass('pbx_hidden');
				first_span.removeClass('pbx_hidden');
				previous_link.addClass('pbx_hidden');
				previous_span.removeClass('pbx_hidden');
				next_link.removeClass('pbx_hidden');
				next_span.addClass('pbx_hidden');
				last_link.removeClass('pbx_hidden');
				last_span.addClass('pbx_hidden');
			}
			// else if it's the last page, enable next and last but disable first and previous
			else if(page == nbpages)
			{
				first_link.removeClass('pbx_hidden');
				first_span.addClass('pbx_hidden');
				previous_link.removeClass('pbx_hidden');
				previous_span.addClass('pbx_hidden');
				next_link.addClass('pbx_hidden');
				next_span.removeClass('pbx_hidden');
				last_link.addClass('pbx_hidden');
				last_span.removeClass('pbx_hidden');
			}
			else
			{
				first_link.removeClass('pbx_hidden');
				first_span.addClass('pbx_hidden');
				previous_link.removeClass('pbx_hidden');
				previous_span.addClass('pbx_hidden');
				next_link.removeClass('pbx_hidden');
				next_span.addClass('pbx_hidden');
				last_link.removeClass('pbx_hidden');
				last_span.addClass('pbx_hidden');
			}
		}
	},
	i18nplural	:	function(variable, qty, display)
	{
		var string = parseInt(qty) > 1 ? 2 : parseInt(qty);
		if(display != 'block')	display = 'inline';
		switch(string)
		{
			case 0:
				$('#pbx_' + variable + '_1').hide();
				$('#pbx_' + variable + '_2').hide();	break;
			case 1:
				$('#pbx_' + variable + '_0').hide();
				$('#pbx_' + variable + '_2').hide();	break;
			case 2:
				$('#pbx_' + variable + '_0').hide();
				$('#pbx_' + variable + '_1').hide();
		}
		$('#' + variable).html(qty);
		$('#pbx_' + variable + '_' + string).css('display', display);
	},
	i18npluralclass	:	function(variable, qty, display, _parent)
	{
		var string = parseInt(qty) > 1 ? 2 : parseInt(qty);
		if(display != 'block')	display = 'inline';
		switch(string)
		{
			case 0:
				$(_parent).children('.pbx_' + variable + '_1').hide();
				$(_parent).children('.pbx_' + variable + '_2').hide();	break;
			case 1:
				$(_parent).children('.pbx_' + variable + '_0').hide();
				$(_parent).children('.pbx_' + variable + '_2').hide();	break;
			case 2:
				$(_parent).children('.pbx_' + variable + '_0').hide();
				$(_parent).children('.pbx_' + variable + '_1').hide();
		}
		$(_parent).children('.pbx_' + variable + '_' + string).children('.' + variable).html(qty);
		$(_parent).children('.pbx_' + variable + '_' + string).css('display', display);
	},

	external	:	function()
	{
		window.open(this.href);
		return false;
	},

	privilege_error		:	function()
	{
		pbx.popup.open({ _this : {title : 'Error'}, settings : 'pbx_popup_privilegeerror' });
	},

	/* Find which radio button is selected from a series.
	 * Pass the id of the form and the name of the radio buton series and this will return the selected value.
	 * Returns null if the form or radio series could not be found. */
	getRadioValue : function(form_id, radio_name)
	{
		try
		{
			var radios = document.forms[form_id].elements[radio_name];
			var radio_value;
			for (var i=0; i<radios.length; i++)
			{
				if (radios[i].checked)
				{
					radio_value = radios[i].value;
					break;
				}
			}
		}
		catch (e)
		{
			radio_value = null;
		}
		return radio_value;
	},

	action_button_busy	:	function(e, elt, status)
	{
		var button = $(elt);
		var html_elt;
		if(button[0].tagName == 'A')
		{
			html_elt = button;
		}
		else
		{
			html_elt = button.parent();
		}
		/*
		if(status)
		{
			html_elt.addClass('pbx_disabled');
		}
		else
		{
			html_elt.removeClass('pbx_disabled');
		}*/
	},

	limitSize	:	function(ctrl, size, callback)
	{
		if(ctrl.value.length <= size)
		{
			callback();
			return true;
		}
		else
		{
			// IE counts return characters as 2 (\n) when using substring
			var returnCount = 0;
			if(pbx.is_ie6 || pbx.is_ie7)
			{
				ctrl.value.replace(/\n/gi,
	  				function()
	  				{
						returnCount++;
	 				}
				);
			}
			ctrl.value = ctrl.value.substr(0, size+returnCount);
			callback();
			return false;
		}
	},

	addBookmark	:	function(title,url)
	{
		if(window.sidebar)
		{
			window.sidebar.addPanel(title, url,"");
		}
		else if(document.all)
		{
			window.external.AddFavorite(url, title);
		}
		else if(window.opera && window.print)
		{
			return true;
		}
	},
	do_nothing	:	function(e)
	{
		return false;
	},
	/*
	 * performDisableCheck()
	 * any actions can be passed through this function which checks if the link is disabled (either directly or by one of its parents)
	 * currently used in basket and search
	 */
	performDisableCheck	:	function(_this, func)
	{
		if( $(_this).is('.pbx_disabled,.pbx_disabled_big') || $(_this).parent().is('.pbx_disabled,.pbx_disabled_big') || $(_this).parent().parent().is('.pbx_disabled,.pbx_disabled_big'))
		{
			return false;
		}
		else if (typeof func == 'function')
		{
			return func(_this);
		}
		return true;
	},
	favourites_item_update	:	function(length)
	{
		var favourites = $('li#pbx_menu_favorites');
		var favourites_link = favourites.children('a');
		var favourites_link_id = favourites_link.attr('id');
		var favourites_id = favourites_link_id.substring(15, favourites_link_id.length);
		var favourites_count = favourites.find('em');
		pbx.menu_photocount_update(favourites_id, length);

		if(favourites_count.length && parseInt(favourites_count.html().substring(1,favourites_count.html().length-1)) == 0)
		{
			favourites.addClass('pbx_disabled');
			favourites_link.bind('click', pbx.do_nothing);
		}
		else
		{
			favourites.removeClass('pbx_disabled');
			favourites_link.unbind('click');
		}
	},
	/* Returns a new copy of 'what'
	 * Use this to copy javascript objects but not on objects that have circular references such as dom elements. */
	copyObject: function (what)
	{
		var obj = new Object();
		for (i in what) {
			if (typeof what[i] == 'object' && isNaN(what[i].nodeType))
			{
				obj[i] = pbx.copyObject(what[i]);
			}
			else
			{
				obj[i] = what[i];
			}
		}
		return obj;
	},
	/* bind this to the click event of a dom element if you want the contents cleared once. */
	clearTextArea:function() {
		if (!this.cleared) {
			$(this).html('');
			$(this).val('');
			this.cleared = true;
		}
	},
	/* replaces the \n with \n<br/>. Call this function when sending a message to be pre-formatted in the email body */
	formatEmailMessage:function(message)
	{
                return message.replace(/\n/gmi, '\n<br />');
	},

	prepareAutoEllipseField	:	function(text, maxsize)
	{
		return '<span class="pbx_auto_ellipse" maxsize="' + maxsize + '">' + text + '</span>';
	},

	autoEllispe			:	function(text, size)
	{
		var _this = $(this);
		_this
			.html(pbx.prepareAutoEllipseField(text, size))
			.find('span.pbx_auto_ellipse')
			.each(pbx.applyAutoEllispe);
		return _this;
	},

	applyAutoEllispe	:	function()
	{
		var width;
		var _this = $(this);						// store the jqueryfied object
		var width = parseInt(_this.attr('maxsize'));

		if(isNaN(width))
		{
			width = parseInt(_this.css('width'));
			if(isNaN(width) || width == 0)
			{
				width = jQuery.iUtil.getSize(this).w;	// try to calculate the actual size
				if(width == 'auto' || width == 0)
				{
					width = 10;
				}
			}
		}
		this.innerHTML = pbx.autoEllipseText(this, this.innerHTML,width);

		$(this).replaceWith(this.innerHTML);
	},

	autoEllipseText		:	function(element, text, width)
	{
		element.innerHTML = '<span id="pbx_ellipsisSpan" style="white-space:nowrap;">' + text + '</span>';
		inSpan = document.getElementById('pbx_ellipsisSpan');
		if(inSpan.offsetWidth> width)
		{
			var i = pbx.ellipse_offset;
			if (!i)
			{
				// if no offset is wet, take a W and try to calculate a starting width
				inSpan.innerHTML = 'W';
				i = parseInt(width/inSpan.offsetWidth);
				inSpan.innerHTML = text;
			}
			inSpan.innerHTML = '';
			while(inSpan.offsetWidth <(width) && i <text.length)
			{
				inSpan.innerHTML = text.substr(0,i) + '...';
				i++;
			}
			returnText = inSpan.innerHTML;
			element.innerHTML = '';
			return returnText;
	   }
	   return text;
	},

	processTags		:	function(tags_string)
	{
		var tags = [];

		// replace breaklines by spaces
		tags_string = tags_string.replace(/\n/g,' ').toString().trim();

		// extract then the strings in " "
		var reg = new RegExp("\"[^\"]*\"", "g");
		var res = tags_string.match(reg);

		if(res)
		{
			$.each(res,
				function()
				{
					tags_string = tags_string.replace(this, " ");	// remove the string from the original string
					tags.push(this.substr(1, this.length - 2));		// then strip out the quotes (")
				}
			);
		}

		// extract then the other strings (',', ' ', ';' separated)
		reg = new RegExp("[, ;]+","g");
		res = tags_string.toString().trim().split(reg);

		// then merge the two arrays before sending them to the backend (and remove any duplicates)
		$.merge(tags, res);


		// then convert the array into a array object (hash)
		var tags_hash = {};

		$.each(tags,
			function(i, e)
			{
				//validate before putting in the array object
				e = pbx.validate(e);
				tags_hash[e] = '';
			}
		);

		return tags_hash;
	},

	ajaxContentInit		:	function(container)
	{
		pbx.update_images(container);

		if( typeof(pbx.slideshow) !== 'undefined' ) pbx.slideshow.init(container);
	},

	update_images		:	function(container)
	{
		if (!$(container)[0])
		{
			// If no container is provided or container does not exist then default to body as the container.
			container = 'body';
		}
		$(container).find('img[longdesc]:not(.pbx_invisible):not(.pbx_alphacarousel)').each(function(){this.src = this.longDesc; $(this).removeAttr('longdesc');});
	},

	string2Hash			:	function(string, seperator)
	{
		var hash = new Object;
		if(!string)
		{
			return hash;
		}
		seperator = seperator || ',';
		var array = string.split(seperator)
		$.each( array,
			function(i,n)
			{
				hash[n] = 1;
			}
		);
		return hash;
	},

	checkCookie : function()
	{
		if (!document.cookie)
		{
			pbx.popup.enableCookies.open();
			return false;
		}
		return true;
	},
	openHelp : function(_this)
	{
		var popup_params = 'top=100,left=200,width=800,height=650';
		popup_params += ',resizable=yes,scrollbars=yes,menubar=no,toolbar=no,location=no,status=yes';

		try
		{
			pbx.helpwin = window.open(_this.href,_this.target,popup_params);
			if (window.focus)
			{
				pbx.helpwin.focus();
			}
			return false;
		}
		catch (e)
		{
			return true;
		}
	}
};

Array.prototype.find = function(str)
{
	for(var i=0; i<this.length; i++)
	if(this[i] == str) return true;
	return false;
};
String.prototype.trim = function()
{
	return this.replace(/^\s+|\s+$/g,"");
}
String.prototype.ltrim = function()
{
	return this.replace(/^\s+/,"");
}
String.prototype.rtrim = function()
{
	return this.replace(/\s+$/,"");
}

jQuery.fn.extend(
	{
		autoEllispe : pbx.autoEllispe
	}
);
// set the option of a select
jQuery.fn.option = function (value) {
return this.each(function() {
var select = $(this)[0];
for ( var i=0; i<select.length; i++ )
if (select[i].value == value)
select.selectedIndex = i;
});
};

// Make live work without needing to instatiate a list of dom elements
$.live = function(selector, type, fn)
{
	var r = $([]);
	r.selector = selector;
	if(type && fn)
	{
		r.live(type, fn);
	}
	return r;
};
pbx.selectable =
{
	current				:	null,
	controlkey			:	null,
	action_made			:	null,
	selected			:	0,

	build							:	function(o)
	{
		if (!o)
		{
			o = {};
		}
		if (window.event)
		{
			$('body',document)
				.bind('keydown', pbx.selectable.keydown)
				.bind('keyup', pbx.selectable.keyup);
		}
		else
		{
			$(document)
				.bind('keydown', pbx.selectable.keydown)
				.bind('keyup', pbx.selectable.keyup);
		}
		this.each(
			function()
			{
				$('body',document).append('<div id="' + o.helperid + '" class="pbx_selecthelper"></div>');
				this.helper =
				{
					elt : $('div#' + o.helperid)
				};
				if(this.is_selectable)
				{
					return;
				}
				this.is_selectable = true;
				this.content_changed = true;
				this.config =
				{
					accept			:	o.accept ? o.accept : false,
					reject			:	o.reject ? o.reject: false,
					selectedclass	:	o.selectedclass ? o.selectedclass : false,
					draggable		:	o.draggable ? o.draggable : false,
					onpreselect		:	o.onpreselect ? o.onpreselect : false,
					onselect		:	o.onselect ? o.onselect : false,
					onunselect		:	o.onunselect ? o.onunselect : false,
					skip_hw_calcul	:	o.skip_hw_calcul ? o.skip_hw_calcul : false,
					checkbox		:	o.checkbox ? o.checkbox : false
				};
				if(this.config.checkbox)
				{
					var container = this;
					$(this.config.accept).find(this.config.checkbox).bind('mousedown',
						function(e)
						{
							if(window.event)
							{
								window.event.cancelBubble = true;
								window.event.returnValue = false;
							}
							else
							{
								e.preventDefault();
								e.stopPropagation();
							}
							if(!this.checked)
							{
								pbx.selectable.select(this.parentNode, container, true);
								if($.browser.safari) this.checked = true;
							}
							else
							{
								pbx.selectable.unselect(this.parentNode, container, true);
								if($.browser.safari) this.checked = false;
							}
							if(pbx.selectable.selected == 0)
							{
								if (container.config.onunselect)
								{
									container.config.onunselect();
								}
							}
							else if (container.config.onselect)
							{
								container.config.onselect();
							}
							pbx.selectable.action_made = null;
						}
					);
				}
				$(this)
					.addClass('pbx_is_selectable')
					.bind('mousedown', pbx.selectable.start);
			}
		);
		return;
	},
	destroy							:	function()
	{
		return this.each(
			function ()
			{
				if(!this.is_selectable)
				{
					return;
				}
				this.is_selectable = null;
				this.config = null;
				$(this)
					.removeClass('pbx_is_selectable')
					.unbind('mousedown', pbx.selectable.start);
			}
		);
	},
	start							:	function(e)
	{
		if(window.event)
		{
			if(window.event.button != 1)	return;						// if not a left click
			window.event.cancelBubble = true;
			window.event.returnValue = false;
			this.helper.sx = window.event.clientX;
			this.helper.sy = window.event.clientY;
		}
		else
		{
			if(e.which != 1)	return;									// if not a left click
			e.preventDefault();
			e.stopPropagation();
			this.helper.sx = e.clientX;
			this.helper.sy = e.clientY;
		}

		this.pos = jQuery.iUtil.getPos(this);							// getting the positions
		this.scr = jQuery.iUtil.getScroll($('body')[0]);

		this.helper.sx += this.scr.l;
		this.helper.sy += this.scr.t;

		$(this).append(this.helper.elt);								// move the helper inside the container (for usability purposes)

		pbx.selectable.getpos(this);

		this.helper.elt.css('display', 'block');						// display the helper

		if (this.config.onpreselect)									// run the preselect function if existing
		{
			this.config.onpreselect();
		}

		pbx.selectable.current = this;

		if (window.event)
		{
			$('body',document)
				.bind('mousemove', 	pbx.selectable.check)					// attach the onmousemove event to the container
				.bind('mouseup', 	pbx.selectable.stop);					// and the onmouseup as well
		}
		else
		{
			$(document)
				.bind('mousemove', 	pbx.selectable.check)					// attach the onmousemove event to the container
				.bind('mouseup', 	pbx.selectable.stop);					// and the onmouseup as well			}
		}

		pbx.selectable.check(e);										// then start the selection check
	},
	getpos							:	function(self)
	{
		if(self.content_changed)
		{
			if(self.config.skip_hw_calcul == true)						// specific for the album page : do not calcul size of every single images because its too long
			{
				$(self.config.accept).each(
					function ()
					{
						this.pos = jQuery.iUtil.getPositionLite(this);
						this.pos.w = pbx.album.image.img_container_w * pbx.album.image.ratio.current;
						this.pos.h = pbx.album.image.img_container_h * pbx.album.image.ratio.current;
					}
				);
			}
			else
			{
				$(self.config.accept).each(
					function ()
					{
						this.pos = $.extend($.iUtil.getPositionLite(this), $.iUtil.getSize(this))
					}
				);
			}
			self.content_changed = false;
		}
	},
	check							:	function(e)
	{
		var self = pbx.selectable.current;

		if(pbx.selectable.action_made === null)
		{
			pbx.selectable.action_made = false;
		}

		if (e)
		{
			if (window.event)
			{
				window.event.cancelBubble = true;
				window.event.returnValue = false;
				nx = window.event.clientX;
				ny = window.event.clientY;
			}
			else
			{
				e.preventDefault();
				e.stopPropagation();
				nx = e.clientX;
				ny = e.clientY;
			}
		}

		nx += self.scr.l;
		ny += self.scr.t;

		// fixing limits of the select box
		if(nx < self.pos.x)
		{
			nx = self.pos.x;
		}
		else if(nx > self.pos.x + self.pos.w)
		{
			nx = self.pos.x + self.pos.w;
		}
		if(ny < self.pos.y)
		{
			ny = self.pos.y;
		}
		else if(ny > self.pos.y + self.pos.h)
		{
			ny = self.pos.y + self.pos.h;
		}

		if(nx > self.helper.sx)
		{
			self.helper.x = self.helper.sx - self.pos.x;
			self.helper.w = nx - self.helper.sx;
			self.helper.l = self.helper.sx;
			self.helper.r = self.helper.sx + self.helper.w;
		}
		else
		{
			self.helper.x = nx - self.pos.x;
			self.helper.w = self.helper.sx - nx;
			self.helper.l = nx;
			self.helper.r = nx + self.helper.w;
		}
		if(ny > self.helper.sy)
		{
			self.helper.y = self.helper.sy - self.pos.y;
			self.helper.h = ny - self.helper.sy;
			self.helper.t = self.helper.sy;
			self.helper.b = self.helper.sy + self.helper.h;
		}
		else
		{
			self.helper.y = ny - self.pos.y;
			self.helper.h = self.helper.sy - ny;
			self.helper.t = ny;
			self.helper.b = ny + self.helper.h;
		}

		self.helper.elt.css(
			{
				left	:	self.helper.x + 'px',
				top		:	self.helper.y + 'px',
				width	:	self.helper.w + 'px',
				height	:	self.helper.h + 'px'
			}
		);
		
		// Quick fix to disable marquee select: JC commented out following function.
		/*$(pbx.selectable.current.config.accept).not(pbx.selectable.current.config.reject).each(
			function()
			{
				// if the current image is inside of the select div
				if (!(this.pos.x > self.helper.r || (this.pos.x + this.pos.w) < self.helper.l || this.pos.y > self.helper.b || (this.pos.y + this.pos.h) < self.helper.t))
				{
					// if the selection started over the element, if its draggable and if the element is not already selected
					if (pbx.selectable.action_made == false && self.config.draggable && this.s != true)
					{
						// if the control key is not pressed, unselect all element first
						if (self.config.onunselect && pbx.selectable.controlkey != true)
						{
							self.config.onunselect({keepmenu:true});			// unselect all
							pbx.selectable.selected = 1;						// then just 1 selected
						}
						else													// else
						{
							pbx.selectable.selected++;							// 1 more selected
						}
						this.s = true;											// then select the element
						$(this).addClass(self.config.selectedclass);			// style the selected element
						if(self.config.checkbox)								// if checkboxes are enable
						{
							$(this).children(self.config.checkbox)[0].checked = true;
						}
						pbx.selectable.action_made = true;						// needed for the stop{} function
						pbx.selectable.stop(e);									// stop the selection
						$(this).Draggable(eval(self.config.draggable));			// set this element draggable
						$.iDrag.draginit(e,this,true);							// then run the drag
						return;													// and stop checking
					}
					// if the element is not selected
					if (this.s != true)
					{
						pbx.selectable.action_made = true;
						pbx.selectable.select(this, self)
					}
					else if(!pbx.selectable.action_made && pbx.selectable.controlkey == true)
					{
						pbx.selectable.action_made = true;
						pbx.selectable.unselect(this, self)
					}
				}
				// else if the element is already selected and the controlkey is not pressed
				else if (this.s == true && pbx.selectable.controlkey != true)
				{
					pbx.selectable.unselect(this, self);
				}
			}
		);*/
		if(pbx.selectable.action_made !== null)
		{
			pbx.selectable.action_made = true;
		}
	},
	select							:	function(self, container, fromcheckbox)
	{
		pbx.selectable.selected++;
		self.s = true;
		$(self).addClass(container.config.selectedclass);
		if(container.config.draggable)
		{
			$(self).Draggable(eval(container.config.draggable));
		}
		if(!fromcheckbox && container.config.checkbox)
		{
			$(self).children(container.config.checkbox)[0].checked = true;
		}
	},
	unselect						:	function(self, container, fromcheckbox)
	{
		pbx.selectable.selected--;
		self.s = false;
		$(self).removeClass(container.config.selectedclass);
		if(container.config.draggable)
		{
			$(self).DraggableDestroy();
		}
		if(!fromcheckbox && container.config.checkbox)
		{
			$(self).children(container.config.checkbox)[0].checked = false;
		}
	},
	stop							:	function(e)
	{
		var self = pbx.selectable.current;

		if (window.event)
		{
			$('body',document)
				.unbind('mousemove', 	pbx.selectable.check)				// unattach the onmousemove event to the container
				.unbind('mouseup', 	pbx.selectable.stop);					// and the onmouseup as well
		}
		else
		{
			$(document)
				.unbind('mousemove', 	pbx.selectable.check)				// unattach the onmousemove event to the container
				.unbind('mouseup', 	pbx.selectable.stop);					// and the onmouseup as well			}
		}
		//pbx.selectable.checkall()
		self.helper.elt.css({	display	: 	'none',
								height	:	'0px',
								width	:	'0px'	});		// hide the helper


		// if the flag mousemoved is false, means that the user just clicked once to unselect
		if(pbx.selectable.selected == 0)
		{
			if (self.config.onunselect)
			{
				self.config.onunselect();
			}
		}
		else if (self.config.onselect)
		{
			self.config.onselect();
		}
		pbx.selectable.action_made = null;
	},
	content_changed					:	function(e)
	{
		$('.pbx_is_selectable').each(
			function()
			{
				this.content_changed = true;
			}
		);
	},
	keydown							:	function(e)
	{
		var code = (window.event) ? window.event.keyCode : e.which;
		if (code == 17)
		{
			pbx.selectable.controlkey = true;
		}
	},
	keyup							:	function(e)
	{
		var code = (window.event) ? window.event.keyCode : e.which;
		if (code == 17)
		{
			pbx.selectable.controlkey = false;
		}
	}
};
jQuery.fn.extend(
	{
		selectable : pbx.selectable.build,
		selectable_destroy : pbx.selectable.destroy
	}
);
pbx.send_friend = {

	email_list:null,
	message:null,
	url:null,

	email_field:null,
	message_field:null,
	name_field:null,
	submit_button:null,

	emailCleared:false,
	nameCleared:false,

	shareMessageMaxLength:null,
	shareMessageRemaining:null,


	init:function(params)
	{
		pbx.send_friend.email_field = $('#pbx_share_emails');
		pbx.send_friend.email_field.bind('change', pbx.send_friend.validate_emails).bind('focus', pbx.clearTextArea);
		pbx.send_friend.name_field = $('#pbx_share_name');
		pbx.send_friend.name_field.bind('change', pbx.send_friend.validate_name).bind('focus', pbx.clearTextArea);
		pbx.send_friend.theForm = $('#pbx_send_friend_form');
		pbx.send_friend.theForm.bind('submit', pbx.send_friend.send);
		pbx.send_friend.submit_btn = $('#pbx_send_friend_form');
		pbx.send_friend.submit_btn.bind('submit', pbx.send_friend.send);

		// Message length handling
		pbx.send_friend.message_field = $('#pbx_share_message');
		pbx.send_friend.shareMessageMaxLength = $('#pbx_share_message').attr('maxLength');
		pbx.send_friend.shareMessageRemaining = $('span#pbx_share_message_remaining');
		pbx.send_friend.message_field.bind('change', pbx.send_friend.validate_message).bind('keyup', pbx.send_friend.updateRemainingCount).keyup();

		// Contact email widgit init
		$('form#pbx_send_friend_form').find('div.pbx_contacts_widgit').each(
			function()
			{
				pbx.contacts.init(this,$('div#autosuggest').siblings('textarea')[0]);
			}
		);
	},

	/* Checks the email addresses. Returns list of valid emails or false if an error is found. Also prints the error message. */
	validate_emails:function()
	{
		$('#pbx_share_errors_email_empty').css('display', 'none');
		$('#pbx_share_errors_email').css('display','none');

		var email_list_str = pbx.send_friend.email_field.val();

		if (email_list_str == '')
		{
			$('#pbx_share_errors_email_empty').css('display', 'block');
			return false;
		}
		
		var validation_result = pbx.validate_email_list(email_list_str);

		if (validation_result.valid_list.length > 10)
		{
			$('#pbx_share_errors_email_toomany').css('display','block');
			validation_result.valid_list.splice(10);
		}

		if (validation_result.error_list.length > 0)
		{
			pbx.send_friend.print_email_errors(validation_result.error_list);
			return false;
		}
		else
		{
			return validation_result.valid_list;
		}
	},

	print_email_errors:function(errorList)
	{
		var error_str = errorList.join('<br/>');
		$('#pbx_send_friend_email_errors').html(error_str);
		$('#pbx_share_errors_email').css('display','block');
	},

	validate_name:function()
	{
		var name_str = pbx.validate(pbx.send_friend.name_field.val());
		if (name_str.length == 0)
		{
			$('#pbx_send_friend_noName').css('display','block');
			return false;
		}
		$('#pbx_send_friend_noName').css('display','none');
		return name_str;
	},

	validate_message:function()
	{
		$('#pbx_share_errors_min').css('display','none');
		$('#pbx_share_errors_max').css('display','none');

		var msg_str = pbx.send_friend.message_field.val();
		if (msg_str.length==0)
		{
			$('#pbx_share_errors_min').css('display','block');
			return false;
		}
		if (msg_str.length > pbx.send_friend.shareMessageMaxLength)
		{
			$('#pbx_share_errors_max').css('display','block');
			return false;
		}
		return pbx.validate(msg_str);
	},

	updateRemainingCount: function(e)
	{
		try
		{
			// check for the esc key to remove the popup.
			if (e == null)
				keycode = event.keyCode;	// ie
			else
				keycode = e.which;			// mozilla
			if(keycode == 27)				// Esc key
			{
				pbx.popup.remove(params);
				return;
			}
			
			// if the event is keydown, then just save the current text in case max number char have been reached
			var text = pbx.send_friend.message_field.val();
			var char_remaining = pbx.send_friend.shareMessageMaxLength - text.length;
			if(char_remaining < 0)
			{
				pbx.send_friend.message_field.val(pbx.send_friend.shareMessageLast);
				pbx.send_friend.shareMessageRemaining.parent().addClass('pbx_error pbx_visible');
			}
			else
			{
				if (char_remaining == 0) char_remaining = '0';	// otherwise it doesn't show.
				pbx.send_friend.shareMessageRemaining.parent().removeClass('pbx_error');
				$('#pbx_share_errors_max').css('display','none');
			}
			pbx.send_friend.shareMessageRemaining.html(char_remaining);
		}
		catch(e)
		{
			alert(e);
		}
	},

	send:function()
	{
		var details = {};
		pbx.send_friend.details = details;
		var errors = 0;
		var babel = null;

		details.tellee_emails = pbx.send_friend.validate_emails();
		if (!details.tellee_emails)
		{
			errors++;
		}
		details.personal_message = pbx.send_friend.validate_message();
		if (!details.personal_message)
		{
			errors++;
		}
		if (!pbx.babel.session.loggedIn())
		{
			details.sender_name = pbx.send_friend.validate_name();
			if (!details.sender_name)
			{
				errors++;
			}
		}
		else
		{
			details.sender_name = (pbx.babel.member.first_name && pbx.babel.member.last_name) ? (pbx.babel.member.first_name +' '+ pbx.babel.member.last_name) : (pbx.babel.member.first_name||pbx.babel.member.last_name);
		}
		details.link = pbx.popup.sendToAFriend.url;

		if (!errors)
		{
			try
			{
				details.sender_email = pbx.babel.member.email || pbx.babel.getChannelEmail();
				babel = pbx.babel.callBabel('Community.Referral.MultipleTellLink', details);
				$('#pbx_send_friend_form').css('display','none');
				$('#pbx_send_friend_thanks').css('display','block');

			}
			catch (e)
			{
				alert(e.toString());
			}

		}
		pbx.popup.action_is_done();
		return false;
	}



};
/*
 * new popup/dialog code
 * this is an extension to the jQuery ui.dialog object
 * reference jquery.ui v. 1.5.3
 *
 * example call:
 *
 *		$('#pbx_signin').click(function()
 *		{
 *			pbx.dialog.open({shortcut:'login',width:330,height:270});
 *		});

 * Depends:
 *	ui.core.js
 *  jquery.bgiframe.js
 *	ui.dialog.js
 *	ui.dialog.extended.js
 */

pbx.dialog = {

	dialog_counter : 0,
	storage: new Array(),
	currently_open : null, // The serialiseDialog() key of the last opened dialog.

	/*
	 * open()
	 *
	 * open the dialog popup
	 * parameters :
	 * title (required) string : the dialog title
	 * component (required) string : the component or shortcut of the popup to open
	 * loadRelated (optional) bool : it loads the related script in lib/popup folder using the shortcut as name
	 * width, hight (optional) number : the dimension of the dialog popup
	 * params (optional) object : additional params for the dialog that will be passed to the specific popup script
	 */
	open : function(settings)
	{
		/* Check that params is an object */
		if (typeof(settings)!='object')
		{
			params = {};
		}

		/* Key used to store in the dialog cache */
		/* NOTE: If the key is empty (no params) then the dialog will not be stored */
		var key = serialise(settings);

		/* initialise the optional params */
		var params = init(settings);

		/* Check for existing dialog in the cache */
		var dialog;
		if (key && pbx.dialog.storage[key] && pbx.dialog.storage[key].dialog)
		{
			dialog = pbx.dialog.storage[key].dialog;
			result = pbx.dialog.storage[key].result;
		}

		/*
		 * Show the cached dialog
		 */
		if(dialog && result)
		{
			/* Open dialog and add cached result */
			dialog
				.html(result) /* content must be inserted first to avoid miscalculation in dialog dimensions */
				.dialog('open')
				.dialog('hideObjects', true);
			/* specific content customisation
			 * This ensures that cached dialogs do not increase in height each time they are opened
			 */
			$('.ui-dialog-content').removeAttr('style');
		}
		/*
		 * Else create a new dialog
		 */
		else
		{
			/* set up a unique dialog id (used for binding and the container div) */
			var dialog_id = 'pbx_dialog_'+params.counter;

			/* append the dialog to the body */
			$('body').append('<div id="'+dialog_id+'" class="pbx_dialog_content"><div class="pbx_loading"></div></div>');

			/* Set dialog to the new attached html. Is there another clever way? store it in the cache */
			dialog = $('#'+dialog_id);
			pbx.dialog.storage[key] = new Object;
			pbx.dialog.storage[key].dialog = dialog;

			/* bind the close button */
			$.live('.'+dialog_id+' .pbx_dialog_close, .'+dialog_id+' .pbx_submit_cancel', 'click',
				function(e)
				{
					dialog
						.dialog('close')
						.dialog('hideObjects', false)
						.dialog('postClose');
					e.preventDefault();
				}
			);

			/* Open dialog */
			dialog
				.dialog({ width: params.width, height: params.height })
				.dialog('customise', params)
				.dialog('hideObjects', true);

			/* If we have a component fetch the result */
			if(params.component)
			{
				$.ajax(
					{
						type	: 	"POST",
						url		: 	'/includes/dialog',
						data	: 	params.params,
						dataType:	"html",
						success	: 	function(result)
						{
							dialog.dialog('addContent',result);
							finalise();
							/* store the result */
							pbx.dialog.storage[key].result = result;
						}
					}
				);
			}

			/* increment the counter */
			pbx.dialog.dialog_counter++;
		}

		/* keep a record of the currently open dialog */
		pbx.dialog.currently_open = dialog;


		/*
		 * Private functions
		 */

		/* Check the params and set any defaults if values are missing */
		function init(params)
		{
			/* define the params to pass to the loaded script as empty if not defined */
			if( !params.params ) {
				params.params = {};
			};
			/* retrieve the component from the parameters or from the shortcuts */
			if( params.component ) {
				if(params.component.search('/')!==0 ) {
					try {
						var component = eval('pbx.dialog.shortcuts.' + params.component);
						params.shortcut = params.component;
						params.component = component;
					}
					catch(error)
					{
						return params = {};
					}
				}
				/* add component=component parameter */
				params.params.component = params.component
			}
			/* width and height */
			if( params.width ) {
				params.width = params.width * 1;
			}
			if( !params.width || isNaN(params.width) ) {
				params.width = 400;
			}
			if( params.height ) {
				params.height = params.height * 1;
			}
			if( !params.height || isNaN(params.height) ) {
				params.height = 400;
			};
			/* if no title is passed, set a generic one */
			params.analyticsname = params.title = (params.title) ? params.title : "dialog title unspecified";
			/* Set the counter */
			params.counter = pbx.dialog.dialog_counter;

			return params;
		}

		/* Use the parameters to generate a unique key */
		function serialise(params)
		{
			$.each(params,
				function(key,value)
				{
					if(typeof(value) == 'object')
					{
						params.key = $.param(value);
					}
				}
			);
			return $.param(params);
		}

		function finalise()
		{
			/*
			 * load the related script
			 * look jquery.include.js
			 */
			if (typeof(params.loadRelated) !== 'undefined') {
				$.include('http://' + pbx.config.assetHost + '/assets/js/lib/dialog/' + params.shortcut + '.js?'+pbx.config.asset_last_update, function(){/*possible callback. maybe init()?*/});
			}

			// Analytics call for all popups/
			s.pageName = "popup::" + params.analyticsname;
			s.channel = "Popup Dialogues";
			s.server = window.location.hostname;
			try
			{
				void(s.t()); // The void clears all previous parameters of s.
			}
			catch(e)
			{
				// do nothing, its only analytics
			}
		}

		return dialog;
	},
	/**
	 * close the currently open dialog
	 * if clear_cache is true then the cache will also be cleared
	 */
	close : function(clear_cache)
	{
		var dialog_to_close = pbx.dialog.currently_open;
		if (clear_cache)
		{
			dialog_to_close
				.dialog('destroy')
				.dialog('hideObjects', false)
				.dialog('postClose');
			delete pbx.dialog.storage[pbx.dialog.currently_open];
		}
		else
		{
			dialog_to_close
				.dialog('close')
				.dialog('hideObjects', false)
				.dialog('postClose');
		}
	}
}

pbx.dialog.shortcuts = {
	close_account : '/my/account/close_account',
	creation_markup : '/my/creation/share/markup',
	login : '/includes/popup/login',
	payme_pt1 : '/includes/dialog/payme'
}
pbx.popup =
{
	signin			:
	{
		name		:	'login',
		height		:	245,
		width		:	267,
		login_error	:	null,
		focus		:	'input#pbx_login_email',
		precall     :   pbx.checkCookie,
		callback	:	function(params)
		{
			if(params.redirect)
			{
				$('form#pbx_loginform,form.pbx_loginform').attr('action',params.redirect);
			}
			$('span#pbx_login_unsuccessful').hide();
			$('span#pbx_login_suspended').hide();
			$('p#pbx_passwordconfirmation').hide();
			$('input#pbx_login_email').removeAttr('disabled');
			$('input#pbx_login_password').val('');

			// display error message if needed and remove the trigger from the link (then if the user close and reopen the popup, it looks normal)
			if(pbx.popup.signin.login_error)
			{
				pbx.popup.signin.login_error = null;
			}
			if(pbx.login_error)
			{
				pbx.login_error = null;
				pbx.popup.signin.login_error = true;
				$('span#pbx_login_error').remove();
				$('span#pbx_login_unsuccessful').show();
				$('span#pbx_login_suspended').remove();
			}
			if(pbx.account_suspended)
			{
				pbx.account_suspended = null;
				pbx.popup.signin.account_suspended = true;
				$('span#pbx_login_error').remove();
				$('span#pbx_login_unsuccessful').remove();
				$('span#pbx_login_suspended').show();
			}
			if(params.password_confirmation)
			{
				$("a#pbx_passwordforgotten_confirmation").remove();
				$('p#pbx_passwordconfirmation').show();
				$('input#pbx_login_email')
					.attr('disabled','disabled')
					.val(params.email);
				$('input#pbx_login_password')[0].focus();
				params.password_confirmation = false;
			}
			else
			{
				$('input#pbx_login_email')[0].focus();
			}
			$('form#pbx_loginform,form.pbx_loginform').bind('submit',
				function()
				{
					$('input#pbx_login_email').removeAttr('disabled');

					//slideshow specific code
					if(typeof(pbx.babel.slideshow) !== 'undefined')
					{
						var returnvalue = pbx.babel.login($('input#pbx_login_email').val(), $('input#pbx_login_password').val());
						returnvalue +=''; //convert to string
						if(returnvalue.match('201|202|203|220'))
						{
							$('.pbx_error').css('display', 'block');
						}
						else
						{
							pbx.babel.slideshow.event.doLoginSuccess(pbx.babel.session.code);
							pbx.popup.remove();
						}
						return false;
					}
				}
			);

			if(params.registerpopup === true || params.registerpopup == "true")
			{
				$('a#pbx_signin_joinnow').unbind('click').bind('click',
					function() {
						pbx.popup.open({ _this : this, settings : 'pbx_popup_register', redirect : params._this.href });
						pbx.popup.remove(params);
						return false;
					}
				);

				$('input#pbx_submit_login').unbind('click').bind('click',
					function(){
						$('form#pbx_loginform,form.pbx_loginform').attr('action',params._this.href);
						pbx.popup.remove(params);
						return true;
					}
				);
			}

			//slideshow specific code
			if(typeof(pbx.babel.slideshow) !== 'undefined')
			{
				pbx.babel.slideshow.event.doLoginSuccess();
				return false;
			}
		}
	},
	forgottenpassword	:
	{
		name		:	'forgotten_password',
		height		:	245,
		width		:	265,
		callback	:	function(params)
		{
			//pre compile email field if emails is passed
			the_email = params.email || "";

			$('input#pbx_passwordforgotten_email')
				.val(the_email)
				.focus();
			$('form#pbx_forgottenpassword').bind('submit',
				function()
				{
					$('label').removeClass('pbx_error');
					$('span#pbx_passwordforgotten_bad_email').hide();
					$('span#pbx_passwordforgotten_noregistered_email').hide();
					if($('input#pbx_passwordforgotten_email').val() === '') // test first if the email is not empty
					{
						$('input#pbx_passwordforgotten_email')
							.prev()
							.addClass('pbx_error');
						pbx.popup.action_is_done();
						$('span#pbx_passwordforgotten_bad_email').show();
					}
					else
					{
						var email = $('input#pbx_passwordforgotten_email').val();
						var reset_password = pbx.babel.reset_password(email);

						if(reset_password == 509)			//	Email address does not belong to a registered member')
						{
							$('input#pbx_passwordforgotten_email')
								.prev()
								.addClass('pbx_error');
							pbx.popup.action_is_done();
							$('span#pbx_passwordforgotten_noregistered_email').show();
						}
						else if(reset_password == 508)		// Invalid email address entered (eg no @ symbol found)
						{
							$('input#pbx_passwordforgotten_email')
								.prev()
								.addClass('pbx_error');
							pbx.popup.action_is_done();
							$('span#pbx_passwordforgotten_bad_email').show();
						}
						else
						{
							var href = $("a#pbx_passwordforgotten_confirmation").attr('href');
							$("a#pbx_passwordforgotten_confirmation")
								.attr('href', href + '&email=' + email)
								.insertAfter("#pbx_popup_window");
							$("#pbx_overlay").click();
							pbx.popup.timer = setTimeout("$('a#pbx_passwordforgotten_confirmation').click()",200);
						}
					}

					return false;
				}
			);
		}
	},
	changepassword		:
	{
		name		:	'change_password',
		height		:	245,
		width		:	320,
		callback	:	function(params)
		{
			pbx.register.change_password_init(params);
		}
	},
	changepaypassword		:
	{
		name		:	'change_pay_password',
		height		:	245,
		width		:	320,
		callback	:	function(params)
		{
			pbx.checkout.payment.change_password_init(params);
		}
	},
	changeemail :
	{
		name		:	'change_email',
		height		:	245,
		width		:	450,
		callback	:	function(params)
		{
			$("#pbx_close").hide();
			$('#pbx_change_success').hide();
			$('#pbx_submit_changeemail').bind('click', pbx.popup.changeemail.process_change).bind('submit', pbx.popup.changeemail.process_change);
		},

		process_change : function()
		{
			try
			{
				$('label').removeClass('pbx_error');

				$("#pbx_currentemail_error").hide();
				$("#pbx_newemailnotvalid_error").hide();
				$("#pbx_emailnotdifferent_error").hide();
				$("#pbx_emailnotmatch_error").hide();
				$("#pbx_emailinuse_error").hide();
				$('span#pbx_email_error').hide();
				$("#pbx_close").hide();

				var current_email = $('input#pbx_current_email').val().toLowerCase();
				var new_email = $('input#pbx_new_email').val().toLowerCase();
				var new_email_confirm = $('input#pbx_retype_email').val().toLowerCase();
				var member_email = pbx.babel.member.email.toString().toLowerCase();


				if (current_email != member_email)
				{
					$('#pbx_current_email').prev().addClass('pbx_error');
					$('#pbx_currentemail_error').show();
				}
				else if(!pbx.validate(new_email, 'email'))
				{
					$('#pbx_new_email').prev().addClass('pbx_error');
					$('#pbx_newemailnotvalid_error').show();
				}
				else if(new_email == member_email)
				{
					$('#pbx_new_email').prev().addClass('pbx_error');
					$('#pbx_emailnotdifferent_error').show();
				}
				else if(new_email_confirm != new_email)
				{
					$('#pbx_retype_email').prev().addClass('pbx_error');
					$('#pbx_emailnotmatch_error').show();
				}
				else
				{
					try
					{
						pbx.babel.member.callBabel('Set', {email:new_email});
						pbx.babel.member = pbx.babel.getMember();
						$('#pbx_change_success').show();
						$("#pbx_submit").hide();
						$("#pbx_cancel").hide();
						$("#pbx_close").show().focus();
					}
					catch (e)
					{
						pbx.popup.action_is_done();
						$('span#pbx_email_error').show();
					}
				}
				pbx.popup.action_is_done();
				return false;
			}
			catch (e)
			{
				alert(e);
			}
			return false;
		}
	},
	register			:
	{
		name		:	'register',
		height		:	500,
		width		:	500,
		precall     :   pbx.checkCookie,
		callback	:	function(params)
		{
			pbx.register.init();
			pbx.dateselect.init();
			$("input#pbx_button_register").unbind('click');
			$("input#pbx_button_register").bind('click',
				function()
				{
					var check = null;
					var url = null;
					
					check = pbx.register.check_all();
					if(check)
					{
						var register_settings =
						{
							title		: $('#pbx_customer_title').val() || pbx.getRadioValue('pbx_register_form', 'customer_title'),
							first_name	: $('#pbx_customer_first_name').val(),
							last_name	: $('#pbx_customer_last_name').val(),
							email		: $('#pbx_customer_email').val(),
							country		: $('#pbx_customer_country').val() || pbx.babel.session.country_id,
							mobile		: $('#pbx_customer_mobile').val(),
							news		: $("input[id='customer_news_yes']:checked").length,
							offers		: $("input[id='customer_offers_yes']:checked").length,
							set_password	: { password : $('#pbx_customer_password').val() }
						};
						var babel;
						try
						{
							babel = pbx.babel.callBabel('Community.Member.New', register_settings);

							if(params.redirect)
							{
								url = params.redirect;
							}
							else
							{
								url = window.location.href;
								var anchor_pos = url.indexOf('#');
								if(anchor_pos != -1)
								{
									url = url.substring(0, anchor_pos);
								}
							}
							// Make analytics request
							pbx.analytics.regsiterUser();

							var query_pos = url.indexOf('?');

							if (query_pos != -1)
							{
								url = url + '&track=registered';
							}
							else
							{
								url = url + '?track=registered';
							}

							/* do not redirect for the slideshow */
							if(typeof(pbx.babel.slideshow)=='undefined')
							{
								window.location.href = url;
							}
							else
							{
								pbx.babel.init();

								pbx.babel.slideshow.event.doJoinSuccess(pbx.babel.session.code);
								pbx.popup.remove();
							}
						}
						catch(e)
						{
							if($.browser.msie)
							{
								e.message = (e.message == 'Anemailaddressmustbesupplied') ? '503' : '501';
							}
							$('span#pbx_error' + e.message).addClass('pbx_visible');

							pbx.register.init();
							$("input#pbx_button_register").unbind('click',pbx.register.check_all);
						}
					}
					pbx.register.busy = false;
					return false;
				}
			);
		}
	},
	movecopy			:
	{
		name		:	'move_copy',
		height		:	400,
		width		:	400,
		params		:
		{
			nb_images	:	"params.photo_id.length",
			album_id	:	"pbx.album.id"
		},
		callback	:	function(params)
		{
			$('select#pbx_album_selector').children('option[value="' + pbx.album.id + '"]').remove();
			$('select#pbx_album_selector')[0].selectedIndex = 0;
			$('input#pbx_album_new')[0].value = "";
			$('input#pbx_album_new')[0].disabled = "disabled";
			$('select#pbx_album_selector').bind('change',
				function()
				{
					if(this.value === 0)
					{
						$('p#pbx_newalbum')
							.removeClass('pbx_disabled')
							.children('input')
							.removeAttr('disabled');
					}
					else
					{
						$('p#pbx_newalbum')
							.addClass('pbx_disabled')
							.children('input')
							.attr('disabled','disabled')
							.attr('value','');
					}
				}
			);
			$('input#pbx_submit_save').unbind('click').bind('click',
				function()
				{
					try
					{
						$('span#pbx_movecopy_noname').hide();
						$('input#pbx_album_new').prev().removeClass('pbx_error');
						var selcted_album_index = $('select#pbx_album_selector')[0].selectedIndex;
						var album_destination_id = $('select#pbx_album_selector')[0].options[selcted_album_index].value;
						album_destination_id = album_destination_id.replace(/\D/g, '');
						var refresh_menu = false;

						// if a new album has been chosen
						if(album_destination_id == "0")
						{
							// check if the name has been entered, else return error message
							if($('input#pbx_album_new')[0].value == "")
							{
								$('input#pbx_album_new').prev().addClass('pbx_error');
								$('span#pbx_movecopy_noname').show();
								return false;
							}
							// create the album
							var newName = pbx.validate($('input#pbx_album_new')[0].value);
							var album_destination = pbx.babel.member.callBabel('CreateAlbum', {name:newName}).response;
							album_destination_id = album_destination.id;
							refresh_menu = true;
						}
						if(!album_destination)	// if the album hasn't been created
						{
							var album_destination = pbx.babel.callBabel('Community.Album.Fetch', album_destination_id).response;
						}

						// copy the selection
						if($('input#pbx_copy')[0].checked == true)
						{
							pbx.copy_photos(album_destination, params.photo_id);
						}
						// or move it
						else if($('input#pbx_move')[0].checked == true)
						{
							var album_id = pbx.album.id;//pbx.get_params_from_url(window.location.href).album_id;
							var album = pbx.babel.callBabel('Community.Album.Fetch', album_id).response;
							pbx.move_photos(album, album_destination, params.photo_id);
							$('div.pbx_thumb.pbx_selected').remove();
							if(pbx.album.album_page_loaded)
							{
								pbx.album.photocount_update(-1 * params.photo_id.length);
								pbx.album.content_changed();
								pbx.album.unselect_all();
							}
							refresh_menu = true;
						}
						// if menu need to be refreshed, do it then close the popup once its done
						$.ajax(	{ 	type		: 	"POST",
									url			: 	"/includes/ajax/album_selector",
									success		: 	function(result)
													{
														$('span#pbx_album_selector_wrapper').html(result);
														if(refresh_menu)
														{
															pbx.menu_album_tree_refresh(
																function()
																{
																	pbx.popup.remove(params);
																	if(params.onComplete)
																	{
																		params.onComplete();
																	}
																}
															);
														}
														else
														{
															pbx.popup.remove(params);
															if(params.onComplete)
															{
																params.onComplete();
															}
														}
													}
								}	);
					}
					catch(e)
					{
						alert(e);
					}
					return false;
				}
			);
		}
	},
	objectdetails 		:
	{
		name		: 'object_details',
		height		: 500,
		width		: 500,
		focus		: "#pbx_object_details_name",
		params	:
		{
			object_id 		: "params.object_id",
			object_type	: "params.object_type"
		},
		setNewDetailsOnPage : function(newparams)
		{
			/*
			* TODO: adapt this function to be more generic
			* split-it in mini functions related to the page where the popup is called
			* or better use the FIND jQuery function and a class name in each page where this function is needed
			*/

			/* change the name displayed */
			$('div[id*=_'+newparams.id+'] .pbx_object_name').autoEllispe(newparams.name,140);

			/* change all relative titles an alt attributes */
			$('div[id*=_'+newparams.id+'] .pbx_object_name').attr("title", newparams.name);
			$('div[id*=_'+newparams.id+'] img').attr("alt", newparams.name);
			$('.pbx_myphotobox_thumbnail_link').attr("title", newparams.name);
			/* change description if displayed */
			$('span[id*=_'+newparams.id+'] .pbx_object_description').text(newparams.desc);

			/* change the album name in the menu if there */
			$('#pbx_menu_album_'+newparams.id+' span.albumName').text(newparams.name);
			$('#pbx_menu_album_'+newparams.id).attr("title", newparams.name);

			/* chage the cover where applied (my albums tab) */
			if (newparams.cover && pbx.my.loaded)
			{
				//change the photo in my object with the new one
				//my['pbx_album_'+newparams.id]['photo_id']=newparams.cover;
				// reload the cover
				//$('div[id*=_'+newparams.id+'_]').loadCovers();
				pbx.my.updateThumbnail(newparams.id, null, newparams.type);
			}

			/* album page changes */
			$('#pbx_title_album').autoEllispe(newparams.name,400); //album page
			$('#pbx_title_album').attr("title", newparams.name);
			$('#pbx_album_description').html(newparams.desc);
			/* reload the entire box if album */
			if (newparams.type.match(/^album/) && newparams.id!=='upload') { pbx.menu_album_tree_refresh(); }

			/* photo page changes */
			$('#pbx_title_photo').autoEllispe(newparams.name,400);
			$('span#pbx_photo_name').autoEllispe(newparams.name,120);

			/* save links to edit tags and desc before appending their containers */
			var desc_edit_link = $('span#pbx_photo_description a').clone();
			var tags_edit_link = $('span#pbx_photo_tags a').clone();
			$('span#pbx_photo_description a').remove();
			$('span#pbx_photo_tags a').remove();
			$('span#pbx_photo_description').autoEllispe(newparams.desc,120).append(desc_edit_link);
			$('span#pbx_photo_tags').autoEllispe(newparams.tags,120).append(tags_edit_link);

			(newparams.desc === '') ? $('a#set_desc_link').removeClass('pbx_hidden') : $('a#set_desc_link').addClass('pbx_hidden');
			(newparams.tags === '') ? $('a#set_tag_link').removeClass('pbx_hidden') : $('a#set_tag_link').addClass('pbx_hidden');

			/* upload aurigma page */
			$('input[name=album_name]').val(newparams.name);
			$('input[name=album_description]').val(newparams.desc);
			$('input[name=album_tags]').val(newparams.tags);
			if(newparams.id=='upload') { $('#pbx_upload_create_album_name').blur(); } // from upload.js file

		},
		sendNewDetailsToBabel : function(params, newparams)
		{
			var functionToCall;

			//choose the right function to call
			switch(newparams.type)
			{
				case "photo":
					functionToCall = 'Community.Photo.Fetch';
					break;

				case "creation":
				case "creations":
					functionToCall = 'Community.Creation.Fetch';
					break;

				case "album":	// Need both as myPhotobox uses 'albums' throughout. Other pages just have 'album'
				case "albums":
				case "album_shared":
					functionToCall = 'Community.Album.Fetch';
					break;

				default:
					alert("error");
			}

			//load the babel object
			if (newparams.id != "new")
			{
				babel = pbx.babel.callBabel(functionToCall, newparams.id);
			}

			//create the proper object for the babel call
			var babelparams	 = {};
			// only set the cover if it's set - works fine for creations and photos too
			if (newparams.cover)
			{
				babelparams.cover_photo_id=newparams.cover;
			}
			babelparams.name=newparams.name;
			babelparams.description=newparams.desc;
			//hack to add photo tags. look babeldoc.
			if(newparams.type!=="photo") { babelparams.tags=pbx.validate(newparams.tags); }

			//set new parameters to an unexistent album
			if (newparams.id == "upload")
			{
				pbx.popup.objectdetails.setNewDetailsOnPage(newparams);
			}
			//create an album and set new parameters
			else if (newparams.id == "new")
			{
				pbx.babel.member.callBabel('CreateAlbum', babelparams, function(babel)
					{
						pbx.popup.objectdetails.postBabelSend(babel, params, newparams);
					}
				);
			}
			//standard set new parameters to an existing album
			else
			{
				babel.response.callBabel('Set', babelparams, function()
					{
						pbx.popup.objectdetails.postBabelSend(babel, params, newparams);
					}
				);
			}
		},
		postBabelSend : function(babel, params, newparams)
		{
			//hack to add photo tags. look babeldoc. //validation occur in album.js inside function
			if(newparams.type=="photo") { pbx.album.addPhotoTags([newparams.id], newparams.tags, 1); }

			params[newparams.type] = babel.response;

			if(params.after)
			{
				eval(params.after.replace(/_/g, '.') + '(params)');
			}
			if(params.object_id == "new")
			{
				pbx.popup.remove(params);
				pbx.show_overlay(true);
				pbx.show_loading(true);
				window.location.href = $('span#pbx_menu_album_page_url').text().replace('--albumid--', params.album.id);
				return false;
			}
			// update the page with new values
			pbx.popup.objectdetails.setNewDetailsOnPage(newparams);

			//finalize
			pbx.popup.objectdetails.finalize(params, newparams);

			return false;
		},
		finalize : function(params, newparams) //last common operations
		{
			if (params.do_page_refresh)
			{
				window.location.reload();
			}
			else
			{
				/* Close the popup */
				pbx.popup.remove(pbx.popup.objectdetails.params);

				/* Change the details in the cached Popup */
				$('input#pbx_object_details_name').val(newparams.name);
				$('textarea#pbx_object_details_description').html(newparams.desc);
				$('textarea#pbx_object_details_tags').html(newparams.tags);
			}
		},
		callback : function(params)
		{
			//fill the fields on popup when needed
			/* upload aurigma page */
			$('input#pbx_object_details_name').val($('input[name=album_name]').val());
			$('textarea#pbx_object_details_description').val($('input[name=album_description]').val());
			$('textarea#pbx_object_details_tags').val($('input[name=album_tags]').val());


			$('input#pbx_objectdetails_save').bind('click',
				function()
				{
					// declare the newparams object and validate all variables
					var newparams =
					{
						cover : $('select#pbx_object_cover_select').val(),
						name : pbx.validate($('input#pbx_object_details_name').val()),
						desc : pbx.validate($('textarea#pbx_object_details_description').val()),
						//do not validate tags here but just before submit
						tags : $('textarea#pbx_object_details_tags').val(),
						type : params.object_type,
						id : params.object_id
					};

					//call babel if not upload
					if (newparams.id !== 'upload')
					{
						// cut too long strings
						if (newparams.name.length > 255)
						{
							newparams.name = newparams.name.substr(0, 255);						
						}
						if (newparams.desc.length > 255)
						{
							newparams.desc = newparams.desc.substr(0, 255);
						}
						if (newparams.tags.length > 255)
						{
							newparams.tags = newparams.tags.substr(0, 255);
						}
						// send new parameters to backend
						pbx.popup.objectdetails.sendNewDetailsToBabel(params, newparams);
					}
					else
					{
						//just set new params to page
						pbx.popup.objectdetails.setNewDetailsOnPage(newparams);

						//finalize
						pbx.popup.objectdetails.finalize(params, newparams);
					}
					return false;
				}
			);
		}
	},
	basketitemdelete:
	{
		name		:	'delete_basket',
		height		:	245,
		width		:	250,
		focus		:	'#pbx_deletebasket_ok',
		params	: {
			upsell_effect : "params.upsell_effect"
		},
		callback	:	function(params)
		{
			if (params.upsell_effect == 'is')
			{
				$('.pbx_basket_delete_offer').removeClass('pbx_hidden');
			}
			else
			{
				$('.pbx_basket_delete_offer').addClass('pbx_hidden');
			}
			
			if (params.upsell_effect == 'has')
			{
				$('.pbx_basket_delete_affects_offer').removeClass('pbx_hidden');
			}
			else
			{
				$('.pbx_basket_delete_affects_offer').addClass('pbx_hidden');
			}

			$('input#pbx_deletebasket_ok').bind('click',
				function()
				{
					var row = $(params._this).parent().parent();
					$(row).find('input.pbx_basket_form_delete').attr('checked','checked');

					pbx.popup.remove(params);
					pbx.show_overlay(true);
					pbx.show_loading(true);
					document.pbx_basket_form.submit();
					return false;
				}
			);
		}
	},
	basketofferremove:
	{
		name		:	'remove_special_offer',
		height		:	245,
		width		:	250,
		focus		:	'#pbx_deletebasket_ok',
		params	: {
			offer_text: "params.offer_text"
		},
		callback	:	function(params)
		{
			$('input#pbx_deletebasket_ok').bind('click',
				function()
				{
					var row = $(params._this).parent().parent();
					$(row).find('input.pbx_basket_form_delete').attr('checked','checked');
					pbx.popup.remove(params);
					pbx.show_overlay(true);
					pbx.show_loading(true);
					document.pbx_basket_form.submit();
					return false;
				}
			);
		}
	},
	emptybasket:
	{
		name		:	'empty_basket',
		height		:	245,
		width		:	250,
		focus		:	'#pbx_emptybasket_ok',
		callback	:	function(params)
		{
			$('input#pbx_emptybasket_ok').bind('click',
				function()
				{
					pbx.popup.remove(params);
					if(pbx.basket.loaded)
					{
						pbx.show_overlay(true);
						pbx.show_loading(true);
						$("input[name='empty']").val('1');
						document.pbx_basket_form.submit();
					}
					else
					{
						pbx.babel.EmptyBasket(
							function()
							{
								pbx.babel.basketcount_update('0','0');
								$('div#pbx_popup_cart').addClass('pbx_disabled');
							}
						);
					}
					return false;
				}
			);
		}
	},
	noUpsellEditing:
	{
		name : 'no_upsell_editing',
		height : 245,
		width : 250,
		dialog : 'ok',
		open : function(_this)
		{
			pbx.popup.open({ _this : _this, settings : 'pbx_popup_noUpsellEditing'});
		}
	},
	orderprint:
	{
		name		:	'order_prints',
		height		:	300,
		width		:	400,
		focus		:	'#pbx_product_id',
		precall     :   pbx.checkCookie,
		params		:
		{
			product_id	: "params.product_id",
			mode		: "params.mode",
			nb_total	: "params.nb_total",
			nb_uploaded	: "params.nb_uploaded",
			nb_selected	: "params.nb_selected",
			go_to_basket: "params.go_to_basket",
			object_type : "params.object_type",
			object_id : "params.object_id"
		},
		/* Fetches the style list for the product selected in select#pbx_product_id,
		 * updates select#pbx_style_id and the upsell data (unless skip_upsell is true).
		 * Returns the number of styles available for the product. */
		getStyle	: 	function(skip_upsell, defaultStyleId)
		{
			var pid = $('select#pbx_product_id').val();
			var styles_dropdown = $("select#pbx_style_id");
			var styles = (pbx.babel.getStyle(pid));
			if(styles.length > 0)
			{
				styles_dropdown.removeAttr('disabled');
				var new_html = '';
				for(var b=0; b<styles.length; b++)
				{
					var selectedString = (defaultStyleId && defaultStyleId == styles[b].id) ? ' selected="selected"' : '';
					new_html += '<option value="' + styles[b].id + '"' + selectedString + '>' + styles[b].name + '</option>';
				}
				styles_dropdown.html(new_html);
			}
			else
			{
				styles_dropdown.attr('disabled','disabled').html('<option value="" />');
			}

			if(!skip_upsell)
			{
				// added feature: need to load as well product description (FS#2732)
				var longdesc_holder = $('div#pbx_orderpopup_longdesc span');
				if(longdesc_holder.length)
				{
					var longdesc = pbx.babel.product.longdescription.toString();
					if(longdesc.length > 303)
					{
						longdesc = longdesc.substring(0,300) + '...';
					}
					longdesc_holder.html(longdesc);
					pbx.babel.product.callBabel('GetExtendedPrice', null,
						function(babel)
						{
							$('div#pbx_orderpopup_longdesc b').html(babel.response.toString());
						}
					);
				}

				// added feature : upsell ECO vs Premium
				var upsell_container = $('#pbx_popup_upsell');
				var upsell_content = upsell_container.children('p#pbx_popup_upsell_content');
				if(parseInt(pbx.babel.product.upsell_product_id))
				{
					$.ajax(
						{ 	type		: 	"POST",
							url			: 	"/includes/ajax/upsell_popup",
							data		: 	"pid=" + pbx.babel.product.id.toString() + "&new_pid=" + pbx.babel.product.upsell_product_id,
							success		: 	function(upsell)
											{
												if(upsell_container.css('display') == 'none')
												{
													upsell_container.slideDown('fast',
														function()
														{
															upsell_content.fadeIn();
														}
													);
												}
												upsell_content.html(upsell);
												$('a.pbx_switch2premium').bind('click',
													function()
													{
														$("select#pbx_product_id option[value=" + pbx.babel.product.upsell_product_id + "]").attr('selected','selected');
														$("select#pbx_product_id").change();
													}
												);
											}
						}
					);
				}
				else if(upsell_container.css('display') != 'none')
				{
					upsell_content.fadeOut();
					upsell_container.slideUp('fast');
				}
			}
			return styles.length;
		},
		fillValues	: 	function(params)
		{
			params.pid = $('select#pbx_product_id').val();
			params.style = $('select#pbx_style_id').val();
			params.newquantity = parseInt($('input#pbx_product_qty').val());
			params.newitem = $('input#pbx_product_new').attr('checked');
		},
		checknumber	:	function()
		{
			var frantic_block_large_albums = 2;
			//oldValue = parseInt($('#pbx_product_qty').attr("oldValue"), 10);
			if($('#pbx_product_qty').attr('value').match(/^\s*\d+\s*$/) === null)
			{
				$('span#pbx_invalid_number').show();
				$('span#pbx_zero_number').hide();
				return false;
			}
			newValue = parseInt($('#pbx_product_qty').attr('value'), 10);
			if(isNaN(newValue)) // it should never happen with regular expression before...
			{
				$('span#pbx_invalid_number').show();
				$('span#pbx_zero_number').hide();
				return false;
			}
			else if(newValue <= 0)
			{
				$('span#pbx_invalid_number').hide();
				$('span#pbx_zero_number').show();
				return false;
			}
			else
			{
				$('span#pbx_invalid_number').hide();
				$('span#pbx_zero_number').hide();
				return true;
			}
		},
		callback	:	function(params)
		{
			// If frantic mode is active then the order popup will only have this element.
			if ($('div#pbx_order_prints_popup_blocked').length > 0)
			{
				return;
			}

			$("select#pbx_style_id").attr('disabled','disabled');	// SAFARI HACK : visible by default but hidden at the load, to get a correct height

			// update details for cached popups
			if(params.product_id)
			{
				$("select#pbx_product_id").children("option[value="+params.product_id+"]").attr("selected","selected");
			}
			else
			{
				$("select#pbx_product_id").children("option[value="+pbx.babel.get_preference('default_product')+"]").attr("selected","selected");
			}
			pbx.popup.orderprint.getStyle(false, (params.style_id) ? params.style_id : pbx.babel.get_preference('default_style'));
			// Are we actually changing something in the basket
			if(params.mode == 'pbx.basket.changeItem' || params.mode == 'pbx.basket.changeItems' || params.mode == 'pbx.basket.changeProduct' || params.mode == 'pbx.order.changeItem')
			{
				$('input#pbx_submit_save').parent().removeClass('pbx_hidden');
				$('input#pbx_submit_order').parent().addClass('pbx_hidden');
				$("div#pbx_popup_advanced").addClass('pbx_hidden');
				// show the as new tickbox
				$("p#pbx_popup_asnew").removeClass('pbx_hidden');
				if(params.mode == 'pbx.basket.changeItem')
				{
					$('input#pbx_product_qty').val($(params._this).parent().siblings('td.pbx_basket_item_quantity').children('input').val().toString());
				}
				else if(params.mode == 'pbx.order.changeItem')
				{
					$('input#pbx_product_qty').val($(pbx.order.getRow(params._this)).find('input.pbx_order_form_quantity').val());
				}
				else
				{
					$('input#pbx_product_qty').val('1');
				}
			}
			else
			{
				$('input#pbx_submit_save').parent().addClass('pbx_hidden');
				$('input#pbx_submit_order').parent().removeClass('pbx_hidden');
				$("div#pbx_popup_advanced").removeClass('pbx_hidden');
				$("p#pbx_popup_asnew").addClass('pbx_hidden');
			}
			if(params.mode == 'pbx.album.order')
			{
				var nb_uploaded = $('input.pbx_uploaded_ids').length;
				var nb_selected = $("div#pbx_myalbum div.pbx_thumb.pbx_selected").length;
				var nb_total = parseInt(pbx.album.albums[pbx.album.id].photo_count.toString());
				var uploaded_order = $('p#pbx_uploaded_order');
				var selected_order = $('p#pbx_selected_order');
				var all_order = $('p#pbx_all_order');

				if(uploaded_order.length > 0 && nb_uploaded > 0 && (nb_uploaded != nb_total))					// if some photos have been uploaded
				{
					uploaded_order.removeClass('pbx_hidden');					// show the line
					params.type = 'uploaded';
					uploaded_order.children('input').bind('click',
						function()
						{
							params.type = 'uploaded';
						}
					);
				}
				else
				{
					uploaded_order.children('input').removeAttr('checked');		// uncheck the hidden option
					selected_order.children('input').attr('checked','checked');	// and check the next one
					params.type = 'album';
				}
				if(selected_order.length > 0 && nb_selected > 0)												// if some photos have been selected
				{
					selected_order.removeClass('pbx_hidden');					// show the line
					params.type = 'selected';
					selected_order.children('input').bind('click',
						function()
						{
							params.type = 'selected';
						}
					);

				}
				if(nb_uploaded == 0 && nb_selected == 0)						// if no photo have been uploaded or selected
				{
					uploaded_order.children('input').removeAttr('checked');		// uncheck hidden options
					selected_order.children('input').removeAttr('checked');
					all_order.children('input').attr('checked','checked'); 		// and check "all album" option
					params.type = 'album';
				}
				else
				{
					all_order.removeClass('pbx_hidden');
					all_order.children('input').bind('click',
						function()
						{
							params.type = 'album';
						}
					);
				}
			}
			$("#pbx_product_id").bind('change', function() { pbx.popup.orderprint.getStyle(false, (params.style_id) ? params.style_id : pbx.babel.get_preference('default_style')); } );
			/*$("input#pbx_product_qty").click(
				function()
				{
					$(this).attr("oldValue",this.value);
				}
			);*/
			$("#pbx_product_qty").bind('blur', pbx.popup.orderprint.checknumber);
			//$('#pbx_submit_order').bind('click', function()
			$('#pbx_order_prints_popup').submit(
				function()
				{
					if(pbx.popup.orderprint.checknumber())
					{
						if (params.go_to_basket)
						{
							eval(params.mode + '(params)');
						}
						else
						{
							pbx.popup.orderprint.fillValues(params);
							pbx.popup.remove(params);
							pbx.show_overlay(true);
							pbx.show_loading(true);
							eval(params.mode + "(params)");
						}
					}
					else
					{
						pbx.popup.action_is_done();
					}
					return false;
				}
			);
			$('#pbx_order_adv_options').not('.pbx_disabled').bind('click', function()
				{
					if (params.mode == 'pbx.album.order' || params.mode == 'pbx.search.orderAll' || (params.mode == 'pbx.my.objectOrder' && params.object_type.match(/^album/)))
					{
						params.use_config = true;
						eval(params.mode + '(params)');
					}
					else
					{
						pbx.babel.config_order(params);
					}
					return false;
				}
			);

			// bind keys
			document.onkeydown = function(e)
			{
				if (e == null)		keycode = event.keyCode;		// ie
				else				keycode = e.which;				// mozilla
				if (keycode == 13)
				{
					$('div#pbx_popup_content input[type=submit]').click();
				}
			};

		}
	},
	ordercreation:
	{
		name		:	'order_creations',
		height		:	345,
		width		:	400,
		precall     :   pbx.checkCookie,
		params		:
		{
			mode		: "params.mode",
			object_id	: "params.object_id"
		},
		fillValues	: 	function(params)
		{
			params.newquantity = parseInt($('input#pbx_product_qty').val());
		},
		callback	:	function(params)
		{
			if(params.mode == 'pbx.basket.changeItem' || params.mode == 'pbx.basket.changeItems' || params.mode == 'pbx.basket.changeProduct')
			{
				$("p#pbx_popup_asnew").show();
			}
			else
			{
				$("p#pbx_popup_asnew").hide();
			}
			$('span#pbx_product_name').html(my['pbx_creation_' + params.object_id].product_name);
			$("input#pbx_product_qty").bind('blur', pbx.popup.orderprint.checknumber);
			$('input#pbx_submit_order').bind('click',
				function()
				{
					if(pbx.popup.orderprint.checknumber())
					{
						pbx.popup.ordercreation.fillValues(params);
						pbx.popup.remove(params);
						pbx.show_overlay(true);
						pbx.show_loading(true);
						eval(params.mode + "(params)");
					}
					else
					{
						pbx.popup.action_is_done();
					}
					return false;
				}
			);
		}
	},
	orderSharedCreation:
	{
		name		:	'order_shared_creation',
		height		:	345,
		width		:	400,
		precall     :   pbx.checkCookie,
		params		:
		{
			album_id		: "params.album_id",
			creation_id	: "params.creation_id"
		},
		callback	:	function(params)
		{
			// fire the analytics order event
			pbx.analytics.orderCreation();

			$('form#pbx_order_shared_creation_popup').bind('submit', function(){
				try{
					$(this).ajaxSubmit(
						{
							url				: '/?layout=ajax',
							beforeSubmit	: function()
							{
								var qty = $('div#pbx_popup_window').find('input.pbx_order_form_quantity').val();
								pbx.popup.remove(params);
								scrollTo(0,0);
								$('span#bubblebasket').each(function(){
									pbx.i18nplural('bubblebasket', qty);
								});
								pbx.ordering = 1; // because bubble uses mouseover event, we need this to stop the rollover cart popup being fired
								pbx.bubble_show('a#pbx_basket_link', '200px');
								$('div#pbx_popup_cart').removeClass('pbx_disabled');
							},
							success			: function()
							{
								$('span.pbx_bubble_async_status').html(100)
								pbx.babel.basketcount_update();
								setTimeout("pbx.bubble_hide('a#pbx_basket_link', true)", 3000);
								pbx.ordering = 0;

								// fire the analytics order event
								pbx.analytics.orderCreationPopup();
							}
						});
					}
					catch (e)
					{
						$('span.pbx_bubble_async_status').html(100)
						pbx.babel.basketcount_update();
						setTimeout("pbx.bubble_hide('a#pbx_basket_link', true)", 3000);
						pbx.ordering = 0;
					}

				return false;
			});
		}
	},
	duplicatecreation:
	{
		name		:	'duplicate_creation',
		height		:	345,
		width		:	355,
		callback	:	function(params)
		{
			$('input#pbx_creation_name').val($('input#pbx_creation_copyof').val() + ' ' + my['pbx_creation_' + params.creation_id].name);
			$('input#pbx_submit_duplicate').bind('click',
				function()
				{
					// only check that creation_name is not composed of only spaces
					var creation_name = $('input#pbx_creation_name').val();
					if(creation_name.match(/^\s*$/) == null)
					{
						pbx.popup.remove(params);
						pbx.show_overlay(true);
						pbx.show_loading(true);
						pbx.babel.callBabel('Community.Creation.Fetch', params.creation_id,
							function(babel)
							{
								var creation = babel.response;
								creation.callBabel('Duplicate', null,
									function(babel2)
									{
										var new_creation = babel2.response;
										new_creation.callBabel('Set', { 'name': creation_name },
											function(babel3)
											{
												pbx.my.updateThumbnail(params.creation_id, new_creation.id);
											}
										);
									}
								);
							}
						);
					}
					else
					{
						pbx.popup.action_is_done();
					}
					return false;
				}
			);
		}
	},
	genericOK :
	{
		name : 'ok',
		width: 300,
		height: 400,
		dialog : 'ok',
		content : '',

		open : function(inTitle, inContent, callback_function)
		{
			this.content = inContent;
			this.func = callback_function;
			var params =
			{
				settings : 'pbx_popup_genericOK',
				_this : {
					title : inTitle || ''
				}
			};
			pbx.popup.open(params);
		},
		callback	:	function(params)
		{
			if(typeof pbx.popup.genericOK.func == 'function')
			{
				pbx.popup.genericOK.func(params)
			}
			$('p.pbx_generic_ok_content').html(pbx.popup.genericOK.content);
			$('#pbx_popup_content').find('input.pbx_submit_ok')[0].focus();
		}
	},
	comingsoon 			:
	{
		name   : 'coming_soon',
		height : 170,
		width  : 300,
		dialog : 'ok'
	},
	invalidBasket 			:
	{
		name   : 'invalid_basket',
		height : 170,
		width  : 300,
		dialog : 'ok'
	},
	photodeleteconfirm :
	{
		name   : 'delete_photos',
		height : 170,
		width  : 300,
		focus  : '#pbx_popup_content input.pbx_submit_ok',
		action_href :
		{
			cat			:	'album',
			action		:	'photo_delete'
		}
	},
	photodelete :
	{
		name	: 'delete_photo',
		height	: 400,
		width	: 250,
		focus	: '#pbx_photo_album_delete',
		action_href :
		{
			cat			:	'photo',
			action		:	'delete_from_album'
		}
	},
	objectdeleteconfirm	:
	{
		name		:	'delete_myphotobox_object',
		height		:	400,
		width		:	300,
		focus		:	'#pbx_popup_content input.pbx_submit_ok',
		action_href			:
		{
			cat			:	'my',
			action		:	'objectDelete'
		},
		callback	:	function(params)
		{
			$('p.pbx_objectdelete_message').addClass('pbx_hidden');
			$('p#pbx_delete_' + params.object_type).removeClass('pbx_hidden');
		}
	},
	addedtobasket		:
	{
		name				:	'added_to_basket_photos',
		height				:	170,
		width				:	300,
		callback			:	function(params)
		{
			var pbx_albums_count = $("div#pbx_account_album div.pbx_album_thumb.pbx_selected").length;
			pbx.i18nplural('albumcount', pbx_albums_count);
		}
	},
	emptyalbum		:
	{
		name				:	'empty_album',
		height				:	170,
		width				:	300,
		callback			:	function(params)
		{
			$('input#pbx_submit_uploadphoto').bind('click',	function()
				{
					window.location.href = $('a#pbx_upload_link').attr('href');
				}
			);
		}
	},
	emptytmpalbum		:
	{
		name				:	'empty_tmpalbum',
		height				:	170,
		width				:	300,
		callback			:	function(params)
		{
			$('input#pbx_submit_emptytmpalbum').bind('click',
				function()
				{
					pbx.album.empty(params.album_id,
						function()
						{
							pbx.popup.remove();
							window.location.href = $('a#pbx_myphotobox_menu').attr('href');
						}
					);
				}
			);
		}
	},
	tagphotos			:
	{
		name				:	'tag_photos',
		height				:	170,
		width				:	500,
		cacheable		:	true,
		params		:
		{
			photo_id	: "params.photo_id",
			album_id	: "params.album_id"
		},
		callback			:	function(params)
		{
			$('input#pbx_phototags_save').bind('click',
				function()
				{
					params.tags_string = $('textarea#pbx_photo_details_tags').val();
					eval(params._do + '(params)');
					pbx.popup.remove();
					return false;
				}
			);
		}
	},
	addedtotmpalbum :
	{
		name   : 'added_to_tmpalbum',
		height : 170,
		width  : 300,
		dialog : 'ok'
	},
	removedfromtmpalbum :
	{
		name   : 'removed_from_tmpalbum',
		height : 170,
		width  : 300,
		dialog : 'ok'
	},
	selectsomephotos :
	{
		name   : 'select_some_photos',
		height : 170,
		width  : 300,
		dialog : 'ok'
	},
	selectsomealbums :
	{
		name   : 'select_some_albums',
		height : 170,
		width  : 300,
		dialog : 'ok'
	},
	cropitem		:
	{
		name   : 'crop_item',
		height : 650,
		width  : 540,
		focus  : '#pbx_save_crop',
		params :
		{
			page : "params.page", // When used on a paginated /order or /my/basket/edit page
			item_id : "params.item_id",
			price_plan_id : "params.price_plan_id",
			photo_id : "params.photo_id",
			product_id : "params.product_id",
			submit_mode : "params.submit_mode", // The form's action attribute. Can be 'order', 'edit' or a url
			on_save : "params.on_save",         // Alternative Javascript function(cropdimensions, params) for saving the results.
			crop_disable_changeproduct : "params.crop_disable_changeproduct || 0", /*quick fix for save as new bottom disabled. To be improved*/
			cropw : "params.cropw",
			croph : "params.croph",
			cropx : "params.cropx",
			cropy : "params.cropy",
			fit : "params.fit",
			rotation : "params.rotation"
		},
		callback : function(params)
		{
			pbx.crop.init(params);
		},
		precall : function(params)
		{
			// Passing a function as a POST parameter is bad.
			if (typeof(params.on_save) === 'function')
			{
				pbx.crop.on_save = params.on_save;
				params.on_save = 0;
			}
			return true;
		}
	},
	previewitem		:
	{
		name   : 'preview_item',
		height : 550,
		width  : 540,
		focus  : '#pbx_preview_close',
		params :
		{
			item_id : "params.item_id"
		},
		callback : function(params)
		{
			//pbx.crop.init(params);
		}
	},
	sendToAFriend :
	{
		name   : 'send_to_friend',
		width  : 455,
		height : 455,
		focus  : '#pbx_share_send',
		params :
		{
			message_token: 'params.message_token'
		},
		precall: function(inParams)
		{
			if(inParams['message_token'])
			{
				pbx.popup.sendToAFriend['message_token'] = inParams['message_token'];
			}
			if(inParams['url'])
			{
				pbx.popup.sendToAFriend['url'] = inParams['url'];
			}
			else
			{
				var uri_str = location.href;
				pbx.popup.sendToAFriend['url'] = uri_str;
			}
		},
		callback: pbx.send_friend.init
	},

	offensivecontent :
	{
		name     : 'offensive_content',
		height   : 300,
		width    : 400,
		callback : function(params)
		{
			$('form#pbx_offensive_content').bind('submit',
				function()
				{
					$('span#pbx_offensive_content_bademail').hide();
					$('span#pbx_offensive_comment_badcomment').hide();

					var email = $('input#pbx_offensive_content_email').val();
					var message = $('textarea#pbx_offensive_content_comment').val();

					if(pbx.validate(email,'email'))
					{
						if(message.length)
						{
							pbx.album.albums[pbx.album.id].callBabel('ReportOffence',{ message : message, email : email },function(){});
							pbx.popup.remove();
							pbx.popup.open({ _this : params._this, settings : 'pbx_popup_offensivecontentthanks'});
							return false;
						}
						else
						{
							$('span#pbx_offensive_content_badcomment').show();
							pbx.popup.action_is_done();
							return false;
						}
					}
					else
					{
						$('span#pbx_offensive_content_bademail').show();
						pbx.popup.action_is_done();
						return false;
					}
				}
			);
		}
	},
	offensivecontentthanks 			:
	{
		name   : 'offensive_content_thanks',
		height : 170,
		width  : 300,
		onclose	:	function()
		{
			window.location.href = $('a#pbx_gallery_categoryurl').attr('href');
		}

	},

	offensivecomment :
	{
		name     : 'offensive_comment',
		height   : 300,
		width    : 400,
		params   : {
			comment_id : "params.comment_id"
		},
		callback : function(params)
		{
			$('form#pbx_offensive_comment').bind('submit',
				function()
				{
					$('span#pbx_offensive_comment_badcomment').hide();

					var message = $('textarea#pbx_offensive_comment_comment').val();

					if(message.length)
					{
						pbx.babel.callBabel('Community.AlbumCommentComplaint.New',
							{
								album_comment_id : params.comment_id,
								message : message
							},
							function(){}
						);
						pbx.popup.remove();
						pbx.popup.open({ _this : params._this, settings : 'pbx_popup_offensivecommentthanks'});
						return false;
					}
					else
					{
					$('span#pbx_offensive_comment_badcomment').show();
						pbx.popup.action_is_done();
						return false;
					}
				}
			);
		}
	},
	offensivecontentthanks 			:
	{
		name   : 'offensive_content_thanks',
		height : 170,
		width  : 300,
		onclose	:	function()
		{
			var url_elmt = $('a#pbx_gallery_categoryurl');
			if (url_elmt.length > 0)
			{
				window.location.href = url_elmt.attr('href');
			}
		}

	},
	privilegeerror 			:
	{
		name   : 'privilege_error',
		height : 170,
		width  : 300
	},
	image 			:
	{
		name   : 'image',
		height : 500,
		width  : 500,
		params          :
		{
			graphic_id	:	"params.graphic_id"
		}
	},
	component 		:
	{
		name   : 'cms_component',
		height : 500,
		width  : 500,
		params :
		{
			path :	"params.path"
		},
		open   : function(params, path, inTitle)
		{
			if (!params)
			{
				params = { _this : {title: inTitle}};
			}
			params.settings = 'pbx_popup_component';
			params.path = path;
			pbx.popup.open(params);
		}
	},
	/* Loads a specified flash file in a popup window*/
	flash 		:
	{
		name   : 'flash',
		height : 500,
		width  : 500,
		params :
		{
			file_url : "params.file_url",
			width    : "params.width",
			height    : "params.height"
		},
		callback : function(params)
		{
			pbx.popup.popup.addClass('pbx_flash_popup');
			if(pbx.popup.settings.width)
			{
				var width = pbx.popup.settings.width + 13;
				pbx.popup.popup.width(width);
				pbx.popup.flash.width = width;
			}
			if(pbx.popup.settings.height)
			{
				var height = pbx.popup.settings.height + 46;
				//pbx.popup.popup.height(height);
				pbx.popup.flash.height = height;
			}
			pbx.popup.position();
		},
		onclose : function ()
		{
			pbx.popup.popup.removeClass('pbx_flash_popup');
		}
	},

	/**
	 * Contact handling
	 */
	contactslookup :
				{
		name    : 'contacts_lookup',
		height  : 500,
		width   : 500,
		callback : function(params)
		{
			$('form#pbx_contacts_form').bind('submit',
				function()
				{
					$(params._this).siblings('textarea').each(pbx.clearTextArea);
					var toAdd = new Array();
					var ob = $('select#pbx_contacts_select_box')[0];
					var input = $(params._this).siblings('textarea');
					for (var i=0; i < ob.options.length; i++)
					{
						if (ob.options[i].selected == true)
						{
							toAdd.push(ob.options[i].value);
						}
					}
					var joiner = ', ';
					if (($(input).val() == '') || ($(input).val().match(/,\s*$/)))
					{
						joiner = '';
					}

					$(input).val($(input).val() + joiner + toAdd.join(', '));
					pbx.popup.remove();
				}
			);
		}
	},
	editcontact		:
	{
		name			:	'edit_contact',
		height			:	500,
		width			:	500,
		params          :
		{
			contact_id	:	"params.contact_id",
			group_id	:	"params.group_id",
			action		:	"params.action"
		},
		callback		:	function(params)
		{
			$('form#pbx_contact_details').bind('submit',
				function()
				{
					var email = $("input[name='pbx_contact_email']").val();
					if(!email && !$("input[name='pbx_contact_firstname']").val())
					{
						$('span#pbx_contact_name_error').show();
						$('span#pbx_contact_email_error').hide();
						pbx.popup.action_is_done();
						return false;
					}
					else if(email && !pbx.validate(email, 'email'))
					{
						$('span#pbx_contact_name_error').hide();
						$('span#pbx_contact_email_error').show();
						pbx.popup.action_is_done();
						return false;
					}
					$('input#pbx_contact_save').attr('disabled','disabled');
					$('span#pbx_contact_name_error').hide();
					$('span#pbx_contact_email_error').hide();
				}
			);
		}
	},
	editgroup		:
	{
		name			:	'edit_group',
		height			:	170,
		width			:	300,
		params          :
		{
			group_id	:	"params.group_id",
			action		:	"params.action"
		},
		callback		:	function(params)
		{
			$('form#pbx_contact_details').bind('submit',
				function()
				{
					if(!$("input[name='group_name']").val())
					{
						$('span#pbx_group_error').show();
						pbx.popup.action_is_done();
						return false;
					}
					$('input#pbx_contact_save').attr('disabled','disabled');
					$('span#pbx_group_error').hide();
				}
			);
		}
	},
	deletecontact		:
	{
		name			:	'delete_contact',
		height			:	170,
		width			:	300,
		params          :
		{
			contact_id	:	"params.contact_id",
			action		:	"params.action"
		},
		callback		:function(params)
		{
			$('input#pbx_contact_delete').val(params.contact_id);
			var name_field = $(params._this).parent().siblings('td.pbx_contact_name').html() || $(params._this).parent().siblings('td.pbx_contact_email').html() || '';
			$('b#pbx_contact_name_field').html(name_field);
			$('form#pbx_delete_contact_popup').bind('submit',
				function()
				{
					$('form#pbx_delete_contact_popup input[type=submit]').attr('disabled','disabled');
				}
			);
		}
	},
	deletecontactgroup		:
	{
		name			:	'delete_contact_group',
		height			:	170,
		width			:	300,
		params          :
		{
			group_id	:	"params.group_id",
			action		:	"params.action"
		},
		callback		:function(params)
		{
			$('input#pbx_group_delete').val(params.group_id);
			var group_field = $(params._this).parent().siblings('td.pbx_contact_name').children('b').html() || '';
			$('b#pbx_contact_group_field').html(group_field);
			$('form#pbx_delete_group_popup').bind('submit',
				function()
				{
					$('form#pbx_delete_group_popup input[type=submit]').attr('disabled','disabled');
				}
			);
		}
	},
	localupload:
	{
		name		:	'local_upload',
		height		:	345,
		width		:	420,
		params		:
		{
			mode		: "params.mode",
			album_id	: "params.album_id",
			album_name	: "params.album_name"
		},
		callback_params	:	null,
		show_panel	:	function(panel_name)
		{
			//shows the given panel and hides the others

			// hide all panels
			$('div[class^="pbx_local_upload_"]').addClass('pbx_invisible');
			$('form[class^="pbx_local_upload_"]').addClass('pbx_invisible');
			//show the right one
			$('.pbx_local_upload_' + panel_name).removeClass('pbx_invisible');
		},
		validate	:	function()
		{
			$('b[id^="pbx_local_upload_error_"]').addClass('pbx_hidden');
			switch (pbx.upload.validatePhoto($('input#pbx_local_upload_photo').val()))
			{
				case pbx.upload.validatePhoto_error_empty:
					$('#pbx_local_upload_error_empty').removeClass('pbx_hidden');
					return false;
				case pbx.upload.validatePhoto_error_notjpg:
					$('#pbx_local_upload_error_notjpg').removeClass('pbx_hidden');
					return false;
			}
			pbx.popup.localupload.show_panel('progress');
			return true;
		},
		progress	:	function(response)
		{
			// xml contains the serial=...&ulhost=...
			// display progress panel
			//pbx.popup.localupload.show_panel('progress');
			//init upload progress
			//   arguments are callback for success and error
			pbx.upload.local_init_progress(response.replace(/&amp;/g, '&'), pbx.popup.localupload.success, pbx.popup.localupload.error, pbx.popup.localupload.generic_error);
			// poll the backend till it finishes processing the photo
			pbx.upload.load_photos_local_progress(0);
		},
		success		:	function(photo_list)
		{
			// display success panel
			pbx.popup.localupload.show_panel('success');
			// refresh list of albums, tree in the menu,
			$.ajax
			(
				{
					type		: 	"POST",
					url		: 	"/includes/ajax/album_selector",
					data		:	"include_clipboard=1&tmp_album=" + pbx.popup.localupload.params.album_id + "&album_id=" + pbx.popup.localupload.callback_params.album_id,
					success		: 	function(result)
								{
									$('span#pbx_album_selector_wrapper select').html($(result).html());
									$('span#pbx_album_selector_wrapper select').trigger("change");
									if (photo_list && photo_list.length > 0)
									{
										pbx.albumnavbar.localupload_photo_id = "" + photo_list[0];
									}
									pbx.menu_album_tree_refresh();
									pbx.popup.remove(pbx.popup.localupload.callback_params);
								}
				}
			);
		},
		error		:	function(error_list)
		{
			var list_str = '';

			for (var i=0; i < error_list.length; i++)
			{
				list_str += error_list[i].filename.toString() + ' - ' + error_list[i].error.toString() + '<br/>';
			}
			$('#pbx_upload_error_details').html(list_str);

			// display error panel
			pbx.popup.localupload.show_panel('error');
		},
		generic_error		:	function(obj)
		{
			// display stalled panel
			pbx.popup.localupload.show_panel('genericerror');
		},
		callback	:	function(params)
		{
			$('input#pbx_local_upload_photo').val(''); // on FF when reloading the page the input.file keeps the last value
			$('#pbx_album_name').html(decodeURI(params.album_name));
			$('input#pbx_hidden_album_id').val(params.album_id);
			// prevent manual modification on input.file
			pbx.upload.initializeInputFileNotManual('form.pbx_local_upload_choose');
			$('div#pbx_popup_window a.pbx_submit_cancel').unbind('click').bind('click',
				function()
				{
					pbx.popup.remove(params);
					return false;
				}
			);
			$('.pbx_local_upload_retry_button').unbind('click').bind('click',
				function()
				{
					pbx.popup.localupload.show_panel('choose');
					return false;
				}
			);

			// prepare form
			var options =
			{
				beforeSubmit: pbx.popup.localupload.validate,
				// hacked by ben2 to add support for running alternative success function (not just studio)
				success : eval(params.success) || pbx.popup.localupload.progress
				//target: '#response'
				//url: '/xmlrpcproxy'
			};
			$('form.pbx_local_upload_choose').ajaxForm(options);

			pbx.popup.localupload.callback_params = params;
			pbx.popup.localupload.show_panel('choose');
		},
		onclose	:	function()
		{
			// hide errors and reset form
			$('b[id^="pbx_local_upload_error_"]').addClass('pbx_hidden');
			$('form.pbx_local_upload_choose').resetForm();
		}
	},
	changesharingpassword:
	{
		name			:	'change_sharing_password',
		height			:	500,
		width			:	350,
		params          :
		{
			mode		:	"params.mode",
			password	:	"params.password",
			old_status	:	"params.old_status",
			tab			:	"params.tab",
			action		:	"params.action",
			form_action	:	"params.form_action",
			album_id	:	"params.album_id"
		},
		focus  : '#pbx_change_sharing_password_password',
		callback		:	function(params)
		{
			var oldpassword = $('#' + params.password).html();
			if (oldpassword)
			{
				$('input#pbx_change_sharing_password_password').val(oldpassword);
				$('#pbx_change_sharing_password_oldpassword').html(oldpassword);
				$('#pbx_change_sharing_password_header_new').hide();
				$('#pbx_change_sharing_password_label_new').hide();
				$('#pbx_change_sharing_password_header_change').show();
				$('#pbx_change_sharing_password_label_change').show();
			}
			else
			{
				$('#pbx_change_sharing_password_header_new').show();
				$('#pbx_change_sharing_password_label_new').show();
				$('#pbx_change_sharing_password_header_change').hide();
				$('#pbx_change_sharing_password_label_change').hide();
			}
			// hide errors
			$('p[id^="pbx_change_sharing_password_error_"]').hide();
			//set "clear" callback
			$('a.pbx_change_sharing_password_clear').unbind('click').bind('click',
				function()
				{
					$('input#pbx_change_sharing_password_password').val('');
					$('#pbx_change_sharing_password_oldpassword').val('');
					return false;
				}
			);
			// form submission
			$('form#pbx_change_sharing_password_form').attr('action', unescape(params.form_action)).unbind('submit').bind('submit',
				function()
				{
					$(this).validate
					(
						{
							error: function(form, field_name, error_code)
							{
								form.validate.defaults.error(form, field_name, error_code);
								pbx.popup.action_is_done();
								return false;
							},
							success: function(form)
							{
								form.unbind('submit').submit();
							}
						}
					);
				}
			);
		},
		onclose	:	function()
		{
			$('p[id^="pbx_change_sharing_password_error_"]').hide();
			$('input#pbx_change_sharing_password_password').val('');
			$('#pbx_change_sharing_password_oldpassword').val('');
		}
	},
	removesharingpassword:
	{
		name			:	'remove_sharing_password',
		height			:	400,
		width			:	350,
		params          :
		{
			mode		:	"params.mode",
			action		:	"params.action",
			form_action	:	"params.form_action",
			album_id	:	"params.album_id"
		},
		callback		:	function(params)
		{
			// set the action
			$('form#pbx_remove_sharing_password_form').attr('action', unescape(params.form_action)).unbind('submit').bind('submit',
				function()
				{
					$(this).unbind('submit').submit();
					//pbx.popup.remove(params);
					//pbx.show_overlay(true);
					//pbx.show_loading(true);
				}
			);
		}
	},
	changesharingstatus:
	{
		name			:	'change_sharing_status',
		height			:	400,
		width			:	350,
		cacheable		:	true,
		params          :
		{
			mode				:	"params.mode",
			old_status			:	"params.old_status",
			new_status			:	"params.new_status" || "private",
			category_input		:	"params.category_input",
			operation			:	"params.operation",
			remove_invitations	:	"params.remove_invitations",
			action				:	"params.action",
			form_action			:	"params.form_action",
			on_submit			:	"params.on_submit"
		},
		callback		:	function(params)
		{
			// display the right content depending on the operation required
			$('#pbx_change_sharing_status_header div[id^=pbx_change_sharing_status_header_][id!=pbx_change_sharing_status_header_' + params.operation + ']').addClass('pbx_hidden');
			$('#pbx_change_sharing_status_header div[id=pbx_change_sharing_status_header_' + params.operation + ']').removeClass('pbx_hidden');
			// set the hidden fields depending on the params
			$('form#pbx_change_sharing_status_form input[name=share_remove]').val(params.remove_invitations ? 1 : 0);
			$('form#pbx_change_sharing_status_form input[name=set_share_status]').val(params.new_status);
			if (typeof(params.category_input) !== 'undefined' && $('#' + params.category_input).length)
			{
				$('form#pbx_change_sharing_status_form input[name=category_id]').val($('#' + params.category_input).val());
			}
			// set the action
			$('form#pbx_change_sharing_status_form').attr('action', unescape(params.form_action)).unbind('submit').bind('submit',
				function()
				{
					if (typeof(params.on_submit) !== 'undefined')
					{
						eval(params.on_submit + '()');
						return false;
					}
					$(this).unbind('submit').submit();
					//pbx.popup.remove(params);
					//pbx.show_overlay(true);
					//pbx.show_loading(true);
				}
			);
		}
	},
	checkoutpaymenttransfer 			:
	{
		name   : 'checkout_payment_transfer',
		height : 170,
		width  : 300,
		params          :
		{
			previous	:	"params.previous"
		},
		callback		:function(params)
		{
			$('form#pbx_checkout_payment_transfer_popup').bind('submit',
				function()
				{
					params.toSet.is_open = true;
					$(params._this).attr('checked','checked');
					$('#pbx_payment_options_transfer').removeClass('pbx_hidden');
					pbx.checkout.payment.pay_methods.creditcard.close();
					pbx.checkout.payment.pay_methods.ELV.close();
					pbx.checkout.payment.pay_methods.paypal.close();
					pbx.checkout.paymentSelected = $(params._this);
					pbx.popup.action_is_done();
					pbx.popup.remove(params);
					return false;
				}
			);
		}
	},
	unsharesingle :
	{
		name	: 'unshare_single',
		height	: 170,
		width	: 300,
		params	:
		{
			unshareobj : "params.unshareobj"
		},
		callback: function(params)
		{
			$('.pbx_submit_ok').bind('click', function(){
				pbx.share.unshare(params.unshareobj);
				pbx.popup.remove(params);
				return false;
			});
			$('.pbx_submit_cancel').bind('click', function(){
				pbx.popup.remove(params);
			});
		}
	},
	unshareall :
	{
		name	: 'unshare_all',
		height	: 170,
		width	: 300,
		callback: function()
		{
			$('.pbx_submit_ok').bind('click', function(){
				pbx.share.unshareAll();
				pbx.popup.remove();
				return false;
			});
			$('.pbx_submit_cancel').bind('click', function(){
				pbx.popup.remove(params);
			});
		}
	},
	/* Presents the user with a list of albums to choose from. */
	genericalbumselector :
	{
		name : 'album_selector',
		height : 170,
		width : 300,
		params          :
		{
			okfunc	   : "params.okfunc",
			cancelfunc : "params.cancelfunc"
		},
		callback : function(params)
		{
			$('.pbx_submit_ok').bind('click', eval(params.okfunc)).bind('submit', eval(params.okfunc));
			$('.pbx_submit_cancel').bind('click', eval(params.cancelfunc));
		}

	},
	addToPublicGallery :
	{
		name : "add_to_public_gallery",
		height : 200,
		width  : 400,
		params :
		{
			category_id : "params.category_id",
			album_id    : "params.album_id"
		},
		callback : function(params)
		{
			$('input[id=pbx_submit_ok]').bind('click',
			function()
			{
				pbx.popup.addToPublicGallery.saveGallery(params);
				return false;
			});
			$('input[id=pbx_submit_cancel]').bind('click', function(){
				pbx.popup.remove(params)
			});
		},
		saveGallery : function(params)
		{
			var album_id =  document.getElementById('pbx_popup_gallery_album_selector').value;
			var topic_id =  document.getElementById('pbx_gallery_topic_selector').value;
			var popup_title = params._this.title;
			var ajax_response = $.ajax( {
				type    : "POST",
				url     : "/includes/ajax/my/album/share_public",
				data    :
				{
					performAction			: 'album',
					album_id				: album_id,
					set_share_status		: 'public',
					set_share_password		: '',
					category_id				: topic_id,
					layout					: 'ajax'
				},
				success : function()
				{
					var ok_content = $('#pbx_gallery_saved_content').html();
					pbx.popup.genericOK.open(popup_title, ok_content, function()
						{
							$('#pbx_popup_content').find('input.pbx_submit_ok').bind('click', function()
								{
									pbx.show_overlay(true);
									pbx.show_loading(true);
									setTimeout(window.location.reload, 300);
								}
							);
						}
					);
				}
			});
		}
	},
	albumEditSave:
	{
		name		:	'album_edit_save',
		height		:	245,
		width		:	250,
		focus		:	'#pbx_popup_albumedit_save',
		callback	:	function(params)
		{
			$('input#pbx_popup_albumedit_save').bind('click',
				function()
				{
					pbx.popup.remove(params);
					document.pbx_albumedit_form.submit();
					return false;
				}
			);
		}
	},
	albumEditPrompt:
	{
		name		:	'album_edit_prompt',
		height		:	245,
		width		:	250,
		focus		:	'#pbx_popup_albumedit_save',
		callback	:	function(params)
		{
			$('input#pbx_popup_albumedit_save2').bind('click',
				function()
				{
					// if the tickbox is unchecked, then do not open album after saving
					if(!$('input#pbx_popup_albumedit_albumopen:checked').length)
					{
						$("input:hidden[name='open']").val('edit');
					}
					pbx.popup.remove(params);
					document.pbx_albumedit_form.submit();
					return false;
				}
			);
		}
	},
	enableCookies :
	{
		name : "enable_cookies",
		width : 400,
		height : 200,
		callback : function()
		{
			$('#pbx_popup_title').html($('#pbx_enable_cookies_popup_title').html());
		},
		open : function()
		{
			var params =
			{
				settings : 'pbx_popup_enableCookies',
				_this : {
					title : '&nbsp;'
				}
			};
			pbx.popup.open(params);
		}
	},
	creationStatus		:
	{
		name			:	'creation_status',
		height			:	170,
		width			:	300,
		params          :
		{
			prototype_creation_id	:	"params.prototype_creation_id"
		},
		callback		:function(params)
		{
			return;
		}
	},
	deletePrototypeCreation		:
	{
		name			:	'delete_prototype_creation',
		height			:	170,
		width			:	300,
		params          :
		{
			prototype_creation_id   :	"params.prototype_creation_id",
			album_id                :	"params.album_id",
			extra_args:
			{
				collection_id   : "params.collection_id",
				vendor_id       : "params.vendor_id"
			}
		},
		callback		:function(params)
		{
			return;
		}
	},
	orderPhoto		:
	{
		name			:	'order_photo',
		height			:	170,
		width			:	400,
		params			:
		{
			photo_id	:	"params.photo_id"
		},
		callback		:function(params)
		{
			// Bind the order button to submit the form via ajax
			$('input.pbx_order_ajax').bind('click',
				function()
				{
					// Change form values temporarely
					$("input[name='performAction']").attr('value', 'basket');
					// Sumbit the form
					$('div#pbx_popup_window').find('form').ajaxSubmit(
					{
						url				: '/?layout=ajax',
						beforeSubmit	: function()
						{
							var added_lines = 1;
							var qty = $('div#pbx_popup_window').find('input.pbx_order_form_quantity').val();
							pbx.popup.remove(params);
							scrollTo(0,0);
							$('span#bubblebasket').each(
							function()
							{
								pbx.i18nplural('bubblebasket',added_lines * qty);
							}	);
							pbx.ordering = 1; // because bubble uses mouseover event, we need this to stop the rollover cart popup being fired
							pbx.bubble_show('a#pbx_basket_link', '200px');
							pbx.ordering = 0;
							$('div#pbx_popup_cart').removeClass('pbx_disabled');
						},
						success			: function()
						{
							$('span.pbx_bubble_async_status').html(100)
							pbx.babel.basketcount_update();
							setTimeout("pbx.bubble_hide('a#pbx_basket_link', true)", 3000);
						}
					}	);
					// restore the old values
					$("input[name='performAction']").attr('value', 'temp')
					return false;
				}
			);
			$('div#pbx_popup_window').find('select.pbx_order_select_product').updateProduct();
		}
	},
	orderAlbum		:
	{
		name			:	'order_album',
		height			:	170,
		width			:	400,
		params			:
		{
			album_id	:	"params.album_id",
			photos		:	"params.photos"
		},
		callback		:	function(params)
		{
			/* Bind the radio buttons to submit the correct value */
			$("#pbx_order_prints_popup input[name='order_choice']").bind("click",
				function()
				{
					toggleAlbumSelected();
				}
			);

			/* Bind the order button to submit the form via ajax */
			$("#pbx_order_prints_popup input.pbx_order_ajax").bind("click",
				function()
				{
					// Change form values temporarely
					$("#pbx_order_prints_popup input[name='performAction']").attr('value', 'basket');

					// Remove unwanted fields
					removeUnwantedFields();

					// Submit the form
					$("#pbx_order_prints_popup").ajaxSubmit(
					{
						url				: '/?layout=ajax',
						beforeSubmit	: function()
						{
							var added_lines = getAddedLines() || 1;
							var qty = $("#pbx_order_prints_popup input.pbx_order_form_quantity").val();

							pbx.popup.remove(params);

							scrollTo(0,0);
							$('span#bubblebasket').each(
								function()
								{
									pbx.i18nplural('bubblebasket',added_lines * qty);
								}
							);
							pbx.ordering = 1; // because bubble uses mouseover event, we need this to stop the rollover cart popup being fired
							pbx.bubble_show('a#pbx_basket_link', '200px');
							pbx.ordering = 0;
							$('div#pbx_popup_cart').removeClass('pbx_disabled');

						},
						success			: function()
						{
							$('span.pbx_bubble_async_status').html(100)
							pbx.babel.basketcount_update();
							setTimeout("pbx.bubble_hide('a#pbx_basket_link', true)", 3000);

							// slideshow specific call
							if (typeof(pbx.babel.slideshow) !== 'undefined')
							{
  								var eventInfo = new pbx.babel.slideshow.event.eventInfo( "itemsUpdated", "successful" );
    							pbx.babel.slideshow.event.sendToActionScript( eventInfo );
							}
						}
					});
					// restore the old values
					$("#pbx_order_prints_popup input[name='performAction']").attr('value', 'temp')
					return false; //avoid webkit browsers to redirect
				}
			);

			$('#pbx_order_prints_popup select.pbx_order_select_product').updateProduct();

			//preselect the hidden fileds when the popup loads
			toggleAlbumSelected();

			/* get the added line value */
			function getAddedLines()
			{
				if ($("#pbx_order_prints_popup input[name='item_count'][type='radio']").length > 0)
				{
					return $("#pbx_order_prints_popup input[name='item_count']:checked").val();
				}
				else
				{
					return $("#pbx_order_prints_popup input[name='item_count']").val();
				}
			}

			/* toggle all the radio buttons according to the selected main radio buttons */
			function toggleAlbumSelected()
			{
				if ($("#pbx_order_prints_popup input[name='order_choice']:checked").val() == "selected")
				{
					$("#pbx_order_prints_popup .pbx_order_choice_album").removeAttr("checked");
					$("#pbx_order_prints_popup .pbx_order_choice_selected").attr("checked", "checked");
					$("#pbx_order_prints_popup input[name='album_id']").attr('disabled', 'disabled');
					$("#pbx_order_prints_popup input[name='photo_id']").removeAttr('disabled');
				}
				else
				{
					$("#pbx_order_prints_popup .pbx_order_choice_album").attr("checked", "checked");
					$("#pbx_order_prints_popup .pbx_order_choice_selected").removeAttr("checked");
					$("#pbx_order_prints_popup input[name='photo_id']").attr('disabled', 'disabled');
					$("#pbx_order_prints_popup input[name='album_id']").removeAttr('disabled');
				}
			}

			/* remove the input we are not going to submit to perform action according to
			 * the main selected radio buttons
			 */
			function removeUnwantedFields()
			{
				if ($("#pbx_order_prints_popup input[name='order_choice']").length > 0)
				{
					switch ($("#pbx_order_prints_popup input[name='order_choice']:checked").val())
					{
						case "album":
							$("#pbx_order_prints_popup input[name='photo_id']").remove();
							break;

						case "selected":
							$("#pbx_order_prints_popup input[name='album_id']").remove();
							break;
					}
				}
			}


		}
	},
	editItem		:
	{
		name			:	'edit_item',
		height			:	170,
		width			:	400,
		params			:
		{
			item_id		:	"params.item_id",
			submit_mode	:	"params.submit_mode"
		},
		callback		:function(params)
		{
			$('div#pbx_popup_window').find('select.pbx_order_select_product').updateProduct();
		}
	},
	deletevendor		:
	{
		name			:	'delete_vendor',
		height			:	170,
		width			:	400,
		params			:
		{
			vendor_id		: "params.vendor_id"
		}
	},
	newpriceplan		:
	{
		name			:	'new_priceplan',
		height			:	170,
		width			:	335,
		params			:
		{
			vendor_id		:	"params.vendor_id"
		}
	},
	deletepriceplan		:
	{
		name			:	'delete_priceplan',
		height			:	170,
		width			:	335,
		params			:
		{
			price_plan_id   : "params.price_plan_id",
			vendor_id       : "params.vendor_id"
		}
	},
	selectpriceplan		:
	{
		name			:	'priceplan_selector',
		height			:	170,
		width			:	335,
		params			:
		{
			collection_id   : "params.collection_id",
			vendor_id       : "params.vendor_id"
		}
	},
	watermarkcollection	:
	{
		name			:	'watermark_collection',
		height			:	170,
		width			:	335,
		params			:
		{
			collection_id   : "params.collection_id",
			vendor_id       : "params.vendor_id"
		},
		callback		:function(params)
		{
			// Options
			var options =
			{
				url				: '/gallery/collections?layout=ajax',
				beforeSubmit	: function()
				{
					$.ajax(
						{
							type		: "POST",
							url			: "/includes/popup/watermark_collection_progress",
							data		:
							{
								caption : $(params._this).html()
							},
							success	: 	function(result)
							{
								$('div#pbx_popup_window').html(result);
								$('div#pbx_popup_window').find('a#pbx_popup_close').bind('click',
									function()
									{
										pbx.popup.on_close();
										return false;
									}
								);
								$('div#pbx_popup_content').find('a.pbx_popup_close').bind('click',
									function()
									{
										pbx.popup.on_close();
										return false;
									}
								);
							}
						}
					);
				}
			};
			// bind the form submit to use ajax instead
			$('div#pbx_popup_content').find('form').ajaxForm(options);
		}
	},

	/* ########### DO NOT CHANGE ANYTHING AFTER THAT ############## */

	onclose_callback : null,
	timer            : null,
	save             : null,
	on_close         : null,		// Close function referenced here so that it can be changed e.g. crop preview popup.


	// new //
	popup				:	null,
	settings			:	null,
	drag_config			:
	{
		zIndex			: 	1000,
		opacity			: 	0.9,
		snapDistance	:	10,
		handle			:	'div#pbx_popup_header',
		scrollOffset	:	true,
		onStop			:	function()
		{
			pbx.popup.popup.css('position','fixed');
		}
	},
	dialog_bind			:	function(type, params)
	{
		if(pbx.popup.settings.dialog[type])
		{
			$('div#pbx_popup_content input.pbx_submit_' + type).bind('click', pbx.popup.settings.dialog[type]);
		}
		else
		{
			$('div#pbx_popup_content input.pbx_submit_' + type).bind('click',
				function()
				{
					pbx.popup.remove(params);
					return false;
				}
			);
		}
	},

	open : function(params)
	{
		try
		{
			// if the popup hasn't been loaded before
			if(!pbx.popup.popup)
			{
				pbx.popup.popup = $("div#pbx_popup_window");			// cache the jQuery result
			}
			(typeof(pbx.popup.on_close) == 'function') ? pbx.popup.on_close() : pbx.popup.remove(); // remove any remaining popup
			pbx.show_overlay(true, function(){pbx.popup.on_close();});					// display the overlay

			if(!params._this)
			{
				params._this = {title : null, name : null};
			}

			// TODO: optimise!!
			pbx.popup.settings = null;
			var settings = params.settings.replace(/_/g, '.');
			pbx.popup.settings = eval(settings);

			var scripts_params	= pbx.popup.settings.params;
			var name 			= pbx.popup.settings.name;
			var caption 		= pbx.popup.find_title(params, pbx.popup.settings);
			var cat 			= pbx.popup.settings.cat;
			var type 			= pbx.popup.settings.type;
			var precall 		= pbx.popup.settings.precall;
			var callback 		= pbx.popup.settings.callback;
			var theFocus 		= pbx.popup.settings.focus;
			pbx.popup.settings.height = parseInt(params.height) || pbx.popup.settings.height;
			pbx.popup.settings.width = parseInt(params.width) || pbx.popup.settings.width;

			// Analytics call for all popups/
			s.pageName = "popup::" + name;
			s.channel = "Popup Dialogues";
			s.server = window.location.hostname;
			try
			{
				void(s.t()); // The void clears all previous parameters of s.
			}
			catch(e)
			{
				// do nothing, its only analytics
			}

			if (precall)
			{
				/* If precall returns false then stop loading the popup.
				 * It is up to the precall function to tidy up in this case. */
				if (!precall(params))
				{
					return false;
				}
			}

			var action_href = '?';
			if(pbx.popup.settings.action_href)
			{
				$.each(pbx.popup.settings.action_href,
					function(i, n)
					{
						action_href += i + "=" + n + "&";
					}
				);
			}
			pbx.popup.action_href = action_href.substring(0, action_href.length - 1);	// remove the extra "&"
			if(params.photo_id)
			{
				pbx.popup.action_href += "&photo_id=" + params.photo_id;
			}
			if(params.album_id)
			{
				pbx.popup.action_href += "&album_id=" + params.album_id;
			}
			if(params.creation_id)
			{
				pbx.popup.action_href += "&creation_id=" + params.creation_id;
			}
			if(params.object_type)
			{
				pbx.popup.action_href += "&object_type=" + params.object_type;
			}
			if(params.object_id)
			{
				pbx.popup.action_href += "&object_id=" + params.object_id;
			}
			if(params.perform_after)
			{
				pbx.popup.action_href += "&perform=" + params.perform_after;
			}
			pbx.popup.onclose_callback = pbx.popup.settings.onclose ? pbx.popup.settings.onclose : null;

			var content = $('div#pbx_popups div#pbx_popup_' + name);
			if (content.length > 0)
			{
				pbx.popup.save = content;
				content.remove();
				$('#pbx_popup_content').append(content);
				$('#pbx_popup_title').html(caption);
				pbx.popup.show(params);
				$('*.pbx_action').bind('click', pbx.popup.action_is_running);
				if (callback)
				{
					callback(params);
				}
				if(pbx.popup.settings.dialog)
				{
					pbx.popup.dialog_bind('ok', params);
					pbx.popup.dialog_bind('cancel', params);
				}
				pbx.popup.set_focus(theFocus);
			}
			else
			{
				// If the content div does not exist send ajax request
				//pbx.show_loading(true);
				var url = '';
				if(cat)
				{
					url = cat + "/";
				}
				if(type)
				{
					url += type + "/";
				}
				url += name;

				if(url.indexOf("?")!==-1)
				{ //If there is a query string involved
					var baseURL = url.substr(0, url.indexOf("?"));
				}
				else
				{
					var baseURL = url;
				}

				var urlString = /\.jpg|\.jpeg|\.png|\.gif|\.bmp/g;
				var urlType = baseURL.toLowerCase().match(urlString);

				var queryString = url.replace(/^[^\?]+\??/,'');

				var extra_params = {'caption' : caption};
				if(pbx.popup.settings.params)
				{
					for (var i in pbx.popup.settings.params)
					{
						if(typeof(pbx.popup.settings.params[i]) == 'string')
						{
							extra_params[i] = eval(pbx.popup.settings.params[i]) || 0;
						}
						else if (typeof(pbx.popup.settings.params[i]) == 'object')
						{
							for (var b in pbx.popup.settings.params[i])
							{
								extra_params[i+'['+b+']'] = eval(pbx.popup.settings.params[i][b]) || 0;
							}
						}
					}
				}
				urlNoQuery = url.split('TB_');
				$.ajax(	{ 	type		: 	"POST",
							url			: 	"/includes/popup/" + url,
							data		: 	extra_params,
							success		: 	function(msg)
											{
												pbx.popup.show_from_ajax(msg);
												$('*.pbx_action').bind('click', pbx.popup.action_is_running);
												pbx.popup.set_focus(theFocus);
												if(callback)
												{
													callback(params);
												}
												if(pbx.popup.settings.dialog)
												{
													pbx.popup.dialog_bind('ok', params);
													pbx.popup.dialog_bind('cancel', params);
												}
											}
					});
			}
		}
		catch(e)
		{
			alert( e );
			pbx.show_overlay(false);
		}
	},

	find_title : function(params, settings)
	{
		if (params.title)
			title = params.title;
		else if (params._this.title)
			title = params._this.title;
		else if (params._this.name)
		{
			if (params._this.name && $(params._this.name).text())
				title = $(params._this.name).text();
			else if (params._this.name && $('div#pbx_popups div#pbx_popup_' + settings.name + ' div.pbx_popup_title'))
				title = $('div#pbx_popups div#pbx_popup_' + settings.name + ' div.pbx_popup_title').html();
			else
				title = params._this.name;
		}
		else if ($(params._this).is('.pbx_button_action'))
			title = $(params._this).children('span').html();
		else if (params._this.href)
			title = $(params._this).html();
		else
			title = '&nbsp;';

		return title;
	},

	set_focus : function(theFocus)
	{
		if (theFocus && $(theFocus).not(':hidden').not(':disabled')[0])
		{
			$(theFocus).not(':hidden').not(':disabled').focus();
		}
		else
		{
			var defult_action = $('div#pbx_popup_window input[type=submit]').not(':hidden').not(':disabled')[0] || $('div#pbx_popup_window input').not(':hidden').not(':disabled')[0] || $('div#pbx_popup_window a.pbx_button_action').not(':hidden').not(':disabled')[0];
			if (defult_action) defult_action.focus();
		}
	},

	show : function(params)
	{
		try
		{
			if(!pbx.is_ie6)
			{
				pbx.popup.popup.Draggable(pbx.popup.drag_config);	// make it draggable if not IE6
			}

			// and bind the close button to remove()
			$("a#pbx_popup_close").bind('click',
				function()
				{
					pbx.popup.on_close();
					return false;
				}
			);

			pbx.popup.bind_ajax_events(params);

			// hide the loading animation
			pbx.show_loading(false);

			// Display and position the popup
			pbx.popup.popup.css('display','block');
			pbx.popup.position();
			$(window).resize(pbx.popup.position);
		}
		catch(e)
		{
			alert( e );
		}
	},

	bind_ajax_events: function(params)
	{
		pbx.popup.on_close = function(){ pbx.popup.remove(params); }
			$('div#pbx_popup_window .pbx_tooltip').tooltip();
			$('div#pbx_popup_window *.pbx_dropdown').tooltip(pbx.dropdown);

			$('div#pbx_popup_window input.pbx_submit_cancel').bind('click',
				function()
				{
					pbx.popup.on_close();
					return false;
				}
			);
			$('div#pbx_popup_window input#pbx_submit_quickcheckout').bind('click',
					function()
				{
					pbx.popup.on_close();
					window.location.href = '/my/basket';
					return false;
				}
			);
			if(pbx.popup.action_href)
			{
				$('div#pbx_popup_window input.pbx_submit_ok').bind('click',
					function()
					{
						pbx.action(null,{href:pbx.popup.action_href});
						pbx.popup.on_close();
						return false;
					}
				);
			}
	},

	show_from_ajax : function (result)
	{
		pbx.popup.popup.empty();
		pbx.popup.popup.html(result);
		/*Check if the popup can be cached in order to avoid a further ajax request if the popup is launched again*/
		if (pbx.popup.settings.cacheable)
		{
			/*Most file-based popups contain all the popup code and not just its contents. If the current popup contains this extra stuff then we need to get rid of it before caching*/
			var content;
			if (pbx.popup.popup.children(':first').children('#pbx_popup_content').length)
			{
				content = pbx.popup.popup.children(':first').children('#pbx_popup_content').children();

			}
			else
			{
				content = pbx.popup.popup.children();
			}
			/*It is assumed (in pbx.popup.open()) that all cached popups are enclosed in a div, so we need to wrap the content in a div*/
			var clone = content.clone();
			var new_content = $('<div/>');
			new_content.append(clone);
			new_content.attr('id', 'pbx_popup_' + pbx.popup.settings.name);

			$('div#pbx_popups').append(new_content);
		}
		pbx.popup.show();

	},

	/*
	 * remove the popup from the screen
	 */
	remove				:	function(params)
	{
		pbx.show_overlay(false);
		pbx.popup.action_is_done();		// remove the hourglass cursor
		pbx.popup.popup.css('display','none');
		pbx.popup.popup.DraggableDestroy();
		$('div#pbx_popup_content input').unbind('click');
		$('div#pbx_popup_content a.pbx_button_action').unbind('click');
		//$('div#pbx_popup_content').empty();

		if(params && params.settings)
		{
			$('div#pbx_popups').append(pbx.popup.save);
		}
		if(pbx.popup.onclose_callback)
		{
			pbx.popup.onclose_callback();
		}

		$('div#pbx_popup_content').empty();

		return false;
	},

	/*
	 * reposition the popup
	 */
	position			:	function()
	{
		var width = pbx.popup.settings.width < 335 ? 335 : pbx.popup.settings.width;
		var height = parseFloat(pbx.popup.popup.height()) || pbx.popup.popup[0].offsetHeight;
		var top = (pbx.is_ie6?$(window).scrollTop():0) + ($(window).height() - height) / 4;
		top = top<0 ? 0 : top;
		var left = (pbx.is_ie6?$(window).scrollLeft():0) + ($(window).width() - width) / 2;
		left = left<0 ? 0 : left;
		pbx.popup.popup.css({top:top+'px', left:left+'px', width:width+'px'});
		pbx.overlay_size();
	},

	/*
	 * change the cursor to a hourglass
	 */
	action_is_running	:	function()
	{
		$("#pbx_popup_window").addClass('pbx_busy');
	},

	/*
	 * change the cursor to normal
	 */
	action_is_done		:	function()
	{
		$("#pbx_popup_window").removeClass('pbx_busy');
	}
};
/*
* TODO: check slider and remove if obsolete
*/
pbx.albumnavbar	=
{
	ratio 					: 176 / 500,
	studio_photo_id 		: null,
	photos 					: new Array(),
	localupload_photo_id	: null,
	min_res					: 1,
	max_photo_dimension		: 1,
	product 				: null,
	elements 				: null,
	simpler					: true, // simple studio for vendor products

	init : function()
	{
		// add new object variables
		$.extend( 
			pbx.albumnavbar, 
			{
				slider				: $('div#pbx_album_navbar_slider'),
				photolist			: $('div#pbx_photolist'),
				image_area			: $('div#pbx_image_area'),
				photo_actions		: $('div#pbx_studio_actions div span'),
				drop_box			: $('div#pbx_drop_box'),
				studio_photo_id		: $('div#pbx_drop_box span').children('img').attr('id'),
				product_id			: $('input#pbx_product_id').attr('value'),
				product_title		: $('#pbx_product_name'),
				product_price		: $('#pbx_product_price'),
				product_desc		: $('#pbx_product_desc'),
				product_extprice 	: $('#pbx_product_extprice'),
				product_img			: $('#pbx_right_images img'),
				product_list		: $('select#pbx_product_list'),
				min_res				: $('input#pbx_product_min_res').attr('value'),
				product_width		: $('input#pbx_product_width').attr('value'),
				product_height		: $('input#pbx_product_height').attr('value'),
				qty					: $('input#pbx_order_qty'),
				add_to_basket_button: $('a#pbx_studio_add_basket'),
				album_selector		: $('span#pbx_album_selector_wrapper select'),
				loader				: $('div#pbx_photosareloading'),
				styles_dropdown		: $("select#pbx_product_list_styles")
				
			}
		);
		
		/*
		* check if is a simpler simple studio (vendor product basically)
		* and set the flag	
		*/
		if(pbx.albumnavbar.product_list.length>0 && pbx.albumnavbar.album_selector.length>0 )
		{ 
			pbx.albumnavbar.simpler = false;
		}

		// specific binding
		if(!pbx.albumnavbar.simpler)
		{		
			pbx.albumnavbar.album_selector
				.bind('change',pbx.albumnavbar.get_photos);		
			pbx.albumnavbar.slider.children('img')
				.bind('click', pbx.albumnavbar.load_image);
			pbx.albumnavbar.slider.children('li a')
				.bind('click',pbx.albumnavbar.action_is_running);	
			pbx.albumnavbar.product_list
				.bind('change', pbx.albumnavbar.get_product_list)
				.bind('keypress', pbx.albumnavbar.get_product_list);
			
			pbx.albumnavbar.slider.tooltip(pbx.image_zoom);

			// clear photo cache after 10 min
			setInterval('pbx.albumnavbar.clear_cache()',600000);

			// load the selected album
			pbx.albumnavbar.get_photos(null,pbx.albumnavbar.album_selector[0].options[pbx.albumnavbar.album_selector[0].selectedIndex].value);			
		}
		// common binding
		pbx.albumnavbar.qty
			.bind('blur', pbx.albumnavbar.checknumber);		
		
		if(pbx.albumnavbar.studio_photo_id)
		{
			pbx.albumnavbar.get_photo(this.studio_photo_id);
			this.recalcQuality();
		}
		
		pbx.albumnavbar.initStudioUi();
	},

	/* called on page load and after fetching new product information  */
	initStudioUi : function()
	{
		jQuery.fn.extend(
			{
				getValue : pbx.albumnavbar.getValue,
				setValue : pbx.albumnavbar.setValue
			}
		);

		if (typeof(pbx_studio_product) != 'undefined')
		{
			pbx.albumnavbar.product  = pbx_studio_product; // pbx_studio_product is defined in the studio component.
			var elements = pbx_studio_elms;    // pbx_studio_elms is defined in the studio component and sub components.
			pbx.albumnavbar.elements = elements;
			for (var elem in elements)
			{
				elements[elem].domObj = $('#' + elements[elem].id);
			}
		}
	},

	clear_cache : function()
	{
		pbx.albumnavbar.photos = new Array;
	},

	fetch_photo	: function(photo_id)
	{
		return pbx.babel.callBabel('Community.Photo.Fetch', photo_id).response;
	},

	get_photo : function(photo_id)
	{
		var photo;
		if(!(photo = pbx.albumnavbar.photos[photo_id]))
		{
			try
			{
				photo = pbx.albumnavbar.fetch_photo(photo_id);
				pbx.albumnavbar.photos[photo_id] = photo;
			}
			catch (e)
			{
				photo = null;
			}
		}
		return photo;
	},

	unselect_all : function()
	{
		$('div#pbx_album_navbar_slider img.pbx_selected:not(.pbx_hidden)').each(
			function()
			{
				$(this).removeClass('pbx_selected');
				this.s = false;
			}
		);
	},

	load_image : function(obj)
	{
		pbx.albumnavbar.add_to_basket_button.removeClass('pbx_disabled');
		pbx.albumnavbar.photo_actions.addClass('pbx_disabled');
		pbx.albumnavbar.photo_actions.children('a').addClass('pbx_disabled');

		pbx.albumnavbar.action_is_running();							// show the hourglass cursor
		var photo_id = $(obj).attr('id').replace('albumnavbar_','');

		// Fetch the photo object
		var photo = pbx.albumnavbar.get_photo(photo_id);
		if (!photo)
		{
			pbx.albumnavbar.action_is_done();
			return;
		}

		pbx.albumnavbar.refresh_photo_selector(photo_id, function(){
			pbx.albumnavbar.studio_photo_id = photo_id;
			// if the image is not selected
			if(!obj.s)
			{
				pbx.albumnavbar.unselect_all();
				obj.s = true;
				$(obj).addClass('pbx_selected');
			}
		});
	},

	/**
	 * Re-fetch the Photo selector working out the new crop etc.
	 * Replaces with the given photo_id if applicable.
	 * The callback function is only called if the refresh is a success.
	 */
	refresh_photo_selector : function(new_photo_id, callback)
	{
		var ajax_data = pbx.albumnavbar.get_crop();
		ajax_data.product_width  = pbx.albumnavbar.product_width;
		ajax_data.product_height = pbx.albumnavbar.product_height;

		ajax_data.photo_id   = new_photo_id || pbx.albumnavbar.studio_photo_id;

		$.ajax({
			type	: "POST",
			url		: "/includes/ajax/studio/photoselector",
			data	: ajax_data,
			success	: function(data)
			{
				$('#pbx_image_area_container').html(data);
				// get the new image area
				pbx.albumnavbar.image_area = $('div#pbx_image_area');

				// check the photo is present
				// it could "disappear" if the photo was shared with the current user and owner has removed sharing, or if the user has been logged out
				if (pbx.albumnavbar.image_area.find('img').length)
				{
					// common actions
					pbx.albumnavbar.image_area.removeClass('pbx_disabled');
					pbx.albumnavbar.photo_actions.find('a.pbx_icon_crop, a.pbx_icon_clear')
						.removeClass('pbx_disabled')
						.parent().removeClass('pbx_disabled');

					// if the user is the owner of the photo, allow the rotation
					if(pbx.albumnavbar.photos[ajax_data.photo_id].member_id.toString() == pbx.babel.member.id)
					{
						pbx.albumnavbar.photo_actions.find('a[class^=pbx_icon_rotate]')
							.removeClass('pbx_disabled')
							.parent().removeClass('pbx_disabled');
					}
					else
					{
						pbx.albumnavbar.photo_actions.find('a[class^=pbx_icon_rotate]')
							.addClass('pbx_disabled')
							.parent().addClass('pbx_disabled');
					}
				}
				else
				{
					pbx.albumnavbar.clear();
				}

				if (typeof(callback) == 'function')
				{
					callback();
				}

				pbx.albumnavbar.recalcQuality();
				pbx.albumnavbar.action_is_done();
			},
			resent	: 0,
			error	: function(xhr, textStatus, errorThrown)
			{
				if (xhr.status == 502 && this.resent < 3)
				{
					this.resent ? this.resent = 1 : this.resent++;
					$.ajax(this);
				}
				else
				{
					pbx.albumnavbar.action_is_done();
				}
			}
		});
	},

	clear : function(obj)
	{
		pbx.albumnavbar.add_to_basket_button.addClass('pbx_disabled');

		$('div#pbx_drop_box b').addClass('pbx_align_text');

		pbx.albumnavbar.action_is_running();							// show the hourglass cursor
		pbx.albumnavbar.photo_actions.addClass('pbx_disabled');
		pbx.albumnavbar.photo_actions.children('a').addClass('pbx_disabled');
		$('#pbx_drop_box').html($('#pbx_drop_box_emptycontent').html()).addClass('pbx_disabled');
		pbx.albumnavbar.image_area.addClass('pbx_disabled');

		pbx.albumnavbar.studio_photo_id = null;
		$('#pbx_quality').css('visibility', 'hidden');
		pbx.albumnavbar.clear_crop();
		pbx.albumnavbar.action_is_done();
	},

	rotate : function(params)
	{
		if($(params._this).is('.pbx_disabled'))
		{
			return;
		}
		try
		{
			// get the photo id and retrieve the object
			pbx.albumnavbar.action_is_running();
			var photo_id = pbx.albumnavbar.studio_photo_id;
			if (!photo_id)
			{
				return;
			}
			var photo = pbx.albumnavbar.get_photo(photo_id);

			// get the direction of rotation
			var direction = params.to == 'left' ? -90 : 90;

			var rotation = null;
			rotation = pbx.photo.getAttributes(photo).rotation;
			rotation = (rotation != 270) ? rotation + direction : 0;

			pbx.photo.setAttributes(photo, {rotation : rotation});
			pbx.albumnavbar.rotate_crop(direction);
			pbx.albumnavbar.refresh_photo_selector();
		}
		catch(e)
		{
			alert(e.message);
		}
		pbx.albumnavbar.action_is_done();
	},

	getItemId : function()
	{
		var item_id = $('#pbx_studio_add_basket').children('span').attr('id');
		if (item_id)
		{
			item_id = item_id.replace('pbx_item_','');
		}
		return item_id;
	},

	/* This is more like saveCreation now. It does not call Add to basket directly */
	addtobasket : function(params)
	{
		if(!pbx.albumnavbar.studio_photo_id)
		{
			return;
		}
		// getItemId for items that are already in the basket.
		var item_id = pbx.albumnavbar.getItemId();
		var new_quantity = parseInt(pbx.albumnavbar.qty.val());
		var pid = this.getProductId();

		var styles_dropdown = this.styles_dropdown;
		var sid = parseInt(styles_dropdown.val());
		if(!sid || styles_dropdown.attr('disabled'))
		{
			sid = 0;
		}

		var ajax_data = {
			pbx_studio_save_creation: 1,
			product_id : pid,
			style_id   : sid,
			photo_id   : pbx.albumnavbar.studio_photo_id,
			quantity   : new_quantity,
			item_id    : item_id
		};
		
		var crop_data = pbx.albumnavbar.get_crop();
		
		for (var c in crop_data)
		{
			ajax_data[c] = crop_data[c];
		}

		for (var elmnt in pbx.albumnavbar.elements)
		{
			ajax_data[elmnt] = pbx.albumnavbar.elements[elmnt].domObj.getValue();
		}
		
		params.ajax_data = ajax_data;
		
		try
		{
			$.ajax({
				type : "POST",
				url  : "/includes/ajax/studio/save_creation",
				data : ajax_data,
				success : function(response){pbx.albumnavbar.postSave(response, params)}
			});

			// Show the basket bubble
			if(!pbx.basket.loaded)
			{
				pbx.show_loading(false);
				pbx.show_overlay(false);
			}
			pbx.hide_dropdown();

			$('span#bubblebasket').each(
			function()
			{
				pbx.i18nplural('bubblebasket',new_quantity);
			}
			);
			pbx.ordering = 1; // because bubble uses mouseover event, we need this to stop the rollover cart popup being fired
			scrollTo(0,0);    // A hacky way of scrolling to the bubble
			pbx.bubble_show('a#pbx_basket_link', '200px');
			pbx.ordering = 0;
			$('div#pbx_popup_cart').removeClass('pbx_disabled');
		}
		catch (e)
		{

		}
	},

	postSave : function(response, params)
	{
		if (response.match(/pbx_studio_errors/))
		{
			pbx.popup.genericOK.open(pbx.popup.find_title(params), response);
		}
		else
		{
			$('span.pbx_bubble_async_status').html(100);
			setTimeout("pbx.bubble_hide('a#pbx_basket_link', true)", 3000);
			pbx.babel.basketcount_update(params.ajax_data.quantity);
			// Call analytics code
			try	{
				pbx.analytics.addedToBasket(pid, pbx.babel.basket_linecount.html(), 'Addition');
			} catch(e) { /* do nothing, its only analytics */ }
		}
	},

	/* Uses getQuality to update the quality meter on the page. */
	recalcQuality : function()
	{
		var quality = pbx.albumnavbar.getQuality();
		if (quality == -1)
		{
			$('div#pbx_content_area span#pbx_quality').css('visibility', 'hidden');
		}
		else
		{
			if (quality < 4)
			{
				$('div#pbx_content_area div.pbx_order_icon_quality_good').css('display', 'none');
				$('div#pbx_content_area div.pbx_order_icon_quality_low').css('display', 'none');
				$('div#pbx_content_area div.pbx_order_icon_quality_bad').css('display', 'block');
			}
			else if (quality < 8)
			{
				$('div#pbx_content_area div.pbx_order_icon_quality_good').css('display', 'none');
				$('div#pbx_content_area div.pbx_order_icon_quality_low').css('display', 'block');
				$('div#pbx_content_area div.pbx_order_icon_quality_bad').css('display', 'none');
			}
			else
			{
				$('div#pbx_content_area div.pbx_order_icon_quality_good').css('display', 'block');
				$('div#pbx_content_area div.pbx_order_icon_quality_low').css('display', 'none');
				$('div#pbx_content_area div.pbx_order_icon_quality_bad').css('display', 'none');
			}
			$('div#pbx_content_area span#pbx_quality').css('visibility', 'visible');
		}
	},
	
	/* Returns the quality value for the current photo, crop and product dimensions. */
	getQuality : function()
	{
		var min_res = pbx.albumnavbar.min_res;
		var crop = pbx.albumnavbar.get_crop();
		if (!pbx.albumnavbar.studio_photo_id)
		{
			return -1;
		}
		var photo = pbx.albumnavbar.get_photo(pbx.albumnavbar.studio_photo_id)
		var cropped_width  = Number(photo.width);
		var cropped_height = Number(photo.height);

		if (crop.fit != 1)
		{
			cropped_width  *= crop.cropw;
			cropped_height *= crop.croph;
		}
		var max_photo_dimension = pbx.albumnavbar.max_photo_dimension = Math.max(cropped_width, cropped_height);
		var oquality = 3.5 * max_photo_dimension / min_res;
		return oquality > 9.5 ? 10 : Math.floor(oquality + 0.5);
	},

	/* Responds to the user changing the product type. */
	get_product_list : function()
	{
		var product_id = this.options[this.selectedIndex].id;
		var product_value = this.options[this.selectedIndex].value;
		product_id = Number(product_id.replace(/\D/g, ''));

		pbx.babel.callBabel('Shopping.Product.Fetch', { objectid : product_id, object_property_filter : ['content_graphics_name','name', 'longdescription', 'min_resolution', 'width', 'height']},
			function(babel)
			{
				var product = pbx.albumnavbar.product = babel.response;
				// store product resolution in order to calculate quality
				pbx.albumnavbar.min_res = Number(product.min_resolution);
				pbx.albumnavbar.product_width = Number(product.width);
				pbx.albumnavbar.product_height = Number(product.height);
				if(typeof(pbx.albumnavbar.studio_photo_id) !== "undefined" ) pbx.albumnavbar.recalcQuality();
				// update style dropdown
				var styles_dropdown = pbx.albumnavbar.styles_dropdown;
				var styles = (pbx.babel.getStyle(product.id));
				if(styles.length)
				{
					defaultStyleId = pbx.babel.get_preference('default_style');
					styles_dropdown.removeClass('pbx_hidden').attr('disabled', '');
					var new_html = '';
					for(var b=0; b<styles.length; b++)
					{
						var selectedString = (defaultStyleId && defaultStyleId == styles[b].id) ? ' selected="selected"' : '';
						new_html += '<option value="' + styles[b].id + '"' + selectedString + '>' + styles[b].name + '</option>';
					}
					styles_dropdown.html(new_html);
				}
				else
				{
					styles_dropdown.addClass('pbx_hidden').attr('disabled', 'disabled');
				}

				// Update the photo details
				pbx.albumnavbar.clear_crop();
				if (pbx.albumnavbar.studio_photo_id)
				{
					pbx.albumnavbar.refresh_photo_selector();
				}

				// update product details
				var product_price;
				var graphic;

				product.callBabel('GetPrice',{},
					function(babel2)
					{
						product_price = babel2.response;
						pbx.babel.callBabel('Community.ContentGraphic.FetchFromName', { name : product.content_graphics_name, object_property_filter : ['asset_path']},
							function(babel3)
							{
								pbx.albumnavbar.product_title.html(product.name.toString());
								pbx.albumnavbar.product_desc.html(product.longdescription.toString());
								pbx.albumnavbar.product_price.html(product_price.toString());
								pbx.albumnavbar.product_img.attr(
									{
										src 	:	babel3 ? pbx.babel.contentGraphicToUrl(babel3.response) : '',
										alt		:	product.name.toString(),
										title	:	product.name.toString()
									}
								);
							}
						);
					}
				);

				// added feature: need to load as well product description (fs#1706)
				product.callBabel('GetExtendedPrice', null,
					function(babel)
					{
						pbx.albumnavbar.product_extprice.html(babel.response.toString());
					}
				);

				//Get the extra Studio UI options for the product.
				$.ajax(
					{
						type    : "POST",
						url     : "/includes/ajax/studio",
						data    : "productid=" + product_id,
						success : pbx.albumnavbar.ajaxExtrasSuccess,
						resent  : 0,
						error : function(xhr, msg, e)
						{
							if (xhr.status == 502 & this.resent < 3)
							{
								this.resent++;
								$.ajax(this);
							}
						}
					}
				);
			}
		);
	},

	/* Called after fetching the extra options panel for the product */
	ajaxExtrasSuccess : function(response)
	{
		var extras_box = $('#pbx_studio_extra_options');
		extras_box.html(response);
		// Parse javascript for browsers that don't automatically
		extras_box.find('script').each(function()
			{
				var script_string = $(this).html();
				eval(script_string.toString());
			}
		);
		pbx.albumnavbar.initStudioUi();
	},

	studio_process : function()
	{
		$("input#pbx_order_qty").bind('blur', pbx.albumnavbar.checknumber);
	},

	get_photos : function(e,a_id)
	{
		pbx.albumnavbar.photolist.addClass('pbx_hidden');
		pbx.albumnavbar.loader.removeClass('pbx_hidden');
		var photo_list = $('div#pbx_photolist');
		var album_id = this.value || a_id;
		var gp_ajax_data = {
				type		: 	"POST",
				url			: 	"/includes/ajax/nav/header/album_navbar",
				data		: 	"album_id=" + album_id,
				success		: 	function(result)
				{
					photo_list.html(result);
					pbx.albumnavbar.slider.tooltip(pbx.image_zoom);
					pbx.albumnavbar.loader.addClass('pbx_hidden');
					pbx.albumnavbar.photolist.removeClass('pbx_hidden');
					if (pbx.albumnavbar.localupload_photo_id)
					{
						$('img#albumnavbar_' + pbx.albumnavbar.localupload_photo_id).click();
						pbx.albumnavbar.localupload_photo_id = null;
					}
				},
				resent  : 0,
				error : function(xhr, msg, e)
				{
					if (xhr.status == 502 & this.resent < 3)
					{
						this.resent++;
						$.ajax(this);
					}
					else
					{
						pbx.albumnavbar.loader.addClass('pbx_hidden');
						pbx.albumnavbar.photolist.removeClass('pbx_hidden');
					}
				}
			}
		$.ajax(gp_ajax_data);
		/*Add the album id to the main upload link if it exists...*/
		var upload_menu = $('a#pbx_upload_link,li#pbx_topnav_upload_link a');
		if (upload_menu.length)
		{
			var upload_link = upload_menu.attr('href');
			var pos = upload_link.indexOf('?');
			if(pos == -1)
			{
				pos = upload_link.length;
			}
			upload_menu.attr('href', upload_link.substr(0, pos) + '?album_id=' + album_id);
		}
	},

	storenumber : function()
	{
		pbx.albumnavbar.last_qty = parseInt(pbx.albumnavbar.qty.attr('value'));
	},

	checknumber : function()
	{
		pbx.albumnavbar.qty.val(pbx.albumnavbar.qty.val().replace(/\D/g, ''));
		newValue = parseInt('0'+pbx.albumnavbar.qty.val(), 10);
		if(newValue == 0 || newValue < 0 || newValue > 999)
		{
			pbx.albumnavbar.qty.val(1);
			return false;
		}
		else
		{
			return true;
		}
	},

	/**
	 * Basicly a wraper for the crop popup.
	 * Needs to pass the photo_id dynamicaly
	 */
	crop : function(params)
	{
		if($(params._this).is('.pbx_disabled'))
		{
			return;
		}
		params.cat = 'popup';
		params.action = 'open';
		params.settings = 'pbx_popup_cropitem';
		params.submit_mode = '/studio/simple';
		params.item_id = pbx.albumnavbar.getItemId();
		params.photo_id = pbx.albumnavbar.studio_photo_id;
		params.product_id = pbx.albumnavbar.getProductId();
		params.crop_disable_changeproduct = 1;
		params.on_save = pbx.albumnavbar.save_crop;
		
		var crop = pbx.albumnavbar.get_crop();
		for (var c in crop)
		{
			params[c] = crop[c];
		}
		pbx.popup.open(params);
	},

	/**
	 * Saves the crop dimensions to hidden form elemnts.
	 * This function is parsed to and called from the crop popup.
	 * crop_dimensions = {cropw, croph, cropx, cropy, fit}
	 * It then reloads the photo selector.
	 */
	save_crop : function(crop_dimensions, params)
	{
		pbx.albumnavbar.action_is_running();
		pbx.albumnavbar.set_crop(crop_dimensions)
		pbx.albumnavbar.refresh_photo_selector();
	},

	/*
	 * Fetches saved crop values from the hidden form elemnets
	 */
	get_crop : function()
	{
		var crops = {};

		$('input.pbx_studio_crop').each(function()
			{
				var prop = this.name;
				var value = this.value;
				crops[prop] = value;
			});

		return crops;
	},

	/* Set the given crop dimensions to the hidden form inputs */
	set_crop : function(params)
	{
		var crops = {};
		var crop_dimensions = params;
		
		if (crop_dimensions.fit != 1)
		{
			crop_dimensions.fit = 'false';
		}
		$('input.pbx_studio_crop').each(function(i)
			{
				var ji = $(this);
				crops[ji.attr('name')] = ji.val(crop_dimensions[ji.attr('name')]);
			});
	},

	/* Resets the crop values to their defaults.
	 * Use this when changing the product type.
	 * You will need to refresh the image after calling this function. */
	clear_crop : function()
	{
		$('input.pbx_studio_crop').each(function(i)
			{
				var ji = $(this);
				ji.val("");
			});
	},

	rotate_crop : function(direction)
	{
		var crop = pbx.albumnavbar.get_crop();
		var oldx = crop.cropx;
		var oldy = crop.cropy;
		if (direction == -90)
		{
			crop.cropx = oldy;
			crop.cropy = 1 - crop.cropw - oldx;
		}
		else if (direction == 90)
		{
			crop.cropx = 1 - crop.croph - oldy;
			crop.cropy = oldx;
		}
		var oldw = crop.cropw;
		crop.cropw = crop.croph;
		crop.croph = oldw;
		pbx.albumnavbar.set_crop(crop);
	},

	/*
	 * change the cursor to a hourglass
	 */
	action_is_running : function()
	{
		$("#pbx_wrapper").addClass('pbx_busy');
	},

	/*
	 * change the cursor to normal
	 */
	action_is_done : function()
	{
		$("#pbx_wrapper").removeClass('pbx_busy');
	},

	getProductId : function()
	{
		var pid;
		
		if (pbx.albumnavbar.product_list.length > 0) 
		{
			pid = Number(pbx.albumnavbar.product_list[0].options[pbx.albumnavbar.product_list[0].selectedIndex].id.replace(/\D/g, ''))		
		}
		else
		{
			pid = pbx.albumnavbar.product_id;
		}
		return pid;
	},

	/******************************************************
	 ****    Functions for each Studio UI component    ****
	 ******************************************************/

	/* jQuery extension functions. _this should be a jQuery Object */
	getValue : function(_this)
	{
		var output = 0;
		if (!_this) _this = this;

		if (pbx.albumnavbar.elements[_this.attr('name')].getValue)
		{
			output = pbx.albumnavbar.elements[_this.attr('name')].getValue(_this)
		}
		else
		{
			var output = _this.val();
		}
		// This is for elements that depond on other elements. e.g. album and photo selectors.
		if (pbx.albumnavbar.elements[_this.attr('name')].outputList)
		{
			for (var elmtName in pbx.albumnavbar.elements[_this.attr('name')].outputList)
			{
				pbx.albumnavbar.elements[elmtName].domObj.setValue(output);
			}
		}
		return output;
	},

	setValue : function(_this, value)
	{
		if (!_this) _this = this;

		if (pbx.albumnavbar.elements[_this.attr('name')].setValue)
		{
			return pbx.albumnavbar.elements[_this.attr('name')].domObj.setValue(_this, value)
		}
		else
		{
			return $(_this).val(value);
		}
	},

	/**********************************************************
	 ****    Functions for Specific Studio UI component    ****
	 **********************************************************/

	/* Get the color from a colorpicker */
	selectColor : function()
	{

	}
};
pbx.basket = {
	loaded				:	false,				// flag used to know if we are on the basket page or not
	aSyncThresh			:	300,				// The number of lines required in the basket before we start using aSynch calls (add to basket always uses async).
	busy 				:	1,					// Flag to stop page refreshes while waiting for the backend to update
	changed				:	0,					// Flag to mark that the basket has been changed
	counter				:	new Object,			// Object to store counters for perticuler products, used for deleting / expanding product rows
	stopper				:	new Object,			// Object to store a stop value for perticuler products, used to stop deleting / expanding when asked to do the reverse
	init				:	function()
	{
		$("a.pbx_action_checkout").not('.pbx_login_needed').bind('click',
			function()
			{
				pbx.basket.submit(this, '1');
				return false;
			}
		);
		$("input.pbx_basket_form_delete").each(function() { $(this).removeAttr('checked'); } );
		$('.pbx_basket_empty').removeAttr('onclick');
		pbx.basket.busy--;
		pbx.basket.loaded = true;
		// hack to fix the firefox problem of drawing borders where it shouldn't.
		if($.browser.mozilla)
		{
			$('tr.pbx_basket_spacer').hide();
			$('tr.pbx_basket_spacer').show()
		}
		if(document.getElementById('pbx_basket_pageload_status_text1'))
		{
			if(!pbx.is_ie6 && $('#pbx_basket_pageload_status_text1')[0])
			{
				document.getElementById('pbx_basket_pageload_status_text1').innerHTML = '100%';
				document.getElementById('pbx_basket_pageload_status_text2').innerHTML = '100%';
				document.getElementById('pbx_basket_pageload_status_width').style.width = '100%';
			}
			pbx.show_loading(false);
			pbx.show_overlay(false);
		}
	},
	/*
	 * getParent returns the parent object (product group row) of an item.
	 * getChildren returns an array of items(item rows) of a product or if a function is supplied will perform that on each child instead
	 * getSiblings returns an array of rows which share the same product_id (including itself)
	 * getProductString returns the product string (eg 2-149) of either the parent row or single item
	 */
	getParent			:	function(_this)
	{
		if($(row).is('.pbx_basket_skip'))
		{
			pbx.basket.getChildren(row, func, callback, actionId);
		}
		else if(!$(_this).is('.pbx_basket_item_single') && $(_this).is('.pbx_basket_selectable'))
		{
			var row = $(_this).prev();
			while(!isParent)
			{
				if($(row).is('.pbx_basket_product_type'))
				{
					_this = row;
					var isParent = true;
				}
				row = $(row).prev();
			}
		}
		return _this;
	},
	getChildren			:	function(row, func, callback, actionId)
	{
		row = $(row).next();
		if($(row).is('.pbx_basket_skip'))
		{
			pbx.basket.getChildren(row, func, callback, actionId);
		}
		else if(!pbx.basket.stopper[actionId] && $(row).is('.pbx_basket_selectable') && !$(row).is('.pbx_basket_item_single'))
		{
			if(func)
			{
				func(row);
			}
			setTimeout(
				function()
				{
					pbx.basket.getChildren(row, func, callback, actionId);
				},
			0);
		}
		else
		{
			if(callback)
			{
				callback();
			}
			return;
		}
	},
	getSiblings			:	function(_this, pid, func)
	{
		var siblings = new Array;
		if ($(_this).is('.pbx_basket_product_type') || $(_this).is('.pbx_basket_item_single'))
		{
			if(func)
			{
				func(_this);
			}
			else
			{
				siblings.push(_this);
			}
			if(!pid)
			{
				pid = pbx.basket.getProductIds(_this).pid;
			}
			$(_this).siblings('tr.pbx_basket_product_type, tr.pbx_basket_item_single').each(
			function()
			{
				if(pid == pbx.basket.getProductIds(this).pid)
  				{
  					if(func)
  					{
  						func(this);
  					}
					else
					{
  						siblings.push(this);
  					}
  				}
			}	);
		}
		return siblings;
	},
	getProductIds		:	function(_this)
	{
		var productIds = new Object;
		var product_string;
		if(!$(_this).is('.pbx_basket_item_single'))
		{
			product_string = $(_this).attr('id').replace('pbx_basket_product_','');
		}
		else
		{
			product_string = $(_this).children('td.pbx_basket_item_product').attr('id').replace('pbx_basket_product_','');
		}
		productIds.pid = product_string.substring(0,product_string.indexOf('-'));
		productIds.sid = product_string.substring(product_string.indexOf('-')+1);
		return productIds;
	},
	/*
	 * checkLoaded()
	 * are the child items loaded
	 */
	checkLoaded			:	function(row, func)
	{
		if($(row).is('.pbx_basket_item_loading'))
		{
			setTimeout(
				function()
				{
					pbx.basket.checkLoaded(row, func);
				},
			200);
		}
		else
		{
			func();
		}
	},
	/*
	 * checkBusy()
	 * check if basket is doing critical task
	 */
	checkBusy			:	function(func)
	{
		if(pbx.basket.busy>0)
		{
			pbx.show_overlay(true);
			pbx.show_loading(true);
			setTimeout(
				function()
				{
					pbx.basket.checkBusy(func);
				},
			0);
		}
		else
		{
			func();
		}
	},
	/*
	 * markedChanged()
	 * do some stuff when the basket is changed
	 */
	markedChanged		:	function()
	{
		if(!pbx.basket.changed)
		{
			$('.pbx_action_submit').removeClass('pbx_disabled pbx_disabled_big');
			$("a.pbx_action_checkout").removeClass('pbx_login_needed');
			$("a.pbx_action_checkout").unbind('click');
			$("a.pbx_action_checkout").not('.pbx_login_needed').bind('click',
				function()
				{
					pbx.basket.submit(this, '1');
					return false;
				}
			);
			pbx.basket.changed = 1;
		}
	},
	/*
	 * changeQuantity()
	 * change the quantity of an item in the basket
	 */
	changeQuantity		:	function(_this)
	{
		if (!pbx.basket.loaded) { return; }
		var row = _this.parentNode.parentNode;
		if(!_this)
		{
			_this = this;
		}
		var oldValue = parseInt($(_this).attr("oldValue"), 10);
		var newValue = parseInt(_this.value, 10);
		if(isNaN(oldValue || oldValue == 0))
		{
			oldValue = 1;
		}
		if(isNaN(newValue) || newValue < 0)
		{
			$(_this).attr("value",oldValue);
		}
		else if(newValue == 0)
		{
			pbx.basket.deleteItem(_this);
			$(_this).attr("value",oldValue);
		}
		else
		{
			$(_this).attr('disabled','disabled');
			var id = row.id.replace('pbx_basket_item_','');
			var string = "quantity[" + id + "]";
			$(_this).attr('name',string);
			pbx.basket.markedChanged();
			$(_this).removeAttr('disabled');
		}
		$(_this).removeAttr("oldValue");
	},
	/*
	 * changeItem()
	 * change a single item in the basket
	 */
	changeItem			:	function(params)
	{
		var row = params._this.parentNode.parentNode;
		var id = $(row).attr('id').replace('pbx_basket_item_','');
		$("input[name='changeItem']").val('1');
		$("input[name='ItemId']").val(id);
		$("input[name='destProduct']").val(params.pid);
		$("input[name='destStyle']").val(params.style);
		$("input[name='asnew']").val(Number(params.newitem) || 0);
		$("input[name='quantity']").val(params.newquantity);
		// Make analytics call
		try
		{
			var addType = params.newitem? 'New Addition' : 'Modification';
			pbx.analytics.addedToBasket(params.pid, pbx.babel.basket_linecount.html(), addType);
		}
		catch(e)
		{
			// do nothing, its only analytics
		}
		document.pbx_basket_form.submit();
	},
	/*
	 * changeProduct()
	 * change an entire product in the basket
	 */
	changeProduct		:	function(params)
	{
		var row = params._this.parentNode.parentNode;
		var productIds = pbx.basket.getProductIds(row);
		$("input[name='changeProduct']").val('1');
		$("input[name='srcProduct']").val(productIds.pid);
		$("input[name='srcStyle']").val(productIds.sid);
		$("input[name='destProduct']").val(params.pid);
		$("input[name='destStyle']").val(params.style);
		$("input[name='asnew']").val(Number(params.newitem) || 0);
		$("input[name='quantity']").val(params.newquantity);
		// Make analytics call
		try
		{
			var addType = params.newitem? 'New Addition' : 'Modification';
			pbx.analytics.addedToBasket(params.pid, pbx.babel.basket_linecount.html(), addType);
		}
		catch(e)
		{
			// do nothing, its only analytics
		}
		document.pbx_basket_form.submit();
	},
	/*
	 * upsellChange()
	 * change a product using the upsell buttons
	 */
	upsellChange		:	function(_this, pid)
	{
		var row = $(_this).parent().parent().parent().parent().parent().prev();
		var productIds = pbx.basket.getProductIds(row);
		$("input[name='changeProduct']").val('1');
		$("input[name='srcProduct']").val(productIds.pid);
		$("input[name='srcStyle']").val(productIds.sid);
		$("input[name='destProduct']").val(pid);
		$("input[name='asnew']").val('0');
		// Make analytics call
		try
		{
			var addType = params.newitem? 'New Addition' : 'Modification';
			pbx.analytics.addedToBasket(params.pid, pbx.babel.basket_linecount.html(), addType);
		}
		catch(e)
		{
			// do nothing, its only analytics
		}
		document.pbx_basket_form.submit();
	},

	removeSpecialOffer : function(_this, offer_id)
	{
		var row = $(_this).parent().parent();
		var offer_text = $(row).find('span.pbx_basket_offer_text').html();

		var upsell_effect = '';
		var class_names = $(row).attr('class');
		if (class_names.match(/pbx_basket_is_upsell/))
		{
			upsell_effect = 'is';
		}
		else if (class_names.match(/pbx_basket_has_upsell/))
		{
			upsell_effect = 'has';
		}

		pbx.performDisableCheck(_this,
			function()
			{
				pbx.basket.checkBusy(
					function()
					{
							pbx.popup.open({ _this:_this, settings:'pbx_popup_basketofferremove', upsell_effect:upsell_effect, offer_text:offer_text });
					}
				);
			}
		);
		return false;
	},
	/*
	 * straight delete an item form the basket
	 */
	directDelete		:	function(_this)
	{
		var upsell_effect = '';
		var row = $(_this).parent().parent();
		var class_names = $(row).attr('class');
		if (class_names.match(/pbx_basket_is_upsell/))
		{
			upsell_effect = 'is';
		}
		else if (class_names.match(/pbx_basket_has_upsell/))
		{
			upsell_effect = 'has';
		}

		//directly call the submit
		pbx.performDisableCheck(_this,
			function()
			{
				pbx.basket.checkBusy(
					function()
					{
							pbx.popup.open({ _this : _this, settings : 'pbx_popup_basketitemdelete', upsell_effect : upsell_effect });
					}
				);
			}
		);
		return false;
	},
	/*
	 * deleteItem(_this), undeleteItem(_this)
	 * Delete/undelete a single item from the basket
	 * Currently used in basket error page.
	 */
	deleteItem			:	function(_this)
	{
		var row = $(_this).parent().parent();
		$(row).addClass('pbx_disabled');
		$(row).children('td.pbx_basket_item_quantity').children('input.pbx_basket_form_quantity').attr('disabled','disabled');
		$(row).children('td.pbx_basket_item_delete').children('input.pbx_basket_form_delete').attr('checked','checked');
		pbx.basket.markedChanged();
	},
	unDeleteItem			:	function(_this)
	{
		var row = $(_this).parent().parent();
		var parent = pbx.basket.getParent(row);
		$(row).removeClass('pbx_disabled');
		$(parent).removeClass('pbx_disabled');
		$(parent).children('td.pbx_basket_product_delete').children('input.pbx_basket_form_delete').removeAttr('checked');
		$(row).children('td.pbx_basket_item_quantity').children('input.pbx_basket_form_quantity').removeAttr('disabled');
		$(row).children('td.pbx_basket_item_delete').children('input.pbx_basket_form_delete').removeAttr('checked');
		return false;
	},
	/*
	 * deleteProduct(_this), undeleteProduct(_this)
	 * Delete a single item from the basket
	 * Currently used in basket error page.
	 */
	deleteProduct			:	function(_this)
	{
		var row = $(_this).parent().parent();
		var ProductIds = pbx.basket.getProductIds(row);
		var deletId = 'delete_'+ProductIds.pid+'-'+ProductIds.sid;
		var undelId = 'undelete_'+ProductIds.pid+'-'+ProductIds.sid;
		var counterId = 'delete_'+ProductIds.pid+'-'+ProductIds.sid;
		$(row).addClass('pbx_disabled');
		$(row).children('td.pbx_basket_product_delete').children('input.pbx_basket_form_delete').attr('checked','checked');
		pbx.basket.checkLoaded(row,
			function()
			{
				pbx.basket.stopper[deletId] = 0;
				pbx.basket.stopper[undelId] = 1;
				if(!pbx.basket.counter[counterId])
				{
					pbx.basket.counter[counterId] = 1;
				}
				else
				{
					pbx.basket.counter[counterId]++;
				}
				pbx.basket.getChildren(row,
					function(row)
					{
						if(pbx.basket.counter[counterId])
						{
							row.addClass('pbx_disabled');
							$(row).children('td.pbx_basket_item_quantity').children('input.pbx_basket_form_quantity').attr('disabled','disabled');
							$(row).children('td.pbx_basket_item_delete').children('input.pbx_basket_form_delete').attr('checked','checked');
							pbx.basket.counter[counterId]++;
						}
						else
						{
							pbx.basket.stopper[deletId] = 1;
						}
					},
					function()
					{
						if(!pbx.basket.stopper[deletId])
						{
							pbx.basket.counter[counterId] = 0;
						}
					}, deletId
				);
				pbx.show_loading(false);
				pbx.show_overlay(false);
			}
		);
		pbx.basket.markedChanged();
	},
	unDeleteProduct			:	function(_this)
	{
		var row = $(_this).parent().parent();
		var ProductIds = pbx.basket.getProductIds(row);
		var deletId = 'delete_'+ProductIds.pid+'-'+ProductIds.sid;
		var undelId = 'undelete_'+ProductIds.pid+'-'+ProductIds.sid;
		var counterId = 'delete_'+ProductIds.pid+'-'+ProductIds.sid;
		$(row).removeClass('pbx_disabled');
		$(row).children('td.pbx_basket_product_delete').children('input.pbx_basket_form_delete').removeAttr('checked');
		pbx.basket.checkLoaded(row,
			function()
			{
				pbx.basket.busy++;
				pbx.basket.stopper[deletId] = 1;
				pbx.basket.stopper[undelId] = 0;
				if(!pbx.basket.counter[counterId])
				{
					pbx.basket.counter[counterId] = -1;
				}
				else
				{
					pbx.basket.counter[counterId]--;
				}
				pbx.basket.getChildren(row,
					function(row)
					{
						if(pbx.basket.counter[counterId])
						{
							row.removeClass('pbx_disabled');
							$(row).children('td.pbx_basket_item_quantity').children('input.pbx_basket_form_quantity').removeAttr('disabled');
							$(row).children('td.pbx_basket_item_delete').children('input.pbx_basket_form_delete').removeAttr('checked');
							pbx.basket.counter[counterId]--;
						}
						else
						{
							pbx.basket.stopper[undelId] = 1;
						}
					},
					function()
					{
						if(!pbx.basket.stopper[undelId])
						{
							pbx.basket.counter[counterId] = 0;
						}
						pbx.basket.busy--;
					}, undelId
				);
			}
		);
	},
	/*
	 * add_offercode()
	 * add the offercode to the basket
	 */
	postOffer				:	function(offer_message)
	{
		$('#pbx_popup_content').find('input.pbx_submit_ok').bind('click',
			function()
			{
				document.pbx_basket_form.submit();
			}
		);
	},
	/*
	 * remove_offercode()
	 * remove the offercode from the basket
	 */
	remove_offercode		:	function(params)
	{
		$("input[name='removeMemberOffer']").val('1');
		eval('pbx.' + params.cat + '.' + params.action + '(params);');
	},
	restore_offercode		:	function(params)
	{
		$("input[name='removeMemberOffer']").val('0');
	},
	/*
	 * removeInValid()
	 * remove the offercode from the basket
	 */
	removeInValid			:	function()
	{
		$("input[name='rmValidate']").val('1');
		document.pbx_basket_form.submit();
		return false;
	},

	submit					:	function(_this, checkout)
	{
		pbx.performDisableCheck(_this,
			function()
			{
				pbx.basket.checkBusy(
					function()
					{
						$("input[name='checkout']").val(checkout);
					  	if($('tr.pbx_disabled:first').length)
						{
							pbx.popup.open({ _this : _this, settings : 'pbx_popup_basketitemdelete' });
					  	}
						else
						{
							document.pbx_basket_form.submit();
						}
					}
				);
			}
		);
		return false;
	}
};
pbx.analytics = {
	// Register the add to basket event
	addedToBasket:function(product_id, item_count, event_type) {
		var s = s_gi(s_account);
		s.linkTrackVars = "events,products";

		// If this is the first item in the basket
		if (item_count == 0) {
			s.linkTrackEvents = "scOpen,scAdd";
			s.events = "scOpen,scAdd";
		} else {
			s.linkTrackEvents = "scAdd";
			s.events = "scAdd";
		}
		s.products = ";" + product_id;
		s.tl(this,'o','Basket ' + event_type);
	},

	// Register purchase event
	orderTotal:function(quantity, price, vat_share, state, zip, purchase_id, order_count, product_string) {
		var s = s_gi(s_account);

		s.linkTrackVars = "events,products,state,zip,purchaseID";

		// If this is the user's first order
		if (order_count == 1) {
			s.linkTrackEvents="purchase,event15,event14";
			s.events="purchase,event15,event14";
		}
		else {
			s.linkTrackEvents = "purchase,event15";
			s.events = "purchase,event15";
		}

		s.state = state;
		s.zip = zip;
		s.purchaseID = purchase_id;

		s.products = product_string;

		s.tl(this,'o','Order Confirmation');
	},

	// Register a user registration
	regsiterUser:function() {
		var s = s_gi(s_account);

		s.linkTrackVars = "events";
		s.linkTrackEvents = "event1";
		s.events = "event1";
		s.tl(this,'o','Registration via Popup');
	},

	// Register livechats usage
	launchLiveChat:function(serviceAvailable) {
		var s = s_gi(s_account);

		var eventName = 'event23';
		var eventDescription = 'Livechat button - service unavailable';
		if (serviceAvailable)
		{
			eventName = 'event24';
			eventDescription = 'Livechat button - service available';
		}
		s.linkTrackVars = "events";
		s.linkTrackEvents = eventName;
		s.events = eventName;
		s.tl(this,'o',eventDescription);
	},

	// Register an opt in to newletters on checkout delivery page
	newsletterChosen:function() {
		var s = s_gi(s_account);

		s.linkTrackVars = "events";
		s.linkTrackEvents = "event17";
		s.events = "event17";
		s.tl(this,'o','Basket OptIn Checkbox');
	},

	/* Register upload
		Parameters:
		info : object
		uploader	:	aurigma | greenbox | http
		num_total	:	total photo uploaded
		num_ok		:	photos successfully uploaded
		num_error	:	photos with errors
	*/
	upload: function(info)
	{
		// prepare the event name and description to be passed to Omniture
		var event_name = '';
		var event_description = '';
		if (info.num_ok == info.num_total)
		{
		    // all ok
		    event_name = 'event2';
		    event_description = 'Upload Successful';
		}
		else if (info.num_error == info.num_total)
		{
		    // all errors
		    event_name = 'event3';
		    event_description = 'Upload Error';
		}
		else
		{
		    // both errors and ok
		    event_name = 'event4';
		    event_description = 'Upload Partial';
		}

		//alert('upload({uploader: ' + info.uploader + ', total: ' + info.num_total + ', ok: ' + info.num_ok + ', error: ' + info.num_error + '});n' + event_name + ', ' + event_description);
		var s = s_gi(s_account);
		s.linkTrackVars = "events,eVar15";
		s.linkTrackEvents = event_name;
		s.events = event_name;
		s.eVar15 = info.uploader;
		// please name the upload method chosen for this successful upload
		s.tl(this, 'o', event_description);
	},

	// Register orders clicks in Creation Preview page
	orderCreation: function() {
		var s = s_gi(s_account);

		s.linkTrackVars = "events";
		s.linkTrackEvents = "event19";
		s.events = "event19";
		s.tl(this,'o','Creation Page Order Button');
	},

	shareCreationResendInvites: function() {
		var s = s_gi(s_account);

		s.linkTrackVars = "events";
		s.linkTrackEvents = "event20";
		s.events = "event20";
		s.tl(this,'o','Creation Share Resend Creation Invites Button');
	},

	shareCreationSendInvites: function() {
		var s = s_gi(s_account);

		s.linkTrackVars = "events";
		s.linkTrackEvents = "event21";
		s.events = "event21";
		s.tl(this,'o','Creation Share Send Creation Invites Button');
	},

	shareAlbumResendInvites: function() {
		var s = s_gi(s_account);

		s.linkTrackVars = "events";
		s.linkTrackEvents = "event28";
		s.events = "event28";
		s.tl(this,'o','Creation Share Resend Creation Invites Button');
	},

	shareAlbumSendInvites: function() {
		var s = s_gi(s_account);

		s.linkTrackVars = "events";
		s.linkTrackEvents = "event25";
		s.events = "event25";
		s.tl(this,'o','Creation Share Send Creation Invites Button');
	},
	orderCreationPopup: function() {
		var s = s_gi(s_account);

		s.linkTrackVars = "events";
		s.linkTrackEvents = "event22";
		s.events = "event22";
		s.tl(this,'o','Order Button on the Creation Preview Order Popup');
	},

	shareCreationCupid: function() {
		var s = s_gi(s_account);

		s.linkTrackVars = "events";
		s.linkTrackEvents = "event26";
		s.events = "event26";
		s.tl(this,'o','Creation Cupid share button');
	},

	shareCreationPreview: function() {
		var s = s_gi(s_account);

		s.linkTrackVars = "events";
		s.linkTrackEvents = "event26";
		s.events = "event26";
		s.tl(this,'o','Creation Preview share buttons');
	},

	orderCreationPreview: function() {
		var s = s_gi(s_account);

		s.linkTrackVars = "events";
		s.linkTrackEvents = "event27";
		s.events = "event27";
		s.tl(this,'o','Creation Preview order buttons');
	}
};
/* Form Validation
 *
 * check a form is valid to submit based on rules
 * returned from the method Babel.Validate.GetRules.
 *
 * Originally written by Ben Cawkwell, PhotoBox August 2008
 */

//
// create closure
//
(function($)
{
	//
	// plugin definition
	//
	$.fn.validate = function(options)
	{
		// build main options before element iteration
		var opts = $.extend({}, $.fn.validate.defaults, options);
		// Keep a global validation record (good for debugging)
		pbx.validation_record = {};
		// iterate and check each matched element
		return this.each(
			function()
			{
				var $this = $(this);
				var form = $this;
				form[0].invalid = false;
				$this.resetErrors(); // hide the error of previous validate call
				// build element specific options
				var o = $.meta ? $.extend({}, opts, $this.data()) : opts;
				// run the before function if it exists
				if(o.before)
				{
					o.before(form)
				}
				// don't run validation of there are no validation rules
				var validationRules = pbx.form_validation[$this.attr('name')];
				pbx.validation_record[$this.attr('name')] = {};
				if (typeof(validationRules) != 'undefined')
				{
					// Fetch the error hash for this form and iterate over the children
					$.each(pbx.form_validation[$this.attr('name')],
						function(i,hash)
						{
							checker(form, hash, o);
						}
					);
				}
				pbx.form_validation[$this.attr('name')].valid = !form[0].invalid;

				if(form[0].invalid)
				{
					o.nosuccess(form);
				}
				else
				{
					o.success(form);
				}
			}
	)};
	//
	// private function iterating on check hashes
	//
	function checker(form,check,options)
	{
		var field_name = check.field;
		var field = form.find("[name='"+field_name+"']").not(':disabled'); // :enabled does not include hidden inputs. not(:disabled) does.
		// dont check the field if it does not exist and there is no forced_value for it.
		if (field.length > 0 || (options.forced_values && options.forced_values[field_name]))
		{
			var field_value = '';
			field_value = fieldValue(field, field_name, check, options);
			var is_valid = true;
			if (check['javascript_compare_field'])
			{
				// only equal and not equal (via nomatch) for now
				var field2 = form.find("[name='"+check['javascript_compare_field']+"']");
				if (field2.length)
				{
					var field_value2 = fieldValue(field2, '', check, options);
					var operator = check['javascript_compare_operator'] || '==';
					is_valid = eval('(typeof(field_value) == typeof(field_value2) && field_value ' + operator + ' field_value2)') ? !check['nomatch'] : check['nomatch'];
				}
			}
			else
			{
				// standard regex
				var searchString = (check['javascript'].match(/^\//)) ? eval(check['javascript']) : check['javascript'];
				// field is valid IF regexp matches XOR nomatch has been requested
				is_valid = (field_value.search(searchString) != -1) ? !check['nomatch'] : check['nomatch'] || false;
			}
			pbx.validation_record[form.attr('name')][field_name] = is_valid;
			if (is_valid)
			{
				// field valid: check any children
				options.passed(form, field_name, check['error_code']);
				$.each(check['children'],
					function(i, hash)
					{
						checker(form, hash, options);
					}
				);
			}
			// otherwise mark the form as invalid and display the error message if there is an error code
			else if(check['error_code'])
			{
				form[0].invalid = true;
				options.error(form, field_name, check['error_code']);
			}
		}
		else { pbx.validation_record[form.attr('name')][field_name] = ''; }
	};

	//
	// private function to get a field value
	//
	function fieldValue(field, field_name, check, options)
	{
		var field_value = '';

		// Check for forced values
		if(options.forced_values && options.forced_values[field_name])
		{
			field_value = options.forced_values[field_name]+'';
		}
		// Otherwise use the real value.
		else
		{
			if(field.is('input:checkbox'))
			{
				field_value = field.filter(':checked').length+'';
			}
			else if(field.is('input:radio'))
			{
				field_value = field.filter(':checked').val() || '';
			}
			else if(field.is('.pbx_inactive'))
			{
				field_value = '';
			}
			else
			{
				field_value = field.val();
			}
		}
		// Check if the field needs to be a certain type. Mainly used for comaprisons with other fields.
		if (check.field_type)
		{
			if (check.field_type == 'float')
			{
				field_value = parseFloat(field_value);
			}
			else if (check.field_type == 'int')
			{
				field_value = parseInt(field_value);
			}
		}

		return field_value;
	}

	//
	// form errors initialization
	//
	$.fn.resetErrors = function(){
		// hide all the form error message, if present
		this.find(".pbx_error_show").removeClass('pbx_error_show').hide();
	}

	//
	// plugin defaults
	//
	$.fn.validate.defaults =
	{
		success: function(form)
		{
			// when javascript validation has succeeded, validation on perl side is reduntant
			form.find("input[name='validationOk']").val(1);
			// hide the form error message, if present
			form.resetErrors();
			// submit the form
			form.submit();
		},
		nosuccess: function(form)
		{
			// javascript validation not succeeded
			form.find("input[name='validationOk']").val(0);
			// display a form related error message if present
			form.find(".pbx_error_"+form.attr('name')).addClass('pbx_error_show').show();
			return false;
		},
		error: function(form, field_name, error_code)
		{
			field_name = field_name.replace('[','_');
			field_name = field_name.replace(']','');
			field_name = field_name.replace('.','-');
			form.find(".pbx_error_"+field_name+"_"+error_code).addClass('pbx_error_show').show();
		},
		passed: function(form, field_name, error_code)
		{
			field_name = field_name.replace('[','_');
			field_name = field_name.replace(']','');
			form.find('.pbx_error_'+field_name+'_'+error_code).removeClass('pbx_error_show').hide();
		}
	};
//
// end of closure
//
})(jQuery);
pbx.form = {
	check_password	:	function()
	{
		if ($('input#pbx_confirm_password').val() != $('input#pbx_customer_password').val())
		{
			$(this).next('.pbx_error_msg').css('visibility','visible');
			return false;
		}
		else
		{
			$(this).next('.pbx_error_msg').css('visibility','hidden');
			return false;
		};
	},
	check_all		:	function()
	{
		var error = null;
		$('input.pbx_form_check').each(
			function()
			{
				if(!pbx.form.check(null,this))
				{
					error++;
				}
			}
		);

		if(error)
		{
			return false;
		}
		else
		{
			return true;
		}

	},
	check			:	function(e,elt)
	{

		if(!elt)
		{
			elt = this;
		}
		var pattern = null;
		switch($(elt).attr('pbx_type'))
		{
			case 'string' :
				pattern = /^[^\*\(\)\[\]\+\.\,\/\?\:\;\'\"\`\~\\\#\$�\xA3\%\^\&\<\>]+$/;
				break;
			case 'email' :
				pattern = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
				break;
			case 'date' :
				pattern = /(0[1-9]|1[012])+\/(0[1-9]|[12][0-9]|3[01])+\/(19|20)\d\d/;
				break;
		}

		if (($(elt).attr('pbx_type') == 'string') || ($(elt).attr('pbx_type') == 'email') || ($(elt).attr('pbx_type') == 'date'))
		{
			if($(elt).next().next('.pbx_error_msg_babel'))
			{
				if(elt.value_in_error != $(elt).val())
				{

					$(elt).next().next('.pbx_error_msg_babel').hide();
				}
				else
				{

					$(elt).next().next('.pbx_error_msg_babel').css('display', 'inline');
				}
			}

			if (!elt.value.match(pattern))
			{
				$(elt).next('.pbx_error_msg').css('display', 'inline');
				return false;
			}

			if($(elt).attr('pbx_size'))
			{
				if (elt.value.length >= $(elt).attr('pbx_size'))
				{
					$(elt).next('.pbx_error_msg').hide();
					return true;
				}
				else
				{
					$(elt).next('.pbx_error_msg').css('display', 'inline');
					return false;
				}
			}
		}
		else
		{

			if($('input#pbx_confirm_terms').attr('checked') != true)
			{
				$(elt).next().next('.pbx_error_msg').css('display', 'inline');
				return false;
			}
			else
			{
				$(elt).next().next('.pbx_error_msg').hide();
				return true;
			}
		}
	},
	/*
	 * toggleQuantity(_this, direction, callback)
	 * toggle the quantity either up or down
	 * direction - true = add, false = minus
	 */
	toggleQuantity		:	function(_this, direction, callback)
	{
		var input = $(_this.parentNode).prev()[0];
		var qty_max = 9999;
		if(pbx.order && pbx.order.qtymax)
		{
			qty_max = pbx.order.qtymax;
		}
		$(input).attr('oldValue',input.value);
		if(direction)
		{
			if(input.value<qty_max) input.value++;
		}
		else
		{
			if(input.value>1) input.value--;
		}
		if(typeof(callback) == 'function')
		{
			callback(input);
		}
	}
};

/*
 * jquery function for setting the enforcing a maximum number of checkboxes that can be selected.
 */
jQuery.fn.limit = function(settings)
{
	var self = this;
	return this.click(
		function()
		{
			if(self.filter(":checked").length<=settings['max'])
			{
				if(typeof settings.success == 'function')
				{
					settings.success();
				}
				return true;
			}
			else
			{
				if(typeof settings.error == 'function')
				{
					settings.error();
				}
				return false;
			}
		}
	);
};

/*
 * jquery function for updating the sibling elements when a product list dropdown is changed
 */
jQuery.fn.updateProduct = function(settings)
{
	var self = this;
	var parent_form = self.parents('form');
	var style_label = $('.pbx_order_style_label');
	if(style_label.length)
	{
		if(parent_form.find('select.pbx_order_product_related:visible').length)
		{
			style_label.removeClass('pbx_hidden');
		}
		else
		{
			style_label.addClass('pbx_hidden');
		}
	}
	return this.change(
		function()
		{
			var product_id = self.val();
			var related = parent_form.find('.pbx_order_product_id_'+product_id);
			parent_form.find('.pbx_order_product_related').addClass('pbx_hidden').filter('select').attr('disabled','disabled');
			related.removeClass('pbx_hidden').filter('select').removeAttr('disabled');
			if(style_label.length)
			{
				if(parent_form.find('select.pbx_order_product_related:visible').length)
				{
					style_label.removeClass('pbx_hidden');
				}
				else
				{
					style_label.addClass('pbx_hidden');
				}
			}
		}
	);
};

/*
 * jquery function for Adding ad-hoc hidden elements.
 * Each added element is given a class name of pbx_added_dynamically for easy retrieval later.
 */
jQuery.fn.addValue = function(my_name, my_value)
{
	if (this.is('form'))
	{
		this.append('<input class="pbx_added_dynamically" type="hidden" name="' + my_name + '" value="' + my_value + '" />');
	}
	return this;
};
/*
 * jquery function for Disabling or enabling form elements.
 * Each element will have its disabled attribute set and the class 'pbx_disabled' added/removed to it's parent <p> tag
 * parameter - do_disable - (boolean) set to true to disable, false to enable
 */
jQuery.fn.disable = function(do_disable)
{
	if (do_disable) this.attr('disabled', 'disabled').parent('p').addClass('pbx_disabled');
	else this.removeAttr('disable').parent('p').removeClass('pbx_disabled');
	return this;
};
/*
 * Makes form elements look and behave as though they are disabled without disabling them.
 * This is so that the values of the elements are still validated and submitted while stopping users from editing them.
 * parameters
 * do_disable: (boolean) set to true to disable, false to enable
 * focus_target: (jQuery Object) The first element will recieve focus instead of the disabled element.
 */
jQuery.fn.fakeDisable = function(do_disable, focus_target)
{
	if (do_disable){
		this.bind('focus', function(){
			if (focus_target && focus_target.length > 0)
			{
				$(focus_target[0]).trigger('focus');
			}
			else
			{
				var nearest_sibling = $(this).parents('form').find('input,select,textarea').not(':hidden,.pbx_hidden,.pbx_disabled');
				if (nearest_sibling.length > 0) $(nearest_sibling[0]).trigger('focus');
			}
			return false;
		}).bind('click', function(){
			return false;
		}).addClass('pbx_disabled').parent('p').addClass('pbx_disabled');
	}
	else {
		this.unbind('focus').unbind('click').removeClass('pbx_disabled').parent('p').removeClass('pbx_disabled');
	}
	return this;
};
/*
 * Get namespace details from an input
 * parameters
 * detail: (string) can be 'action', 'property', 'key' or 'value'
 */
jQuery.fn.getNamespaceDetail = function(detail)
{
	var string = this.attr('name');
	var regex = /.+/;
	if(detail == 'action')
	{
		regex = /^(\w+(\d+)?)\[/;
	}
	else if(detail == 'property')
	{
		regex = /\[(\w+(\d+)?)/;
	}
	else if(detail == 'key')
	{
		regex = /\.(\w+(\d+)?)/;
	}
	else if(detail == 'value')
	{
		regex = /\:(\w+(\d+)?)]$/;
	}
	var array = regex.exec(string);
	return array[1];
};
/*
 * change namespace details of inputs
 * parameters
 * settings: (object) can contain key 'action', 'property', 'key' or 'value', where the value is the text to be changed to.
 */
jQuery.fn.changeNamespace = function(settings)
{
	this.each(
		function(i)
		{
			var _this = $(this);
			var field_name = _this.attr('name');
			if(settings.action)
			{
				var old_value = _this.getNamespaceDetail('action');
				var regex = new RegExp(old_value);
				field_name = field_name.replace(regex,settings.action);
			}
			if(settings.property)
			{
				var old_value = _this.getNamespaceDetail('property');
				var regex = new RegExp(old_value);
				field_name = field_name.replace(regex,settings.property);
			}
			if(settings.key)
			{
				var old_value = _this.getNamespaceDetail('key');
				var regex = new RegExp(old_value);
				field_name = field_name.replace(regex,settings.key);
			}
			if(settings.value)
			{
				var old_value = _this.getNamespaceDetail('value');
				var regex = new RegExp(old_value);
				field_name = field_name.replace(regex,settings.value);
			}
			_this.attr('name',field_name);
		}
	);
	return this;
};
/*
 * strip namespace details from inputs
 * parameters
 * settings: (object) can contain key 'action', 'property', 'key' or 'value', where the value is the text to be striped.
 */
jQuery.fn.stripNamespace = function(settings)
{
	this.each(
		function(i)
		{
			var _this = $(this);
			var field_name = _this.attr('name');
			if(settings.action)
			{
				// check if its the performAction field, then remove its value
				if(field_name == 'performAction')
				{
					_this.attr('value','');
				}
				// otherwise stip action from the name
				else
				{
					var action = '^'+settings.action;
					var regex = new RegExp(action);
					field_name = field_name.replace(regex,'');
					field_name = field_name.replace(/\[/,'');
					field_name = field_name.replace(/\]/,'');
				}
			}
			if(settings.property)
			{
				var property = settings.property+'\.';
				var regex = new RegExp(property);
				field_name = field_name.replace(regex,'');
				field_name = field_name.replace(/\[/,'');
				field_name = field_name.replace(/\]/,'');
			}
			_this.attr('name',field_name);
		}
	);
	return this;
};
﻿/**
* hoverIntent r5 // 2007.03.27 // jQuery 1.1.2+
* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
* 
* @param  f  onMouseOver function || An object with configuration options
* @param  g  onMouseOut function  || Nothing (use configuration options object)
* @author    Brian Cherne <brian@cherne.net>
*/
(function($){$.fn.hoverIntent=function(f,g){var cfg={sensitivity:7,interval:100,timeout:0};cfg=$.extend(cfg,g?{over:f,out:g}:f);var cX,cY,pX,pY;var track=function(ev){cX=ev.pageX;cY=ev.pageY;};var compare=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);if((Math.abs(pX-cX)+Math.abs(pY-cY))<cfg.sensitivity){$(ob).unbind("mousemove",track);ob.hoverIntent_s=1;return cfg.over.apply(ob,[ev]);}else{pX=cX;pY=cY;ob.hoverIntent_t=setTimeout(function(){compare(ev,ob);},cfg.interval);}};var delay=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);ob.hoverIntent_s=0;return cfg.out.apply(ob,[ev]);};var handleHover=function(e){var p=(e.type=="mouseover"?e.fromElement:e.toElement)||e.relatedTarget;while(p&&p!=this){try{p=p.parentNode;}catch(e){p=this;}}if(p==this){return false;}var ev=jQuery.extend({},e);var ob=this;if(ob.hoverIntent_t){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);}if(e.type=="mouseover"){pX=ev.pageX;pY=ev.pageY;$(ob).bind("mousemove",track);if(ob.hoverIntent_s!=1){ob.hoverIntent_t=setTimeout(function(){compare(ev,ob);},cfg.interval);}}else{$(ob).unbind("mousemove",track);if(ob.hoverIntent_s==1){ob.hoverIntent_t=setTimeout(function(){delay(ev,ob);},cfg.timeout);}}};return this.mouseover(handleHover).mouseout(handleHover);};})(jQuery);/*
 * pbx.topNavHandler - Topnav effects
 *
 * Required plugins:
 * - jquery.hoverIntent.min.js
 */

pbx.topNavHandler = {

	workspaceWidth : 990,
	dropdownCentering : false,
	dropdownCenteringClass : 'pbx_dropdown_center',

	albumListShow : function()
	{
		$("#pbx_myalbums_selector_listing").slideDown();
	},

	albumListHide : function()
	{
		$("#pbx_myalbums_selector_listing").hide();
	},

	albumListInit : function()
	{

		// Combobox selector link event
		$("#pbx_myalbums_selector_combobox").toggle(
				function(){
					pbx.topNavHandler.albumListShow();
				},
				function(){
					pbx.topNavHandler.albumListHide();
				}
		);

		// Combobox list links event
		$("#pbx_myalbums_selector_listing a").click(function()
		{
			theValue = $(this).text();
			$("#pbx_myalbums_selector_combobox").html(theValue.substr(0, 20) + "...");
			pbx.topNavHandler.albumListHide();
		});
	},

	dropdownSlideDown : function() {
		$(this)
		.addClass("pbx_selected")
		.addClass("pbx_opened")
		.children(".pbx_topnav_dropdown").bgIframe()
		.show();
	},

	dropdownSlideUp : function() {
		$(this)
		.removeClass("pbx_opened")
		.removeClass("pbx_selected")
		.children(".pbx_topnav_dropdown")
		.hide();
		/* close the album list */
		pbx.topNavHandler.albumListHide();
	},

	dropdownsHover : function()
	{
		$("#pbx_header .pbx_dropdown_enable").hoverIntent( {
			sensitivity : 3,
			interval : 200,
			over : pbx.topNavHandler.dropdownSlideDown,
			timeout : 300,
			out : pbx.topNavHandler.dropdownSlideUp
		});
	},

	dropdownsPosition : function(level1Menu)
	{

		var parentWidth = level1Menu.width();
		var parentPosition = level1Menu.position();
		var parentLeft = parentPosition.left;
		var dropdownLayer = level1Menu.find(".pbx_topnav_dropdown");
		var dropdownLayerWidth = dropdownLayer.width();
		var dropdownLeftpos = 0;

		// Dropdown resizing
		// -----------------

		// Dropdown width is narrower than its parent menu
		if (dropdownLayerWidth < parentWidth) {
			while (dropdownLayerWidth < parentWidth) {
				dropdownLayerWidth += 1;
			}
			dropdownLayerWidth += 10; /* + 10 for design matter */
			dropdownLayer.css("width", dropdownLayerWidth + "px");
		}

		// Dropdown width is equal or larger than workspace
		if (dropdownLayerWidth >= pbx.topNavHandler.workspaceWidth) {
			// Change dropdown width
			dropdownLayerWidth = pbx.topNavHandler.workspaceWidth;
			dropdownLayer.css("width", dropdownLayerWidth + "px");
		}

		// Dropdown positioning
		// --------------------

		// Centering dropdown
		if (dropdownLayerWidth > parentWidth && (pbx.topNavHandler.dropdownCentering || dropdownLayer.hasClass(pbx.topNavHandler.dropdownCenteringClass))) {
			var dropdownLayerCenterPoint = dropdownLayerWidth / 2;
			var parentCenterPoint = parentWidth / 2;
			dropdownLeftpos = parentCenterPoint - dropdownLayerCenterPoint + 2;
		}

		// Check if the layer doesn't go accross borders
		dropdownLayerRightpos = parentLeft + dropdownLeftpos + dropdownLayerWidth;
		dropdownLeftposAbs = Math.abs(dropdownLeftpos);

		// If dropdown layer is going accross the workspace right border
		if (dropdownLayerRightpos > pbx.topNavHandler.workspaceWidth) {
			accrossWidth = dropdownLayerRightpos - pbx.topNavHandler.workspaceWidth;
			dropdownLeftpos = dropdownLeftpos - accrossWidth;
		}
		// If dropdown layer is going accross the workspace left border
		else if (dropdownLeftposAbs > parentLeft) {
			accrossWidth = parentLeft - dropdownLeftposAbs;
			dropdownLeftpos = dropdownLeftpos - accrossWidth;
		}

		// Applying new left position
		dropdownLayer.css("left", dropdownLeftpos + "px");

	},

	dropdownsInit : function() {
		$("#pbx_header .pbx_dropdown_enable").each(function() {
			pbx.topNavHandler.dropdownsPosition($(this));
		});

		$("#pbx_header .pbx_dropdown_disable").hover(
			function() {
				$(this).addClass('pbx_selected');
			},
			function() {
				$(this).removeClass('pbx_selected');
			}
		);

		pbx.topNavHandler.dropdownsHover();
	},

	// Function to update fav count
	updateFavCount : function(count)
	{
		var span = $('span#album_photocount_fav');
		if(span)
		{
			var old_string = span.html() || '0';
			var old_count = old_string.match(/[0-9]+/)[0];
			count = count + (old_count * 1);
			if(isNaN(count) || count < 0)
			{
				count = '0';
			}
			var string = old_string.replace(/[0-9]+/, count);
			span.html(string);
		}
	}


};
// end of pbx.topNavHandler{};

$(document).ready(function() {

		// Init dropdowns
		// pbx.topNavHandler.dropdownCentering = true;
		pbx.topNavHandler.dropdownsInit();

		// Init albums list menu
		pbx.topNavHandler.albumListInit();

});
//$(document).ready(
	//function()
	//{
	   //	if(typeof(XMLRPC)==='undefined' || !XMLRPC)
	   //	{
			//return;
	   //}
		//pbx.babel.init();
		//pbx.init()
	//}
//);