/*
 * jquery.tools 1.1.2 - The missing UI library for the Web
 * 
 * [tools.tabs-1.0.4, tools.tabs.slideshow-1.0.2, tools.tabs.history-1.0.2, tools.tooltip-1.1.3, tools.tooltip.slide-1.0.0, tools.tooltip.dynamic-1.0.1, tools.scrollable-1.1.2, tools.scrollable.circular-0.5.1, tools.scrollable.autoscroll-1.0.1, tools.scrollable.navigator-1.0.2, tools.scrollable.mousewheel-1.0.1, tools.overlay-1.1.2, tools.overlay.gallery-1.0.0, tools.overlay.apple-1.0.1, tools.expose-1.0.5]
 * 
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 * 
 * -----
 * 
 * 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
 *
 * 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/
 * 
 * -----
 * 
 * jquery.event.wheel.js - rev 1 
 * Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)
 * Liscensed under the MIT License (MIT-LICENSE.txt)
 * http://www.opensource.org/licenses/mit-license.php
 * Created: 2008-07-01 | Updated: 2008-07-14
 * 
 * -----
 * 
 * File generated: Thu Feb 25 20:36:17 GMT 2010
 */
(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)})}});
(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")}})})();
(function(d){d.tools=d.tools||{};d.tools.tabs={version:"1.0.4",conf:{tabs:"a",current:"current",onBeforeClick:null,onClick:null,effect:"default",initialIndex:0,event:"click",api:false,rotate:false},addEffect:function(e,f){c[e]=f}};var c={"default":function(f,e){this.getPanes().hide().eq(f).show();e.call()},fade:function(g,e){var f=this.getConf(),j=f.fadeOutSpeed,h=this.getPanes();if(j){h.fadeOut(j)}else{h.hide()}h.eq(g).fadeIn(f.fadeInSpeed,e)},slide:function(f,e){this.getPanes().slideUp(200);this.getPanes().eq(f).slideDown(400,e)},ajax:function(f,e){this.getPanes().eq(0).load(this.getTabs().eq(f).attr("href"),e)}};var b;d.tools.tabs.addEffect("horizontal",function(f,e){if(!b){b=this.getPanes().eq(0).width()}this.getCurrentPane().animate({width:0},function(){d(this).hide()});this.getPanes().eq(f).animate({width:b},function(){d(this).show();e.call()})});function a(g,h,f){var e=this,j=d(this),i;d.each(f,function(k,l){if(d.isFunction(l)){j.bind(k,l)}});d.extend(this,{click:function(k,n){var o=e.getCurrentPane();var l=g.eq(k);if(typeof k=="string"&&k.replace("#","")){l=g.filter("[href*="+k.replace("#","")+"]");k=Math.max(g.index(l),0)}if(f.rotate){var m=g.length-1;if(k<0){return e.click(m,n)}if(k>m){return e.click(0,n)}}if(!l.length){if(i>=0){return e}k=f.initialIndex;l=g.eq(k)}if(k===i){return e}n=n||d.Event();n.type="onBeforeClick";j.trigger(n,[k]);if(n.isDefaultPrevented()){return}c[f.effect].call(e,k,function(){n.type="onClick";j.trigger(n,[k])});n.type="onStart";j.trigger(n,[k]);if(n.isDefaultPrevented()){return}i=k;g.removeClass(f.current);l.addClass(f.current);return e},getConf:function(){return f},getTabs:function(){return g},getPanes:function(){return h},getCurrentPane:function(){return h.eq(i)},getCurrentTab:function(){return g.eq(i)},getIndex:function(){return i},next:function(){return e.click(i+1)},prev:function(){return e.click(i-1)},bind:function(k,l){j.bind(k,l);return e},onBeforeClick:function(k){return this.bind("onBeforeClick",k)},onClick:function(k){return this.bind("onClick",k)},unbind:function(k){j.unbind(k);return e}});g.each(function(k){d(this).bind(f.event,function(l){e.click(k,l);return false})});if(location.hash){e.click(location.hash)}else{if(f.initialIndex===0||f.initialIndex>0){e.click(f.initialIndex)}}h.find("a[href^=#]").click(function(k){e.click(d(this).attr("href"),k)})}d.fn.tabs=function(i,f){var g=this.eq(typeof f=="number"?f:0).data("tabs");if(g){return g}if(d.isFunction(f)){f={onBeforeClick:f}}var h=d.extend({},d.tools.tabs.conf),e=this.length;f=d.extend(h,f);this.each(function(l){var j=d(this);var k=j.find(f.tabs);if(!k.length){k=j.children()}var m=i.jquery?i:j.children(i);if(!m.length){m=e==1?d(i):j.parent().find(i)}g=new a(k,m,f);j.data("tabs",g)});return f.api?g:this}})(jQuery);
(function(b){var a=b.tools.tabs;a.plugins=a.plugins||{};a.plugins.slideshow={version:"1.0.2",conf:{next:".forward",prev:".backward",disabledClass:"disabled",autoplay:false,autopause:true,interval:3000,clickable:true,api:false}};b.prototype.slideshow=function(e){var f=b.extend({},a.plugins.slideshow.conf),c=this.length,d;e=b.extend(f,e);this.each(function(){var p=b(this),m=p.tabs(),i=b(m),o=m;b.each(e,function(t,u){if(b.isFunction(u)){m.bind(t,u)}});function n(t){return c==1?b(t):p.parent().find(t)}var s=n(e.next).click(function(){m.next()});var q=n(e.prev).click(function(){m.prev()});var h,j,l,g=false;b.extend(m,{play:function(){if(h){return}var t=b.Event("onBeforePlay");i.trigger(t);if(t.isDefaultPrevented()){return m}g=false;h=setInterval(m.next,e.interval);i.trigger("onPlay");m.next()},pause:function(){if(!h){return m}var t=b.Event("onBeforePause");i.trigger(t);if(t.isDefaultPrevented()){return m}h=clearInterval(h);l=clearInterval(l);i.trigger("onPause")},stop:function(){m.pause();g=true},onBeforePlay:function(t){return m.bind("onBeforePlay",t)},onPlay:function(t){return m.bind("onPlay",t)},onBeforePause:function(t){return m.bind("onBeforePause",t)},onPause:function(t){return m.bind("onPause",t)}});if(e.autopause){var k=m.getTabs().add(s).add(q).add(m.getPanes());k.hover(function(){m.pause();j=clearInterval(j)},function(){if(!g){j=setTimeout(m.play,e.interval)}})}if(e.autoplay){l=setTimeout(m.play,e.interval)}else{m.stop()}if(e.clickable){m.getPanes().click(function(){m.next()})}if(!m.getConf().rotate){var r=e.disabledClass;if(!m.getIndex()){q.addClass(r)}m.onBeforeClick(function(u,t){if(!t){q.addClass(r)}else{q.removeClass(r);if(t==m.getTabs().length-1){s.addClass(r)}else{s.removeClass(r)}}})}});return e.api?d:this}})(jQuery);
(function(d){var a=d.tools.tabs;a.plugins=a.plugins||{};a.plugins.history={version:"1.0.2",conf:{api:false}};var e,b;function c(f){if(f){var g=b.contentWindow.document;g.open().close();g.location.hash=f}}d.fn.onHash=function(g){var f=this;if(d.browser.msie&&d.browser.version<"8"){if(!b){b=d("<iframe/>").attr("src","javascript:false;").hide().get(0);d("body").append(b);setInterval(function(){var i=b.contentWindow.document,j=i.location.hash;if(e!==j){d.event.trigger("hash",j);e=j}},100);c(location.hash||"#")}f.bind("click.hash",function(h){c(d(this).attr("href"))})}else{setInterval(function(){var j=location.hash;var i=f.filter("[href$="+j+"]");if(!i.length){j=j.replace("#","");i=f.filter("[href$="+j+"]")}if(i.length&&j!==e){e=j;d.event.trigger("hash",j)}},100)}d(window).bind("hash",g);return this};d.fn.history=function(g){var h=d.extend({},a.plugins.history.conf),f;g=d.extend(h,g);this.each(function(){var j=d(this).tabs(),i=j.getTabs();if(j){f=j}i.onHash(function(k,l){if(!l||l=="#"){l=j.getConf().initialIndex}j.click(l)});i.click(function(k){location.hash=d(this).attr("href").replace("#","")})});return g.api?f:this}})(jQuery);
(function(c){var d=[];c.tools=c.tools||{};c.tools.tooltip={version:"1.1.3",conf:{effect:"toggle",fadeOutSpeed:"fast",tip:null,predelay:0,delay:30,opacity:1,lazy:undefined,position:["top","center"],offset:[0,0],cancelDefault:true,relative:false,oneInstance:true,events:{def:"mouseover,mouseout",input:"focus,blur",widget:"focus mouseover,blur mouseout",tooltip:"mouseover,mouseout"},api:false},addEffect:function(e,g,f){b[e]=[g,f]}};var b={toggle:[function(e){var f=this.getConf(),g=this.getTip(),h=f.opacity;if(h<1){g.css({opacity:h})}g.show();e.call()},function(e){this.getTip().hide();e.call()}],fade:[function(e){this.getTip().fadeIn(this.getConf().fadeInSpeed,e)},function(e){this.getTip().fadeOut(this.getConf().fadeOutSpeed,e)}]};function a(f,g){var p=this,k=c(this);f.data("tooltip",p);var l=f.next();if(g.tip){l=c(g.tip);if(l.length>1){l=f.nextAll(g.tip).eq(0);if(!l.length){l=f.parent().nextAll(g.tip).eq(0)}}}function o(u){var t=g.relative?f.position().top:f.offset().top,s=g.relative?f.position().left:f.offset().left,v=g.position[0];t-=l.outerHeight()-g.offset[0];s+=f.outerWidth()+g.offset[1];var q=l.outerHeight()+f.outerHeight();if(v=="center"){t+=q/2}if(v=="bottom"){t+=q}v=g.position[1];var r=l.outerWidth()+f.outerWidth();if(v=="center"){s-=r/2}if(v=="left"){s-=r}return{top:t,left:s}}var i=f.is(":input"),e=i&&f.is(":checkbox, :radio, select, :button"),h=f.attr("type"),n=g.events[h]||g.events[i?(e?"widget":"input"):"def"];n=n.split(/,\s*/);if(n.length!=2){throw"Tooltip: bad events configuration for "+h}f.bind(n[0],function(r){if(g.oneInstance){c.each(d,function(){this.hide()})}var q=l.data("trigger");if(q&&q[0]!=this){l.hide().stop(true,true)}r.target=this;p.show(r);n=g.events.tooltip.split(/,\s*/);l.bind(n[0],function(){p.show(r)});if(n[1]){l.bind(n[1],function(){p.hide(r)})}});f.bind(n[1],function(q){p.hide(q)});if(!c.browser.msie&&!i&&!g.predelay){f.mousemove(function(){if(!p.isShown()){f.triggerHandler("mouseover")}})}if(g.opacity<1){l.css("opacity",g.opacity)}var m=0,j=f.attr("title");if(j&&g.cancelDefault){f.removeAttr("title");f.data("title",j)}c.extend(p,{show:function(r){if(r){f=c(r.target)}clearTimeout(l.data("timer"));if(l.is(":animated")||l.is(":visible")){return p}function q(){l.data("trigger",f);var t=o(r);if(g.tip&&j){l.html(f.data("title"))}r=r||c.Event();r.type="onBeforeShow";k.trigger(r,[t]);if(r.isDefaultPrevented()){return p}t=o(r);l.css({position:"absolute",top:t.top,left:t.left});var s=b[g.effect];if(!s){throw'Nonexistent effect "'+g.effect+'"'}s[0].call(p,function(){r.type="onShow";k.trigger(r)})}if(g.predelay){clearTimeout(m);m=setTimeout(q,g.predelay)}else{q()}return p},hide:function(r){clearTimeout(l.data("timer"));clearTimeout(m);if(!l.is(":visible")){return}function q(){r=r||c.Event();r.type="onBeforeHide";k.trigger(r);if(r.isDefaultPrevented()){return}b[g.effect][1].call(p,function(){r.type="onHide";k.trigger(r)})}if(g.delay&&r){l.data("timer",setTimeout(q,g.delay))}else{q()}return p},isShown:function(){return l.is(":visible, :animated")},getConf:function(){return g},getTip:function(){return l},getTrigger:function(){return f},bind:function(q,r){k.bind(q,r);return p},onHide:function(q){return this.bind("onHide",q)},onBeforeShow:function(q){return this.bind("onBeforeShow",q)},onShow:function(q){return this.bind("onShow",q)},onBeforeHide:function(q){return this.bind("onBeforeHide",q)},unbind:function(q){k.unbind(q);return p}});c.each(g,function(q,r){if(c.isFunction(r)){p.bind(q,r)}})}c.prototype.tooltip=function(e){var f=this.eq(typeof e=="number"?e:0).data("tooltip");if(f){return f}var g=c.extend(true,{},c.tools.tooltip.conf);if(c.isFunction(e)){e={onBeforeShow:e}}else{if(typeof e=="string"){e={tip:e}}}e=c.extend(true,g,e);if(typeof e.position=="string"){e.position=e.position.split(/,?\s/)}if(e.lazy!==false&&(e.lazy===true||this.length>20)){this.one("mouseover",function(h){f=new a(c(this),e);f.show(h);d.push(f)})}else{this.each(function(){f=new a(c(this),e);d.push(f)})}return e.api?f:this}})(jQuery);
(function(b){var a=b.tools.tooltip;a.effects=a.effects||{};a.effects.slide={version:"1.0.0"};b.extend(a.conf,{direction:"up",bounce:false,slideOffset:10,slideInSpeed:200,slideOutSpeed:200,slideFade:!b.browser.msie});var c={up:["-","top"],down:["+","top"],left:["-","left"],right:["+","left"]};b.tools.tooltip.addEffect("slide",function(d){var f=this.getConf(),g=this.getTip(),h=f.slideFade?{opacity:f.opacity}:{},e=c[f.direction]||c.up;h[e[1]]=e[0]+"="+f.slideOffset;if(f.slideFade){g.css({opacity:0})}g.show().animate(h,f.slideInSpeed,d)},function(e){var g=this.getConf(),i=g.slideOffset,h=g.slideFade?{opacity:0}:{},f=c[g.direction]||c.up;var d=""+f[0];if(g.bounce){d=d=="+"?"-":"+"}h[f[1]]=d+"="+i;this.getTip().animate(h,g.slideOutSpeed,function(){b(this).hide();e.call()})})})(jQuery);
(function(d){var c=d.tools.tooltip;c.plugins=c.plugins||{};c.plugins.dynamic={version:"1.0.1",conf:{api:false,classNames:"top right bottom left"}};function b(h){var e=d(window);var g=e.width()+e.scrollLeft();var f=e.height()+e.scrollTop();return[h.offset().top<=e.scrollTop(),g<=h.offset().left+h.width(),f<=h.offset().top+h.height(),e.scrollLeft()>=h.offset().left]}function a(f){var e=f.length;while(e--){if(f[e]){return false}}return true}d.fn.dynamic=function(g){var h=d.extend({},c.plugins.dynamic.conf),f;if(typeof g=="number"){g={speed:g}}g=d.extend(h,g);var e=g.classNames.split(/\s/),i;this.each(function(){if(d(this).tooltip().jquery){throw"Lazy feature not supported by dynamic plugin. set lazy: false for tooltip"}var j=d(this).tooltip().onBeforeShow(function(n,o){var m=this.getTip(),l=this.getConf();if(!i){i=[l.position[0],l.position[1],l.offset[0],l.offset[1],d.extend({},l)]}d.extend(l,i[4]);l.position=[i[0],i[1]];l.offset=[i[2],i[3]];m.css({visibility:"hidden",position:"absolute",top:o.top,left:o.left}).show();var k=b(m);if(!a(k)){if(k[2]){d.extend(l,g.top);l.position[0]="top";m.addClass(e[0])}if(k[3]){d.extend(l,g.right);l.position[1]="right";m.addClass(e[1])}if(k[0]){d.extend(l,g.bottom);l.position[0]="bottom";m.addClass(e[2])}if(k[1]){d.extend(l,g.left);l.position[1]="left";m.addClass(e[3])}if(k[0]||k[2]){l.offset[0]*=-1}if(k[1]||k[3]){l.offset[1]*=-1}}m.css({visibility:"visible"}).hide()});j.onShow(function(){var l=this.getConf(),k=this.getTip();l.position=[i[0],i[1]];l.offset=[i[2],i[3]]});j.onHide(function(){var k=this.getTip();k.removeClass(g.classNames)});f=j});return g.api?f:this}})(jQuery);
(function(b){b.tools=b.tools||{};b.tools.scrollable={version:"1.1.2",conf:{size:5,vertical:false,speed:400,keyboard:true,keyboardSteps:null,disabledClass:"disabled",hoverClass:null,clickable:true,activeClass:"active",easing:"swing",loop:false,items:".items",item:null,prev:".prev",next:".next",prevPage:".prevPage",nextPage:".nextPage",api:false}};var c;function a(o,m){var r=this,p=b(this),d=!m.vertical,e=o.children(),k=0,i;if(!c){c=r}b.each(m,function(s,t){if(b.isFunction(t)){p.bind(s,t)}});if(e.length>1){e=b(m.items,o)}function l(t){var s=b(t);return m.globalNav?s:o.parent().find(t)}o.data("finder",l);var f=l(m.prev),h=l(m.next),g=l(m.prevPage),n=l(m.nextPage);b.extend(r,{getIndex:function(){return k},getClickIndex:function(){var s=r.getItems();return s.index(s.filter("."+m.activeClass))},getConf:function(){return m},getSize:function(){return r.getItems().size()},getPageAmount:function(){return Math.ceil(this.getSize()/m.size)},getPageIndex:function(){return Math.ceil(k/m.size)},getNaviButtons:function(){return f.add(h).add(g).add(n)},getRoot:function(){return o},getItemWrap:function(){return e},getItems:function(){return e.children(m.item)},getVisibleItems:function(){return r.getItems().slice(k,k+m.size)},seekTo:function(s,w,t){if(s<0){s=0}if(k===s){return r}if(b.isFunction(w)){t=w}if(s>r.getSize()-m.size){return m.loop?r.begin():this.end()}var u=r.getItems().eq(s);if(!u.length){return r}var v=b.Event("onBeforeSeek");p.trigger(v,[s]);if(v.isDefaultPrevented()){return r}if(w===undefined||b.isFunction(w)){w=m.speed}function x(){if(t){t.call(r,s)}p.trigger("onSeek",[s])}if(d){e.animate({left:-u.position().left},w,m.easing,x)}else{e.animate({top:-u.position().top},w,m.easing,x)}c=r;k=s;v=b.Event("onStart");p.trigger(v,[s]);if(v.isDefaultPrevented()){return r}f.add(g).toggleClass(m.disabledClass,s===0);h.add(n).toggleClass(m.disabledClass,s>=r.getSize()-m.size);return r},move:function(u,t,s){i=u>0;return this.seekTo(k+u,t,s)},next:function(t,s){return this.move(1,t,s)},prev:function(t,s){return this.move(-1,t,s)},movePage:function(w,v,u){i=w>0;var s=m.size*w;var t=k%m.size;if(t>0){s+=(w>0?-t:m.size-t)}return this.move(s,v,u)},prevPage:function(t,s){return this.movePage(-1,t,s)},nextPage:function(t,s){return this.movePage(1,t,s)},setPage:function(t,u,s){return this.seekTo(t*m.size,u,s)},begin:function(t,s){i=false;return this.seekTo(0,t,s)},end:function(t,s){i=true;var u=this.getSize()-m.size;return u>0?this.seekTo(u,t,s):r},reload:function(){p.trigger("onReload");return r},focus:function(){c=r;return r},click:function(u){var v=r.getItems().eq(u),s=m.activeClass,t=m.size;if(u<0||u>=r.getSize()){return r}if(t==1){if(m.loop){return r.next()}if(u===0||u==r.getSize()-1){i=(i===undefined)?true:!i}return i===false?r.prev():r.next()}if(t==2){if(u==k){u--}r.getItems().removeClass(s);v.addClass(s);return r.seekTo(u,time,fn)}if(!v.hasClass(s)){r.getItems().removeClass(s);v.addClass(s);var x=Math.floor(t/2);var w=u-x;if(w>r.getSize()-t){w=r.getSize()-t}if(w!==u){return r.seekTo(w)}}return r},bind:function(s,t){p.bind(s,t);return r},unbind:function(s){p.unbind(s);return r}});b.each("onBeforeSeek,onStart,onSeek,onReload".split(","),function(s,t){r[t]=function(u){return r.bind(t,u)}});f.addClass(m.disabledClass).click(function(){r.prev()});h.click(function(){r.next()});n.click(function(){r.nextPage()});if(r.getSize()<m.size){h.add(n).addClass(m.disabledClass)}g.addClass(m.disabledClass).click(function(){r.prevPage()});var j=m.hoverClass,q="keydown."+Math.random().toString().substring(10);r.onReload(function(){if(j){r.getItems().hover(function(){b(this).addClass(j)},function(){b(this).removeClass(j)})}if(m.clickable){r.getItems().each(function(s){b(this).unbind("click.scrollable").bind("click.scrollable",function(t){if(b(t.target).is("a")){return}return r.click(s)})})}if(m.keyboard){b(document).unbind(q).bind(q,function(t){if(t.altKey||t.ctrlKey){return}if(m.keyboard!="static"&&c!=r){return}var u=m.keyboardSteps;if(d&&(t.keyCode==37||t.keyCode==39)){r.move(t.keyCode==37?-u:u);return t.preventDefault()}if(!d&&(t.keyCode==38||t.keyCode==40)){r.move(t.keyCode==38?-u:u);return t.preventDefault()}return true})}else{b(document).unbind(q)}});r.reload()}b.fn.scrollable=function(d){var e=this.eq(typeof d=="number"?d:0).data("scrollable");if(e){return e}var f=b.extend({},b.tools.scrollable.conf);d=b.extend(f,d);d.keyboardSteps=d.keyboardSteps||d.size;this.each(function(){e=new a(b(this),d);b(this).data("scrollable",e)});return d.api?e:this}})(jQuery);
(function(b){var a=b.tools.scrollable;a.plugins=a.plugins||{};a.plugins.circular={version:"0.5.1",conf:{api:false,clonedClass:"cloned"}};b.fn.circular=function(e){var d=b.extend({},a.plugins.circular.conf),c;b.extend(d,e);this.each(function(){var i=b(this).scrollable(),n=i.getItems(),k=i.getConf(),f=i.getItemWrap(),j=0;if(i){c=i}if(n.length<k.size){return false}n.slice(0,k.size).each(function(o){b(this).clone().appendTo(f).click(function(){i.click(n.length+o)}).addClass(d.clonedClass)});var l=b.makeArray(n.slice(-k.size)).reverse();b(l).each(function(o){b(this).clone().prependTo(f).click(function(){i.click(-o-1)}).addClass(d.clonedClass)});var m=f.children(k.item);var h=k.hoverClass;if(h){m.hover(function(){b(this).addClass(h)},function(){b(this).removeClass(h)})}function g(o){var p=m.eq(o);if(k.vertical){f.css({top:-p.position().top})}else{f.css({left:-p.position().left})}}g(k.size);b.extend(i,{move:function(s,r,p,q){var u=j+s+k.size;var t=u>i.getSize()-k.size;if(u<=0||t){var o=j+k.size+(t?-n.length:n.length);g(o);u=o+s}if(q){m.removeClass(k.activeClass).eq(u+Math.floor(k.size/2)).addClass(k.activeClass)}if(u===j+k.size){return self}return i.seekTo(u,r,p)},begin:function(p,o){return this.seekTo(k.size,p,o)},end:function(p,o){return this.seekTo(n.length,p,o)},click:function(p,r,q){if(!k.clickable){return self}if(k.size==1){return this.next()}var s=p-j,o=k.activeClass;s-=Math.floor(k.size/2);return this.move(s,r,q,true)},getIndex:function(){return j},setPage:function(p,q,o){return this.seekTo(p*k.size+k.size,q,o)},getPageAmount:function(){return Math.ceil(n.length/k.size)},getPageIndex:function(){if(j<0){return this.getPageAmount()-1}if(j>=n.length){return 0}var o=(j+k.size)/k.size-1;return o},getVisibleItems:function(){var o=j+k.size;return m.slice(o,o+k.size)}});i.onStart(function(p,o){j=o-k.size;return false});i.getNaviButtons().removeClass(k.disabledClass)});return d.api?c:this}})(jQuery);
(function(b){var a=b.tools.scrollable;a.plugins=a.plugins||{};a.plugins.autoscroll={version:"1.0.1",conf:{autoplay:true,interval:3000,autopause:true,steps:1,api:false}};b.fn.autoscroll=function(d){if(typeof d=="number"){d={interval:d}}var e=b.extend({},a.plugins.autoscroll.conf),c;b.extend(e,d);this.each(function(){var g=b(this).scrollable();if(g){c=g}var i,f,h=true;g.play=function(){if(i){return}h=false;i=setInterval(function(){g.move(e.steps)},e.interval);g.move(e.steps)};g.pause=function(){i=clearInterval(i)};g.stop=function(){g.pause();h=true};if(e.autopause){g.getRoot().add(g.getNaviButtons()).hover(function(){g.pause();clearInterval(f)},function(){if(!h){f=setTimeout(g.play,e.interval)}})}if(e.autoplay){setTimeout(g.play,e.interval)}});return e.api?c:this}})(jQuery);
(function(b){var a=b.tools.scrollable;a.plugins=a.plugins||{};a.plugins.navigator={version:"1.0.2",conf:{navi:".navi",naviItem:null,activeClass:"active",indexed:false,api:false,idPrefix:null}};b.fn.navigator=function(d){var e=b.extend({},a.plugins.navigator.conf),c;if(typeof d=="string"){d={navi:d}}d=b.extend(e,d);this.each(function(){var i=b(this).scrollable(),f=i.getRoot(),l=f.data("finder").call(null,d.navi),g=null,k=i.getNaviButtons();if(i){c=i}i.getNaviButtons=function(){return k.add(l)};function j(){if(!l.children().length||l.data("navi")==i){l.empty();l.data("navi",i);for(var m=0;m<i.getPageAmount();m++){l.append(b("<"+(d.naviItem||"a")+"/>"))}g=l.children().each(function(n){var o=b(this);o.click(function(p){i.setPage(n);return p.preventDefault()});if(d.indexed){o.text(n)}if(d.idPrefix){o.attr("id",d.idPrefix+n)}})}else{g=d.naviItem?l.find(d.naviItem):l.children();g.each(function(n){var o=b(this);o.click(function(p){i.setPage(n);return p.preventDefault()})})}g.eq(0).addClass(d.activeClass)}i.onStart(function(o,n){var m=d.activeClass;g.removeClass(m).eq(i.getPageIndex()).addClass(m)});i.onReload(function(){j()});j();var h=g.filter("[href="+location.hash+"]");if(h.length){i.move(g.index(h))}});return d.api?c:this}})(jQuery);
(function(b){b.fn.wheel=function(e){return this[e?"bind":"trigger"]("wheel",e)};b.event.special.wheel={setup:function(){b.event.add(this,d,c,{})},teardown:function(){b.event.remove(this,d,c)}};var d=!b.browser.mozilla?"mousewheel":"DOMMouseScroll"+(b.browser.version<"1.9"?" mousemove":"");function c(e){switch(e.type){case"mousemove":return b.extend(e.data,{clientX:e.clientX,clientY:e.clientY,pageX:e.pageX,pageY:e.pageY});case"DOMMouseScroll":b.extend(e,e.data);e.delta=-e.detail/3;break;case"mousewheel":e.delta=e.wheelDelta/120;break}e.type="wheel";return b.event.handle.call(this,e,e.delta)}var a=b.tools.scrollable;a.plugins=a.plugins||{};a.plugins.mousewheel={version:"1.0.1",conf:{api:false,speed:50}};b.fn.mousewheel=function(f){var g=b.extend({},a.plugins.mousewheel.conf),e;if(typeof f=="number"){f={speed:f}}f=b.extend(g,f);this.each(function(){var h=b(this).scrollable();if(h){e=h}h.getRoot().wheel(function(i,j){h.move(j<0?1:-1,f.speed||50);return false})});return f.api?e:this}})(jQuery);
(function(c){c.tools=c.tools||{};c.tools.overlay={version:"1.1.2",addEffect:function(e,f,g){b[e]=[f,g]},conf:{top:"10%",left:"center",absolute:false,speed:"normal",closeSpeed:"fast",effect:"default",close:null,oneInstance:true,closeOnClick:true,closeOnEsc:true,api:false,expose:null,target:null}};var b={};c.tools.overlay.addEffect("default",function(e){this.getOverlay().fadeIn(this.getConf().speed,e)},function(e){this.getOverlay().fadeOut(this.getConf().closeSpeed,e)});var d=[];function a(g,k){var o=this,m=c(this),n=c(window),j,i,h,e=k.expose&&c.tools.expose.version;var f=k.target||g.attr("rel");i=f?c(f):null||g;if(!i.length){throw"Could not find Overlay: "+f}if(g&&g.index(i)==-1){g.click(function(p){o.load(p);return p.preventDefault()})}c.each(k,function(p,q){if(c.isFunction(q)){m.bind(p,q)}});c.extend(o,{load:function(u){if(o.isOpened()){return o}var r=b[k.effect];if(!r){throw'Overlay: cannot find effect : "'+k.effect+'"'}if(k.oneInstance){c.each(d,function(){this.close(u)})}u=u||c.Event();u.type="onBeforeLoad";m.trigger(u);if(u.isDefaultPrevented()){return o}h=true;if(e){i.expose().load(u)}var t=k.top;var s=k.left;var p=i.outerWidth({margin:true});var q=i.outerHeight({margin:true});if(typeof t=="string"){t=t=="center"?Math.max((n.height()-q)/2,0):parseInt(t,10)/100*n.height()}if(s=="center"){s=Math.max((n.width()-p)/2,0)}if(!k.absolute){t+=n.scrollTop();s+=n.scrollLeft()}i.css({top:t,left:s,position:"absolute"});u.type="onStart";m.trigger(u);r[0].call(o,function(){if(h){u.type="onLoad";m.trigger(u)}});if(k.closeOnClick){c(document).bind("click.overlay",function(w){if(!o.isOpened()){return}var v=c(w.target);if(v.parents(i).length>1){return}c.each(d,function(){this.close(w)})})}if(k.closeOnEsc){c(document).unbind("keydown.overlay").bind("keydown.overlay",function(v){if(v.keyCode==27){c.each(d,function(){this.close(v)})}})}return o},close:function(q){if(!o.isOpened()){return o}q=q||c.Event();q.type="onBeforeClose";m.trigger(q);if(q.isDefaultPrevented()){return}h=false;b[k.effect][1].call(o,function(){q.type="onClose";m.trigger(q)});var p=true;c.each(d,function(){if(this.isOpened()){p=false}});if(p){c(document).unbind("click.overlay").unbind("keydown.overlay")}return o},getContent:function(){return i},getOverlay:function(){return i},getTrigger:function(){return g},getClosers:function(){return j},isOpened:function(){return h},getConf:function(){return k},bind:function(p,q){m.bind(p,q);return o},unbind:function(p){m.unbind(p);return o}});c.each("onBeforeLoad,onStart,onLoad,onBeforeClose,onClose".split(","),function(p,q){o[q]=function(r){return o.bind(q,r)}});if(e){if(typeof k.expose=="string"){k.expose={color:k.expose}}c.extend(k.expose,{api:true,closeOnClick:k.closeOnClick,closeOnEsc:false});var l=i.expose(k.expose);l.onBeforeClose(function(p){o.close(p)});o.onClose(function(p){l.close(p)})}j=i.find(k.close||".close");if(!j.length&&!k.close){j=c('<div class="close"></div>');i.prepend(j)}j.click(function(p){o.close(p)})}c.fn.overlay=function(e){var f=this.eq(typeof e=="number"?e:0).data("overlay");if(f){return f}if(c.isFunction(e)){e={onBeforeLoad:e}}var g=c.extend({},c.tools.overlay.conf);e=c.extend(true,g,e);this.each(function(){f=new a(c(this),e);d.push(f);c(this).data("overlay",f)});return e.api?f:this}})(jQuery);
(function(b){var a=b.tools.overlay;a.plugins=a.plugins||{};a.plugins.gallery={version:"1.0.0",conf:{imgId:"img",next:".next",prev:".prev",info:".info",progress:".progress",disabledClass:"disabled",activeClass:"active",opacity:0.8,speed:"slow",template:"<strong>${title}</strong> <span>Image ${index} of ${total}</span>",autohide:true,preload:true,api:false}};b.fn.gallery=function(d){var o=b.extend({},a.plugins.gallery.conf),m;b.extend(o,d);m=this.overlay();var r=this,j=m.getOverlay(),k=j.find(o.next),g=j.find(o.prev),e=j.find(o.info),c=j.find(o.progress),h=g.add(k).add(e).css({opacity:o.opacity}),s=m.getClosers(),l;function p(u){c.fadeIn();h.hide();s.hide();var t=u.attr("href");var v=new Image();v.onload=function(){c.fadeOut();var y=b("#"+o.imgId,j);if(!y.length){y=b("<img/>").attr("id",o.imgId).css("visibility","hidden");j.prepend(y)}y.attr("src",t).css("visibility","hidden");var z=v.width;var A=(b(window).width()-z)/2;l=r.index(r.filter("[href="+t+"]"));r.removeClass(o.activeClass).eq(l).addClass(o.activeClass);var w=o.disabledClass;h.removeClass(w);if(l===0){g.addClass(w)}if(l==r.length-1){k.addClass(w)}var B=o.template.replace("${title}",u.attr("title")||u.data("title")).replace("${index}",l+1).replace("${total}",r.length);var x=parseInt(e.css("paddingLeft"),10)+parseInt(e.css("paddingRight"),10);e.html(B).css({width:z-x});j.animate({width:z,height:v.height,left:A},o.speed,function(){y.hide().css("visibility","visible").fadeIn(function(){if(!o.autohide){h.fadeIn();s.show()}})})};v.onerror=function(){j.fadeIn().html("Cannot find image "+t)};v.src=t;if(o.preload){r.filter(":eq("+(l-1)+"), :eq("+(l+1)+")").each(function(){var w=new Image();w.src=b(this).attr("href")})}}function f(t,u){t.click(function(){if(t.hasClass(o.disabledClass)){return}var v=r.eq(i=l+(u?1:-1));if(v.length){p(v)}})}f(k,true);f(g);b(document).keydown(function(t){if(!j.is(":visible")||t.altKey||t.ctrlKey){return}if(t.keyCode==37||t.keyCode==39){var u=t.keyCode==37?g:k;u.click();return t.preventDefault()}return true});function q(){if(!j.is(":animated")){h.show();s.show()}}if(o.autohide){j.hover(q,function(){h.fadeOut();s.hide()}).mousemove(q)}var n;this.each(function(){var v=b(this),u=b(this).overlay(),t=u;u.onBeforeLoad(function(){p(v)});u.onClose(function(){r.removeClass(o.activeClass)})});return o.api?n:this}})(jQuery);
(function(d){var b=d.tools.overlay;b.effects=b.effects||{};b.effects.apple={version:"1.0.1"};d.extend(b.conf,{start:{absolute:true,top:null,left:null},fadeInSpeed:"fast",zIndex:9999});function c(f){var g=f.offset();return[g.top+f.height()/2,g.left+f.width()/2]}var e=function(n){var k=this.getOverlay(),f=this.getConf(),i=this.getTrigger(),q=this,r=k.outerWidth({margin:true}),m=k.data("img");if(!m){var l=k.css("backgroundImage");if(!l){throw"background-image CSS property not set for overlay"}l=l.substring(l.indexOf("(")+1,l.indexOf(")")).replace(/\"/g,"");k.css("backgroundImage","none");m=d('<img src="'+l+'"/>');m.css({border:0,position:"absolute",display:"none"}).width(r);d("body").append(m);k.data("img",m)}var o=d(window),j=f.start.top||Math.round(o.height()/2),h=f.start.left||Math.round(o.width()/2);if(i){var g=c(i);j=g[0];h=g[1]}if(!f.start.absolute){j+=o.scrollTop();h+=o.scrollLeft()}m.css({top:j,left:h,width:0,zIndex:f.zIndex}).show();m.animate({top:k.css("top"),left:k.css("left"),width:r},f.speed,function(){k.css("zIndex",f.zIndex+1).fadeIn(f.fadeInSpeed,function(){if(q.isOpened()&&!d(this).index(k)){n.call()}else{k.hide()}})})};var a=function(f){var h=this.getOverlay(),i=this.getConf(),g=this.getTrigger(),l=i.start.top,k=i.start.left;h.hide();if(g){var j=c(g);l=j[0];k=j[1]}h.data("img").animate({top:l,left:k,width:0},i.closeSpeed,f)};b.addEffect("apple",e,a)})(jQuery);
(function(b){b.tools=b.tools||{};b.tools.expose={version:"1.0.5",conf:{maskId:null,loadSpeed:"slow",closeSpeed:"fast",closeOnClick:true,closeOnEsc:true,zIndex:9998,opacity:0.8,color:"#456",api:false}};function a(){if(b.browser.msie){var f=b(document).height(),e=b(window).height();return[window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,f-e<20?e:f]}return[b(window).width(),b(document).height()]}function c(h,g){var e=this,j=b(this),d=null,f=false,i=0;b.each(g,function(k,l){if(b.isFunction(l)){j.bind(k,l)}});b(window).resize(function(){e.fit()});b.extend(this,{getMask:function(){return d},getExposed:function(){return h},getConf:function(){return g},isLoaded:function(){return f},load:function(n){if(f){return e}i=h.eq(0).css("zIndex");if(g.maskId){d=b("#"+g.maskId)}if(!d||!d.length){var l=a();d=b("<div/>").css({position:"absolute",top:0,left:0,width:l[0],height:l[1],display:"none",opacity:0,zIndex:g.zIndex});if(g.maskId){d.attr("id",g.maskId)}b("body").append(d);var k=d.css("backgroundColor");if(!k||k=="transparent"||k=="rgba(0, 0, 0, 0)"){d.css("backgroundColor",g.color)}if(g.closeOnEsc){b(document).bind("keydown.unexpose",function(o){if(o.keyCode==27){e.close()}})}if(g.closeOnClick){d.bind("click.unexpose",function(o){e.close(o)})}}n=n||b.Event();n.type="onBeforeLoad";j.trigger(n);if(n.isDefaultPrevented()){return e}b.each(h,function(){var o=b(this);if(!/relative|absolute|fixed/i.test(o.css("position"))){o.css("position","relative")}});h.css({zIndex:Math.max(g.zIndex+1,i=="auto"?0:i)});var m=d.height();if(!this.isLoaded()){d.css({opacity:0,display:"block"}).fadeTo(g.loadSpeed,g.opacity,function(){if(d.height()!=m){d.css("height",m)}n.type="onLoad";j.trigger(n)})}f=true;return e},close:function(k){if(!f){return e}k=k||b.Event();k.type="onBeforeClose";j.trigger(k);if(k.isDefaultPrevented()){return e}d.fadeOut(g.closeSpeed,function(){k.type="onClose";j.trigger(k);h.css({zIndex:b.browser.msie?i:null})});f=false;return e},fit:function(){if(d){var k=a();d.css({width:k[0],height:k[1]})}},bind:function(k,l){j.bind(k,l);return e},unbind:function(k){j.unbind(k);return e}});b.each("onBeforeLoad,onLoad,onBeforeClose,onClose".split(","),function(k,l){e[l]=function(m){return e.bind(l,m)}})}b.fn.expose=function(d){var e=this.eq(typeof d=="number"?d:0).data("expose");if(e){return e}if(typeof d=="string"){d={color:d}}var f=b.extend({},b.tools.expose.conf);d=b.extend(f,d);this.each(function(){e=new c(b(this),d);b(this).data("expose",e)});return d.api?e:this}})(jQuery);
/*
 * jQuery selectbox plugin
 *
 * Copyright (c) 2007 Sadri Sahraoui (brainfault.com)
 * Licensed under the GPL license and MIT:
 *   http://www.opensource.org/licenses/GPL-license.php
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * The code is inspired from Autocomplete plugin (http://www.dyve.net/jquery/?autocomplete)
 *
 * Revision: $Id$
 * Version: 1.0
 * 
 * Changelog :
 *  Version 1.0
 *  - Support jQuery noConflict option
 *  - Add callback for onChange event, thanks to Jason
 *  - Fix IE8 support
 *  - Fix auto width support
 *  - Fix focus on firefox dont show the carret
 *  Version 0.6
 *  - Fix IE scrolling problem
 *  Version 0.5 
 *  - separate css style for current selected element and hover element which solve the highlight issue 
 *  Version 0.4
 *  - Fix width when the select is in a hidden div   @Pawel Maziarz
 *  - Add a unique id for generated li to avoid conflict with other selects and empty values @Pawel Maziarz
 */
jQuery.fn.extend({
	selectbox: function(options) {
		return this.each(function() {
			new jQuery.SelectBox(this, options);
		});
	}
});


/* pawel maziarz: work around for ie logging */
if (!window.console) {
	var console = {
		log: function(msg) { 
	 }
	}
}
/* */

jQuery.SelectBox = function(selectobj, options) {
	
	var opt = options || {};
	opt.inputClass = opt.inputClass || "selectbox";
	opt.containerClass = opt.containerClass || "selectbox-wrapper";
	opt.hoverClass = opt.hoverClass || "current";
	opt.currentClass = opt.currentClass || "selected";
    opt.onChangeCallback = opt.onChangeCallback || false;
    opt.onChangeParams = opt.onChangeParams || false;
	opt.debug = opt.debug || false;
	
	var elm_id = selectobj.id;
	var active = 0;
	var inFocus = false;
	var hasfocus = 0;
	//jquery object for select element
	var $select = jQuery(selectobj);
	// jquery container object
	var $container = setupContainer(opt);
	//jquery input object 
	var $input = setupInput(opt);
	// hide select and append newly created elements
	$select.hide().before($input).before($container);
	
	
	init();
	
	$input
	.click(function(){
    if (!inFocus) {
		  $container.toggle();
		}
	})
	.focus(function(){
	   if ($container.not(':visible')) {
	       inFocus = true;
	       $container.show();
	   }
	})
	.keydown(function(event) {	   
		switch(event.keyCode) {
			case 38: // up
				event.preventDefault();
				moveSelect(-1);
				break;
			case 40: // down
				event.preventDefault();
				moveSelect(1);
				break;
			//case 9:  // tab 
			case 13: // return
				event.preventDefault(); // seems not working in mac !
				$('li.'+opt.hoverClass).trigger('click');
				break;
			case 27: //escape
			  hideMe();
			  break;
		}
	})
	.blur(function() {
		if ($container.is(':visible') && hasfocus > 0 ) {
			if(opt.debug) console.log('container visible and has focus')
		} else {
		  // Workaround for ie scroll - thanks to Bernd Matzner
            if((jQuery.browser.msie && jQuery.browser.version.substr(0,1) < 8) || jQuery.browser.safari){ // check for safari too - workaround for webkit
                if(document.activeElement.getAttribute('id').indexOf('_container')==-1){
                    hideMe();
                } else {
                    $input.focus();
                }
            } else {
                hideMe();
            }
		}
	});

	function hideMe() { 
		hasfocus = 0;
		$container.hide(); 
	}
	
	function init() {
		$container.append(getSelectOptions($input.attr('id'))).hide();
		var width = $input.css('width');
		$container.width(width);
    }
	
	function setupContainer(options) {
		var container = document.createElement("div");
		$container = jQuery(container);
		$container.attr('id', elm_id+'_container');
		$container.addClass(options.containerClass);
        $container.css('display', 'none');
		
		return $container;
	}
	
	function setupInput(options) {
		var input = document.createElement("input");
		var $input = jQuery(input);
		$input.attr("id", elm_id+"_input");
		$input.attr("type", "text");
		$input.addClass(options.inputClass);
		$input.attr("autocomplete", "off");
		$input.attr("readonly", "readonly");
		$input.attr("tabIndex", $select.attr("tabindex")); // "I" capital is important for ie
        $input.css("width", $select.css("width"));
		return $input;	
	}
	
	function moveSelect(step) {
		var lis = jQuery("li", $container);
		if (!lis || lis.length == 0) return false;
		active += step;
    //loop through list
		if (active < 0) {
			active = lis.size();
		} else if (active > lis.size()) {
			active = 0;
		}
        scroll(lis, active);
		lis.removeClass(opt.hoverClass);

		jQuery(lis[active]).addClass(opt.hoverClass);
	}
	
	function scroll(list, active) {
      var el = jQuery(list[active]).get(0);
      var list = $container.get(0);
      
      if (el.offsetTop + el.offsetHeight > list.scrollTop + list.clientHeight) {
        list.scrollTop = el.offsetTop + el.offsetHeight - list.clientHeight;      
      } else if(el.offsetTop < list.scrollTop) {
        list.scrollTop = el.offsetTop;
      }
	}
	
	function setCurrent() {	
		var li = jQuery("li."+opt.currentClass, $container).get(0);
		var ar = (''+li.id).split('_');
		var el = ar[ar.length-1];
		//$select.val(el);
        $select.get(0).selectedIndex = $('li', $container).index(li);
		$input.val($(li).html());
        opt.onChangeParams = { selectedVal : $select.val() };
        if (opt.onChangeCallback) opt.onChangeCallback(opt.onChangeParams);
		return true;
	}
	
	// select value
	function getCurrentSelected() {
		return $select.val();
	}
	
	// input value
	function getCurrentValue() {
		return $input.val();
	}
	
	function getSelectOptions(parentid) {
		var select_options = new Array();
		var ul = document.createElement('ul');
		$select.children('option').each(function() {
			var li = document.createElement('li');
			li.setAttribute('id', parentid + '_' + $(this).val());
			li.innerHTML = $(this).html();
			if ($(this).is(':selected')) {
				$input.val($(this).html());
				$(li).addClass(opt.currentClass);
			}
			ul.appendChild(li);
			$(li)
			.mouseover(function(event) {
				hasfocus = 1;
				if (opt.debug) console.log('over on : '+this.id);
				jQuery(event.target, $container).addClass(opt.hoverClass);
			})
			.mouseout(function(event) {
				hasfocus = -1;
				if (opt.debug) console.log('out on : '+this.id);
				jQuery(event.target, $container).removeClass(opt.hoverClass);
			})
			.click(function(event) {
			  var fl = $('li.'+opt.hoverClass, $container).get(0);
				if (opt.debug) console.log('click on :'+this.id);
				$('li.'+opt.currentClass, $container).removeClass(opt.currentClass); 
				$(this).addClass(opt.currentClass);
				setCurrent();
				//$select.change();
				$select.get(0).blur();
				hideMe();
			});
		});
		return ul;
	}
	
	
	
};
 
jQuery.fn.smartFocus = function(text) {
	
	$(this).addClass ("defaultState");
	
$(this).val(text).focus(function(){
if($(this).val() == text){
$(this).val('');
$(this).removeClass("defaultState");

}
}).blur(function(){
if( $(this).val() == '' ){
$(this).val(text);
$(this).addClass ("defaultState");
}
});
};/*
 * 	Character Count Plugin - jQuery plugin
 * 	Dynamic character count for text areas and input fields
 *	written by Alen Grakalic	
 *	http://cssglobe.com/
 *
 *	Copyright (c) 2009 Alen Grakalic (http://cssglobe.com)
 *	Dual licensed under the MIT (MIT-LICENSE.txt)
 *	and GPL (GPL-LICENSE.txt) licenses.
 *
 *	Built for jQuery library
 *	http://jquery.com
 *
 */
 
 /*
 *	Modified by pakeezah DAHOO to calculate the character count on blur and on focus due to static default grey text
 *
 */
 
(function($) {

	$.fn.charCount = function(options){
	  
		// default configuration properties
		var defaults = {	
			allowed: 140,		
			warning: 25,
			css: 'counter',
			counterElement: 'span',
			cssWarning: 'warning',
			cssExceeded: 'exceeded',
			counterText: ''
		}; 
			
		var options = $.extend(defaults, options); 
		
		function calculate(obj){
			var count = $(obj).val().length;
			var available = options.allowed - count;
			if(available <= options.warning && available >= 0){
				$(obj).next().addClass(options.cssWarning);
			} else {
				$(obj).next().removeClass(options.cssWarning);
			}
			if(available < 0){
				$(obj).next().addClass(options.cssExceeded);
			} else {
				$(obj).next().removeClass(options.cssExceeded);
			}
			$(obj).next().html(options.counterText + available);
		};
				
		this.each(function() {  			
			$(this).after('<'+ options.counterElement +' class="' + options.css + '">'+ options.counterText +'</'+ options.counterElement +'>');
			calculate(this);
			$(this).keyup(function(){calculate(this)});
			$(this).change(function(){calculate(this)});
			$(this).blur(function(){calculate(this)});
			$(this).focus(function(){calculate(this)});
		});
	  
	};

})(jQuery);
jQuery('document').ready(function() {                             
                        var cursorPosition=0;         

                        var MAXCHARS;                             
                      jQuery('#summary-dpr').keydown(function(e) {            
                              MAXCHARS = 1500;    
                              cursorStart = getCursorPosition(jQuery(this),'start',0);
                              cursorEnd = getCursorPosition(jQuery(this),'end',0);                  
                                          
                                    if(jQuery(this).val().length > (MAXCHARS - 1) && !(e.which >= 37 && e.which <= 46) && e.which != 8 && cursorStart == cursorEnd){                                      
                                          return false;     
                                    }                                                                                    
                        });
                                 
                      jQuery('#summary-dpr').bind('paste', function(e) {                            
                        var MAXCHARS = 1500;      
                              var txtTitle = jQuery(this);
                              var beforePasteText = txtTitle.val();     
                              cursorPosition = getCursorPosition(txtTitle,'start',0);                 
                        setTimeout(function() {
                           //Execute code after pasting
                            var afterPasteText = txtTitle.val();
                            if(afterPasteText.length > MAXCHARS){
                                          //pasted text greater than maximum, trim
                                          var diff = afterPasteText.length - MAXCHARS;
                                          newCursorPosition = getCursorPosition(txtTitle,'start',0);                                  
                                          txtTitle.val(afterPasteText.substring(0,newCursorPosition - diff) + afterPasteText.substr(newCursorPosition,MAXCHARS - (newCursorPosition - diff)));
                                          getCursorPosition(txtTitle,'startselect',newCursorPosition - diff);                                                                             
                                    }
                                                                
                        }, 10);
                         });  
                          
                           jQuery('.txtDescAnswer').keydown(function(e) {            
                              MAXCHARS = 1500;    
                              cursorStart = getCursorPosition(jQuery(this),'start',0);
                              cursorEnd = getCursorPosition(jQuery(this),'end',0);                  
                                          
                                    if(jQuery(this).val().length > (MAXCHARS - 1) && !(e.which >= 37 && e.which <= 46) && e.which != 8 && cursorStart == cursorEnd){                                      
                                          return false;     
                                    }                                                                                    
                        });
                                
                         jQuery('.txtDescAnswer').bind('paste', function(e) {                            
                        var MAXCHARS = 1500;      
                              var txtTitle = jQuery(this);
                              var beforePasteText = txtTitle.val();     
                              cursorPosition = getCursorPosition(txtTitle,'start',0);                 
                        setTimeout(function() {
                           //Execute code after pasting
                            var afterPasteText = txtTitle.val();
                            if(afterPasteText.length > MAXCHARS){
                                          //pasted text greater than maximum, trim
                                          var diff = afterPasteText.length - MAXCHARS;
                                          newCursorPosition = getCursorPosition(txtTitle,'start',0);                                  
                                          txtTitle.val(afterPasteText.substring(0,newCursorPosition - diff) + afterPasteText.substr(newCursorPosition,MAXCHARS - (newCursorPosition - diff)));
                                          getCursorPosition(txtTitle,'startselect',newCursorPosition - diff);                                                                             
                                    }
                                                                
                        }, 10);
                         });   

                        function getCursorPosition(element,mode,start){
                              
                                    if( document.selection ){                 
                                          // The current selection                  
                                          var range = document.selection.createRange();                  
                                          var stored_range = range.duplicate();                             
                                          // Select all text            
                                                                    
                                          stored_range.moveToElementText(element.get(0));
                                          // Now move end point to end point of original range                               
                                          stored_range.setEndPoint( 'EndToEnd', range );  
                                          // Now we can calculate start and end points                                  
                                          var selectionStart = stored_range.text.length - range.text.length;      
                                          var selectionEnd = selectionStart + range.text.length;      

                                          switch(mode){

                                          case 'start':
                                                return selectionStart;
                                                break;
                                          case 'end':
                                                return selectionEnd;
                                                break;
                                          case 'startselect':
                                                stored_range.move('character',start);
                                                stored_range.select();
                                                break;      
                                    }             

                                                                                                            
                              }                 
                          else{           
                              //Mozilla         
                              
                              switch(mode){

                                    case 'start':
                                          return element.attr('selectionStart');
                                          break;
                                    case 'end':
                                          return element.attr('selectionEnd');
                                          break;
                                    case 'startselect':                                         
                                          element.attr('selectionStart',start);                 
                                          element.attr('selectionEnd',start);     
                                          break;      
                              }                                         
                          }                
                        }                        
                  })
                  

;
/*
 * author: ibasset
 * 
 * JS used to load randomly company logos on FP
 * IMPORTANT NOTES:
 * - all logos must be placed in /static/webimages/frontpage
 * - if a new subpanel is to be added, add a new <div id="subpanel7"></div> in frontpage.jsp, and its img tag with a new id - continue the sequence
 * - add the image name to arrImages
 */
var loadFPlogos = new function(){
	
	var IMAGE_PATH = "/static/webimages/frontpage/";
	
	return {
		randomOrder:function (){
			return (Math.round(Math.random())-0.5);
		} ,
		
		load:function(){
		
			arrImages = new Array('e-commerce-new-1.gif','e-commerce-new-4.gif','e-commerce-24h00.gif',
				'e-commerce-pixmania.gif','e-commerce-new-2.gif','e-commerce-new-5.gif',
				'e-commerce-new-3.gif',	'e-commerce-coolcadeau.gif','e-commerce-maison-facile.gif','e-commerce-mistersport.gif',
				'e-commerce-mobilistore.gif','e-commerce-modanoo.gif','e-commerce-philips.gif','e-commerce-discounteo.gif',
				'e-commerce-auchan.png','e-commerce-babyBidou.png','e-commerce-carrefour.png','e-commerce-chezCuisine.png',
				'e-commerce-CsiBio.png','e-commerce-decovante.png','e-commerce-dogsize.png','e-commerce-edelices.png','e-commerce-editionAtlas.png',
				'e-commerce-ideesMaman.png','e-commerce-jardinSophie.png','e-commerce-kookit.png','e-commerce-laFourchette.png',
				'e-commerce-lafuma.png','e-commerce-lookVoyages.png','e-commerce-maCaveVin.png','e-commerce-matelsom.png','e-commerce-motoBlouz.png',
				'e-commerce-oclio.png','e-commerce-pecheur.png','e-commerce-shirteo.png','e-commerce-showroomPrive.png','e-commerce-surInvitaion.png',
				'e-commerce-usineDesign.png','e-commerce-VsLingerie.png');
			arrImages.sort( loadFPlogos.randomOrder );

			for (var j=0;j<arrImages.length;j++){
				document.getElementById('logo'+(j+1)).src=IMAGE_PATH+arrImages[j];
			}
				
		}		

	}

}
$("document").ready(function () { 
	
//	$("#description").charCount({
//    allowed: 140,		
//    warning: 20,
//    counterText: ' charact\u00E8res',
//    css: 'counterDescription'
//	});

	//DEFAULT GREY TEXT
	$('#mailregister').smartFocus(EU_TEXT.FRONTPAGE_TEMPLATE_EMAIL);
	$('#userregister').smartFocus(EU_TEXT.FRONTPAGE_TEMPLATE_EMAIL);
	$('#txtEmailPublic').smartFocus(EU_TEXT.FRONTPAGE_TEMPLATE_EMAIL);	
	$('#headerSearch').smartFocus(EU_TEXT.HOMEPAGE_SEARCH);
	$('#txtEmailPrestataire').smartFocus(EU_TEXT.FRONTPAGE_TEMPLATE_EMAIL);
	$('#urlSiteGroupe').smartFocus(EU_TEXT.SOCIETE_GROUPE_EXEMPLE);
	$('#urlSite').smartFocus(EU_TEXT.FEEDBACK_EXEMPLE);
	$('#reference').smartFocus(EU_TEXT.SOCIETE_REFERENCE_EXEMPLE);
	$('.txtDescAnswer').smartFocus(EU_TEXT.REPONDRE_PUBLIQUEMENT);
	$('#ajoutercontacts').smartFocus(EU_TEXT.AJOUTERCONTACTS_EXEMPLE);
	$('#txtHeaderSearch').smartFocus(EU_TEXT.HOMEPAGE_SEARCH);
	$('#txtDealHeaderSearch').smartFocus(EU_TEXT.HOMEPAGE_SEARCH);
				
	$('.star').rating({
		callback: function(value, link){
			if (null == document.getElementById('ratingValue'))
				$('input[class=ratingValue]').val(value);
			else
				document.getElementById('ratingValue').value=value;
			
		}
	});	
	
	// V2 - MASQUER UNE NOUVELLE
	$("IMG.supprimer").click(function () { 
		id_table = $(this).parents("table").attr("id");
//		if (confirm(EU_TEXT.NEWS_COMMENTAIRE)){
		  	$("TABLE#"+id_table).fadeOut('fast', function() {
		    	// FONCTION AJAX A APPELER POUR SUPPRIMER CETTE NOUVELLE
		    	
		    		eunews.deleteNewsPushed(id_table);
		    	
		  	});
//		}
	});
	
	$("DIV#optionDeDiffusion").click(function () { 
		if(document.getElementById('tablenouvelle').style.display == 'none'){
			document.getElementById('tablenouvelle').style.display = 'block';
			document.getElementById('zoneCurseur').style.height ="312px";
		}else{
			document.getElementById('tablenouvelle').style.display = 'none';
			document.getElementById('zoneCurseur').style.height ="200px";
		}
	});
	
	// ONGLETS DIFFUSER NOUVELLES OU PROPOSER PARTENARIAT
	$("A#proposerpartenariat").click(function () { 
		$(this).addClass("actif");
		$("#zoneCurseur").css("background-position","75px 5px");	
		$('#capsule02').css("display","none");
		$('#capsule01').css("display","block");
		$("A#diffusernouvelle").removeClass("actif");
		$("DIV#zonetextarea").removeClass("onglet2");	
		$("DIV#zonetextarea").addClass("onglet1");	
		$("DIV#mainLeft1").removeClass("onglet2");	
		$("DIV#mainLeft1").addClass("onglet1");	
		$("DIV#zonePublication").css("display","none");	
		$("DIV#zonePartenariat").fadeIn("slow");
		
		//added by me
		document.getElementById('caseDispatch').value='addDeal';
		$('SELECT#confidentialitePartenariat').value=0;	
		$("TH#infoConfidentiel").html(EU_TEXT.HP_DEAL_PUBLIC);
	});
	$("A#diffusernouvelle").click(function () { 
		$(this).addClass("actif");
		$("#zoneCurseur").css("background-position","250px 5px");	
		$('#capsule01').css("display","none");
		$('#capsule02').css("display","block");
		$("A#proposerpartenariat").removeClass("actif");
		$("DIV#zonetextarea").removeClass("onglet1");	
		$("DIV#zonetextarea").addClass("onglet2");	
		$("DIV#mainLeft1").removeClass("onglet1");	
		$("DIV#mainLeft1").addClass("onglet2");	
		$("DIV#zonePartenariat").css("display","none");	
		$("DIV#zonePublication").fadeIn("slow");
		
		//added by me
		document.getElementById('caseDispatch').value='addNews';
		$('SELECT#confidentialitePublication').value=0;	
		$("TH#infoConfidentiel").html(EU_TEXT.HP_NEWS_PUBLIC);
	});

		// SELECTBOXES
		$('SELECT#confidentialitePublication').selectbox({
        onChangeCallback: myFunction
    });
		$('SELECT#confidentialitePartenariat').selectbox({
        onChangeCallback: myFunction
    });
    
    $('SELECT#typePartenariat').selectbox();
    
    
		$('SELECT#typeSearch').selectbox();
		
		$('SELECT#companyreference').selectbox();
		
		function myFunction(args) {
			myEtat = parseInt(args.selectedVal);
			dispatch = document.getElementById('caseDispatch').value;
			if (myEtat==2) {
				if (dispatch=='addNews')
					$("TH#infoConfidentiel").html(EU_TEXT.HP_NEWS_CONFIDENTIELLE);
				else
					$("TH#infoConfidentiel").html(EU_TEXT.HP_DEAL_CONFIDENTIELLE);
			} else if (myEtat==0) {
				if (dispatch=='addNews')
					$("TH#infoConfidentiel").html(EU_TEXT.HP_NEWS_PUBLIC);
				else
					$("TH#infoConfidentiel").html(EU_TEXT.HP_DEAL_PUBLIC);
			} else {
					$("TH#infoConfidentiel").html(EU_TEXT.HP_DEAL_INTERNE);
			}
    }		

	

		// MENU DEROULANT AIDE
	$("A#aide").mouseover(function () { 
		$("UL#aideMenu").slideDown("fast");
	});
	$("UL#aideMenu").mouseleave(function () { 
		$("UL#aideMenu").slideUp("fast");
	});


	// COMMENTAIRE
	$("INPUT.commentaire").mouseover(function () { 
		$(this).css("background-image","url(/static/webimages/homepage/textbox-on.gif)");
	
	});
	$("INPUT.commentaire").mouseleave(function () { 
		$(this).css("background-image","url(/static/webimages/homepage/textbox.gif)");
		
	});
	$("INPUT.commentaire").focus(function () { 
		element = $(this).attr("id");
		$("#OK_"+element).fadeIn("fast");
		if ($("INPUT.commentaire").attr("value")=="commenter") $("INPUT.commentaire").attr("value","");
	
	});
	
		// MENU DEROULANT CONNEXION
	$("A#connexion").click(function () { 
		$("TABLE#connexionMenu").slideDown("fast");
	});
	$("A#connexionBouton").click(function () { 
		$("TABLE#connexionMenuBouton").slideDown("fast");
	});
	$("IMG#closeLogin").click(function () { 
		$("TABLE#connexionMenu").slideUp("fast");
	});
	$("IMG#closeLoginButton").click(function () { 
		$("TABLE#connexionMenuBouton").slideUp("fast");
	});
	
	
	//ONMOUSEOVER LOGO COMPANY VERIFIED
	$("IMG#verifiedCompanyMessage").mouseover(function () { 
		$("UL#profilCompany").slideDown("fast");
	});
	$("IMG#verifiedCompanyMessage").mouseleave(function () { 
		$("UL#profilCompany").slideUp("fast");
	});
	

	
	// HOME
	$("#flowpanes").scrollable({size: 1,keyboard: false}).circular().navigator({});
	$("#flowmembres").scrollable({size: 1,keyboard: false}).circular().navigator({});
	$("BUTTON.next").click(function () {
 	});


	
	// ONGLETS PROFIL
	$("A#profilonglet1Complet").click(function () { 
		$(this).addClass("actif");
		$("#zoneCurseur").css("background-image","url(../image/fleche-haut.gif)");	
		$("#zoneCurseur").css("background-position","75px 5px");	
		$("A#profilonglet2Complet").removeClass("actif");
		$("A#profilonglet3Complet").removeClass("actif");
		$("DIV#zoneProfil2").css("display","none");	
		$("DIV#zoneProfil3").css("display","none");	
		$("DIV#mainLeft1").removeClass("otheronglet2");	
		$("DIV#mainLeft1").removeClass("otheronglet3");	
		$("DIV#mainLeft1").addClass("otheronglet1");	
		$("DIV#zoneProfil1").fadeIn("slow");	
	});
	$("A#profilonglet2Complet").click(function () { 
		$(this).addClass("actif");
		$("#zoneCurseur").css("background-image","none");	
		$("A#profilonglet1Complet").removeClass("actif");
		$("A#profilonglet3Complet").removeClass("actif");
		$("DIV#zoneProfil1").css("display","none");	
		$("DIV#zoneProfil3").css("display","none");	
		$("DIV#mainLeft1").removeClass("otheronglet1");	
		$("DIV#mainLeft1").removeClass("otheronglet3");	
		$("DIV#mainLeft1").addClass("otheronglet2");	
		$("DIV#zoneProfil2").fadeIn("slow");	
	});
	
	$("A#profilonglet2CompletRating").click(function () { 
		$(this).addClass("actif");
		$("#zoneCurseur").css("background-image","none");	
		$("A#profilonglet1Complet").removeClass("actif");
		$("A#profilonglet3Complet").removeClass("actif");
		$("DIV#zoneProfil1").css("display","none");	
		$("DIV#zoneProfil3").css("display","none");	
		$("DIV#mainLeft1").removeClass("otheronglet1");	
		$("DIV#mainLeft1").removeClass("otheronglet3");	
		$("DIV#mainLeft1").addClass("otheronglet2");	
		$("DIV#zoneProfil2").fadeIn("slow");	
	});
	$("A#profilonglet2CompletLink").click(function () { 
		$("#zoneCurseur").css("background-image","none");	
		$("A#profilonglet1Complet").removeClass("actif");
		$("A#profilonglet3Complet").removeClass("actif");
		$("DIV#zoneProfil1").css("display","none");	
		$("DIV#zoneProfil3").css("display","none");	
		$("DIV#mainLeft1").removeClass("otheronglet1");	
		$("DIV#mainLeft1").removeClass("otheronglet3");	
		$("DIV#mainLeft1").addClass("otheronglet2");	
		$("DIV#zoneProfil2").fadeIn("slow");	
	});
	$("A#profilonglet3Complet").click(function () { 
		$(this).addClass("actif");
		$("#zoneCurseur").css("background-image","none");	
		$("A#profilonglet1Complet").removeClass("actif");
		$("A#profilonglet2Complet").removeClass("actif");
		$("DIV#zoneProfil1").css("display","none");	
		$("DIV#zoneProfil2").css("display","none");	
		$("DIV#mainLeft1").removeClass("otheronglet1");	
		$("DIV#mainLeft1").removeClass("otheronglet2");	
		$("DIV#mainLeft1").addClass("otheronglet3");	
		$("DIV#zoneProfil3").fadeIn("slow");	
	});
	$("A#profilonglet1Simple").click(function () { 
		$(this).addClass("actif");
		$("#zoneCurseur").css("background-image","url(../image/fleche-haut.gif)");	
		$("#zoneCurseur").css("background-position","75px 5px");	
		$("A#profilonglet2Simple").removeClass("actif");
		$("A#profilonglet3Simple").removeClass("actif");
		$("DIV#zoneProfil2").css("display","none");	
		$("DIV#zoneProfil3").css("display","none");	
		$("DIV#mainLeft1").removeClass("otheronglet2Simple");	
		$("DIV#mainLeft1").removeClass("otheronglet3");	
		$("DIV#mainLeft1").addClass("otheronglet1");	
		$("DIV#zoneProfil1").fadeIn("slow");	
	});
	$("A#profilonglet2Simple").click(function () { 
		$(this).addClass("actif");
		$("#zoneCurseur").css("background-image","none");	
		$("A#profilonglet1Simple").removeClass("actif");
		$("A#profilonglet3Simple").removeClass("actif");
		$("DIV#zoneProfil1").css("display","none");	
		$("DIV#zoneProfil3").css("display","none");	
		$("DIV#mainLeft1").removeClass("otheronglet1");	
		$("DIV#mainLeft1").removeClass("otheronglet3");	
		$("DIV#mainLeft1").addClass("otheronglet2Simple");	
		$("DIV#zoneProfil2").fadeIn("slow");	
	});
	$("A#profilonglet2SimpleRating").click(function () { 
		$(this).addClass("actif");
		$("#zoneCurseur").css("background-image","none");	
		$("A#profilonglet1Simple").removeClass("actif");
		$("A#profilonglet3Simple").removeClass("actif");
		$("DIV#zoneProfil1").css("display","none");	
		$("DIV#zoneProfil3").css("display","none");	
		$("DIV#mainLeft1").removeClass("otheronglet1");	
		$("DIV#mainLeft1").removeClass("otheronglet3");	
		$("DIV#mainLeft1").addClass("otheronglet2Simple");	
		$("DIV#zoneProfil2").fadeIn("slow");	
	});
	$("A#profilonglet2SimpleLink").click(function () { 
		$("#zoneCurseur").css("background-image","none");	
		$("A#profilonglet1Simple").removeClass("actif");
		$("A#profilonglet3Simple").removeClass("actif");
		$("DIV#zoneProfil1").css("display","none");	
		$("DIV#zoneProfil3").css("display","none");	
		$("DIV#mainLeft1").removeClass("otheronglet1");	
		$("DIV#mainLeft1").removeClass("otheronglet3");	
		$("DIV#mainLeft1").addClass("otheronglet2Simple");	
		$("DIV#zoneProfil2").fadeIn("slow");	
	});
	
	// COMPTE (TABS) - NOT USED, CAUSING ERROR WHEN CHANGE TAB
	$(function() { 
    // setup ul.tabs to work as tabs for each div directly under div.panes 
    $("ul#supporters").tabs("div.panes > div"); 
	});

		
		
		       // MENU DEROULANT
   $("#header").mouseover(function () {
   	  // $("UL#memberMenu").slideUp("fast");   	   
     //  $("UL#annonceMenu").slideUp("fast");
       $("UL#actualiteMenu").slideUp("fast");
        $("UL#companyMenu").slideUp("fast");
   });
   $("A#member").mouseover(function () {
     //  $("UL#annonceMenu").slideUp("fast");
       $("UL#actualiteMenu").slideUp("fast");
       $("UL#companyMenu").slideUp("fast");
      // $("UL#memberMenu").slideDown("fast");
   });
   $("A#annonce").mouseover(function () {
    //   $("UL#memberMenu").slideUp("fast");
       $("UL#actualiteMenu").slideUp("fast"); 
       $("UL#companyMenu").slideUp("fast");     
      // $("UL#annonceMenu").slideDown("fast");
   });
   $("A#actualite").mouseover(function () {
     //  $("UL#memberMenu").slideUp("fast");      
     //  $("UL#annonceMenu").slideUp("fast");
       $("UL#companyMenu").slideUp("fast");
       $("UL#actualiteMenu").slideDown("fast");
   });
    $("A#company").mouseover(function () {
      // $("UL#memberMenu").slideUp("fast");      
      // $("UL#annonceMenu").slideUp("fast");
       $("UL#actualiteMenu").slideUp("fast");       
       $("UL#companyMenu").slideDown("fast");
   });
   
 /*  $("UL#memberMenu").mouseleave(function () {
       $("UL#memberMenu").slideUp("fast");
   }); 
   $("UL#annonceMenu").mouseleave(function () {
       $("UL#annonceMenu").slideUp("fast");
   });*/
   $("UL#actualiteMenu").mouseleave(function () {
       $("UL#actualiteMenu").slideUp("fast");
   });
   $("A#company").mouseover(function () { 
		$("UL#companyMenu").slideDown("fast");
	});
	
	$("A#stats").mouseover(function () { 
		$("UL#companyMenu").slideUp("fast");
	});
	

	$("A#messages").mouseover(function () { 
		$("UL#companyMenu").slideUp("fast");
	});
	
	$("UL#companyMenu").mouseleave(function () { 
		$("UL#companyMenu").slideUp("fast");
	});
   
   
   //REGISTRATION TOOLTIP
   $(".registrationFields").focus(function(){
   	 elementId = $(this).attr("id");
   	 $("#"+elementId+'Tip').fadeIn("fast");
   	
   });

   
   $(".registrationFields").blur(function(){
   	 elementId = $(this).attr("id");
   	 $("#"+elementId+'Tip').fadeOut("fast");
   	
   });
   
   
   
   //CHANGE CSS FOR WORD WRAP - in NEWS TAG & COMPANY TAG
   changeWordWrap('wordwrap'); //method in file ecomutd.js

})
;




function toggleCheckBox(isChkAll,frm_obj,checkboxname) {
	//alert(isChkAll);	
	for (var i=0;i<frm_obj.elements.length;i++) {
		var e = frm_obj.elements[i];		  
		var index;
		var allselected = checkboxname;
		
		if(!checkboxname.match('all')){
			allselected = 'all'+checkboxname;
		}
		
		if(e.name==allselected) {
			index = i;	
			checkboxname = (e.name).replace('all', '');
		}			
	
		if(!isChkAll){ 
			if (e.type=='checkbox' && e.name==checkboxname) {
				frm_obj.elements[index].checked	= true;
				if (!e.checked) {
			    	frm_obj.elements[index].checked	= false;
			    	break;	              	             	
			   	}	              
			}
		} else {				
			if ((e.name != 'allbox') && (e.type=='checkbox')&&(e.name==checkboxname)) {
				e.checked = frm_obj.elements[index].checked;
			}	
		}
	}	
}

function showPopUp(id){
	document.getElementById('text'+id).style.display='';
	var a = document.getElementById('launchCharte'+id);
	var t = a.title || a.name || null;
	var l = a.href || a.alt;
	var g = a.rel || false;
	tb_show(t,l,g);
	a.focus();
}
		
function checkMinOne(checkBoxName,errorAlertMsg){

var numUnchecked=0;
var checkedBoxCollection=document.getElementsByName(checkBoxName);	
	for(var i=0;i<checkedBoxCollection.length;i++){		
		if(!checkedBoxCollection[i].checked ){			
			numUnchecked = numUnchecked+1;	
						
		}
	}	
	
	if(numUnchecked == checkedBoxCollection.length){
		alert(errorAlertMsg);
		return false;	
	}
	return true;
}

function checkOnlyOne(checkBoxName,errorAlertMsg){

var numUnchecked=0;
var checkedBoxCollection=document.getElementsByName(checkBoxName);	
	for(var i=0;i<checkedBoxCollection.length;i++){		
		if(checkedBoxCollection[i].checked ){			
			numUnchecked = numUnchecked+1;				
		}
	}	
	if(numUnchecked > 1){
		alert(errorAlertMsg);
		return false;	
	}
	return true;
}

function isOneChecked(checkBoxName,dispatch,errorAlertMsg,confirmAlertMsg){
   
	var numUnchecked=0;
	var checkedBoxCollection=document.getElementsByName(checkBoxName);			
		
	for(var i=0;i<checkedBoxCollection.length;i++){		
		if(!checkedBoxCollection[i].checked ){			
			numUnchecked = numUnchecked+1;				
		}
	}	
	if(numUnchecked == checkedBoxCollection.length){
		alert(errorAlertMsg);	
	}
	else{		
		if (confirm(confirmAlertMsg)) {
			document.forms[0].dispatch.value=dispatch;
			return true;
		}	
		return false;
	}
	return (numUnchecked != checkedBoxCollection.length);	   
	   	
}

function setContentHeight(height){	
	
	document.getElementById('content').style.height=height+'px';
	document.getElementById('maincontentbody').style.height=height+'px';
	document.getElementById('leftmenu').style.height=height+'px';
	//document.getElementById('rightmenu').style.height=height+'px';
	
}

function trim(stringtotrim){
	return stringtotrim.replace(/^\s+|\s+$/g,'');
}



String.prototype.endsWith = function(str){
	return (this.match(str+"$")==str);
}

// delete table rows with index greater then 0
	function deleteRows(tableId){
		var tbl = document.getElementById(tableId); // table reference
		// set the last row index
		var lastRow = tbl.rows.length -1;
		// delete rows with index greater then 0
		for (var i=lastRow; i>0; i--) tbl.deleteRow(i);
	}
	
	function showHidePlusMinus(secteurId){
		
		if (secteurId!=null){
				if (document.getElementById('show'+secteurId).style.display==''){					
					document.getElementById('show'+secteurId).style.display='none';
					document.getElementById('iconshowhide'+secteurId).innerHTML='+';
				}else {
					document.getElementById('show'+secteurId).style.display='';					
					document.getElementById('iconshowhide'+secteurId).innerHTML='-';
				}
			}
	}
			
	function checkUncheckAll(secteurId) {
		var lowerIndex = secteurId *100 + 1;
		var upperIndex = lowerIndex + 99;
		var check = document.getElementById(secteurId).checked ;
		// Unselect all sousSecteur between lowerIndex and UpperIndex
		for (var i=lowerIndex;i<upperIndex;i++) {
			if (document.getElementById(i) != null){
				document.getElementById(i).checked = check;
			}
		}
	}	
	
	function selectSecteur(sousSecteurId){
		var secteurId = parseInt(sousSecteurId / 100);
		if (document.getElementById(secteurId).checked == false){
			document.getElementById(secteurId).checked = true;
		}
	}
	
	//convert from plain text to javascript text (i.e. convert all break lines with \n )
function getSource(textToConvert){
	var fromAr = new Array(/\\/g,/'/g,/"/g,/\r\n/g,/[\r\n]/g,/\t/g,new RegExp('--'+'>','g'),new RegExp('<!'+'--','g'),/\//g), toAr = new Array('\\\\','\\\'','\\\"','\\n','\\n','\\t','--\'+\'>','<!\'+\'--','\\\/');
	for( var x = 0; x < fromAr.length; x++ ) {
		textToConvert = textToConvert.replace(fromAr[x],toAr[x]);
	}
	return textToConvert;	
}


function convertJSTxtToHTML(textToConvert){
			
			return textToConvert.replace(/(\r\n|[\r\n])/g, "<br/>")
			
		}
		
function convertHTMLToJSTxt(textToConvert){
	
	return textToConvert.ReplaceAll("<br/>", "\n");
	
}

function setMaxLengthTextArea(obj,maxLength){
	  if (obj.getAttribute && obj.value.length>maxLength)
	      obj.value=obj.value.substring(0,maxLength)
}

String.prototype.ReplaceAll = function(stringToFind,stringToReplace){

    var temp = this;

    var index = temp.indexOf(stringToFind);

        while(index != -1){

            temp = temp.replace(stringToFind,stringToReplace);

            index = temp.indexOf(stringToFind);

        }

        return temp;

    }
    ;
    
     function getElementsByClassName(classname, node) {

	      if(!node) node = document.getElementsByTagName("body")[0];
	
	      var a = [];
	
	      var re = new RegExp('\\b' + classname + '\\b');
	
	      var els = node.getElementsByTagName("*");
	
	      for(var i=0,j=els.length; i<j; i++)
	
	      if(re.test(els[i].className))a.push(els[i]);
	
	      return a;

      }
      
function changeWordWrap(classname){
   var isIEOrChrome=navigator.userAgent.toLowerCase().indexOf('msie') > -1 || navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
   var elements = getElementsByClassName(classname,null);
   var canBreak=false;
   for (var i=0;i<elements.length;i++){
   		var elementHTML = trim(elements[i].innerHTML);
   		
   		//check if there is a too long word
   		var words = elementHTML.split(/\s/);
   		var j=0;
   		while (j < words.length){
   			if (words[j].length > 50){
   				canBreak=true;
   				break;
   			}
   			++j;
   			
   		}
   		if (elementHTML.indexOf(" ")==-1 || canBreak){
   			isIEOrChrome?elements[i].style.wordBreak="break-all":elements[i].style.wordWrap="break-word";
   		}else{
   			isIEOrChrome?elements[i].style.wordBreak="normal":elements[i].style.wordWrap="normal";
   		}
   }
}

function translateMonthToFrench(engdate){
	var frenchdate=engdate;
	
	frenchdate = frenchdate.ReplaceAll(JS_MONTH_ENG.JANUARY,JS_MONTH_FR.JANUARY);
	frenchdate = frenchdate.ReplaceAll(JS_MONTH_ENG.FEBRUARY,JS_MONTH_FR.FEBRUARY);
	frenchdate = frenchdate.ReplaceAll(JS_MONTH_ENG.MARCH,JS_MONTH_FR.MARCH);
	frenchdate = frenchdate.ReplaceAll(JS_MONTH_ENG.APRIL,JS_MONTH_FR.APRIL);
	frenchdate = frenchdate.ReplaceAll(JS_MONTH_ENG.MAY,JS_MONTH_FR.MAY);
	frenchdate = frenchdate.ReplaceAll(JS_MONTH_ENG.JUNE,JS_MONTH_FR.JUNE);
	frenchdate = frenchdate.ReplaceAll(JS_MONTH_ENG.JULY,JS_MONTH_FR.JULY);
	frenchdate = frenchdate.ReplaceAll(JS_MONTH_ENG.AUGUST,JS_MONTH_FR.AUGUST);
	frenchdate = frenchdate.ReplaceAll(JS_MONTH_ENG.SEPTEMBER,JS_MONTH_FR.SEPTEMBER);
	frenchdate = frenchdate.ReplaceAll(JS_MONTH_ENG.OCTOBER,JS_MONTH_FR.OCTOBER);
	frenchdate = frenchdate.ReplaceAll(JS_MONTH_ENG.NOVEMBER,JS_MONTH_FR.NOVEMBER);
	frenchdate = frenchdate.ReplaceAll(JS_MONTH_ENG.DECEMBER,JS_MONTH_FR.DECEMBER);
	
	return frenchdate;

}

function getRandomNumber(max){
	var floor = parseInt(max)+1;
	var idToDisplay  =  Math.ceil(Math.floor(floor*Math.random()));
	if (idToDisplay <1 || idToDisplay>floor) idToDisplay=1;
	return idToDisplay;
}

/* 
 * DISPLAY RANDOMLY ROWS OF A TABLE
 */
function randomizeContent(classname){
	var contents=randomizeContent.collectElementbyClass(classname)
	contents.text.sort(function() {return 0.5 - Math.random();})
	var tbodyref=contents.ref[0].tagName=="TR"? contents.ref[0].parentNode : new Object()
	for (var i=0; i<contents.ref.length; i++){
		if (tbodyref.moveRow) //if IE
			tbodyref.moveRow(0, Math.round(Math.random()*(tbodyref.rows.length-1)))
		else
			contents.ref[i].innerHTML=contents.text[i]
		contents.ref[i].style.visibility="visible"
	}
}

randomizeContent.collectElementbyClass=function(classname){ //return two arrays containing elements with specified classname, plus their innerHTML content
	var classnameRE=new RegExp("(^|\\s+)"+classname+"($|\\s+)", "i") //regular expression to screen for classname within element
	var contentobj=new Object()
	contentobj.ref=new Array() //array containing references to the participating contents
	contentobj.text=new Array() //array containing participating contents' contents (innerHTML property)
	var alltags=document.all? document.all : document.getElementsByTagName("*")
	for (var i=0; i<alltags.length; i++){
		if (typeof alltags[i].className=="string" && alltags[i].className.search(classnameRE)!=-1){
			contentobj.ref[contentobj.ref.length]=alltags[i]
			contentobj.text[contentobj.text.length]=alltags[i].innerHTML
		}
	}
	return contentobj
}
    /*
 * Thickbox 3 - One Box To Rule Them All.
 * By Cody Lindley (http://www.codylindley.com)
 * Copyright (c) 2007 cody lindley
 * Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php
*/

var tb_pathToImage = "static/webimages/loadingAnimation.gif";

eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('$(o).2S(9(){1u(\'a.18, 3n.18, 3i.18\');1w=1p 1t();1w.L=2H});9 1u(b){$(b).s(9(){6 t=X.Q||X.1v||M;6 a=X.u||X.23;6 g=X.1N||P;19(t,a,g);X.2E();H P})}9 19(d,f,g){3m{3(2t o.v.J.2i==="2g"){$("v","11").r({A:"28%",z:"28%"});$("11").r("22","2Z");3(o.1Y("1F")===M){$("v").q("<U 5=\'1F\'></U><4 5=\'B\'></4><4 5=\'8\'></4>");$("#B").s(G)}}n{3(o.1Y("B")===M){$("v").q("<4 5=\'B\'></4><4 5=\'8\'></4>");$("#B").s(G)}}3(1K()){$("#B").1J("2B")}n{$("#B").1J("2z")}3(d===M){d=""}$("v").q("<4 5=\'K\'><1I L=\'"+1w.L+"\' /></4>");$(\'#K\').2y();6 h;3(f.O("?")!==-1){h=f.3l(0,f.O("?"))}n{h=f}6 i=/\\.2s$|\\.2q$|\\.2m$|\\.2l$|\\.2k$/;6 j=h.1C().2h(i);3(j==\'.2s\'||j==\'.2q\'||j==\'.2m\'||j==\'.2l\'||j==\'.2k\'){1D="";1G="";14="";1z="";1x="";R="";1n="";1r=P;3(g){E=$("a[@1N="+g+"]").36();25(D=0;((D<E.1c)&&(R===""));D++){6 k=E[D].u.1C().2h(i);3(!(E[D].u==f)){3(1r){1z=E[D].Q;1x=E[D].u;R="<1e 5=\'1X\'>&1d;&1d;<a u=\'#\'>2T &2R;</a></1e>"}n{1D=E[D].Q;1G=E[D].u;14="<1e 5=\'1U\'>&1d;&1d;<a u=\'#\'>&2O; 2N</a></1e>"}}n{1r=1b;1n="1t "+(D+1)+" 2L "+(E.1c)}}}S=1p 1t();S.1g=9(){S.1g=M;6 a=2x();6 x=a[0]-1M;6 y=a[1]-1M;6 b=S.z;6 c=S.A;3(b>x){c=c*(x/b);b=x;3(c>y){b=b*(y/c);c=y}}n 3(c>y){b=b*(y/c);c=y;3(b>x){c=c*(x/b);b=x}}13=b+30;1a=c+2G;$("#8").q("<a u=\'\' 5=\'1L\' Q=\'1o\'><1I 5=\'2F\' L=\'"+f+"\' z=\'"+b+"\' A=\'"+c+"\' 23=\'"+d+"\'/></a>"+"<4 5=\'2D\'>"+d+"<4 5=\'2C\'>"+1n+14+R+"</4></4><4 5=\'2A\'><a u=\'#\' 5=\'Z\' Q=\'1o\'>1l</a> 1k 1j 1s</4>");$("#Z").s(G);3(!(14==="")){9 12(){3($(o).N("s",12)){$(o).N("s",12)}$("#8").C();$("v").q("<4 5=\'8\'></4>");19(1D,1G,g);H P}$("#1U").s(12)}3(!(R==="")){9 1i(){$("#8").C();$("v").q("<4 5=\'8\'></4>");19(1z,1x,g);H P}$("#1X").s(1i)}o.1h=9(e){3(e==M){I=2w.2v}n{I=e.2u}3(I==27){G()}n 3(I==3k){3(!(R=="")){o.1h="";1i()}}n 3(I==3j){3(!(14=="")){o.1h="";12()}}};16();$("#K").C();$("#1L").s(G);$("#8").r({Y:"T"})};S.L=f}n{6 l=f.2r(/^[^\\?]+\\??/,\'\');6 m=2p(l);13=(m[\'z\']*1)+30||3h;1a=(m[\'A\']*1)+3g||3f;W=13-30;V=1a-3e;3(f.O(\'2j\')!=-1){1E=f.1B(\'3d\');$("#15").C();3(m[\'1A\']!="1b"){$("#8").q("<4 5=\'2f\'><4 5=\'1H\'>"+d+"</4><4 5=\'2e\'><a u=\'#\' 5=\'Z\' Q=\'1o\'>1l</a> 1k 1j 1s</4></4><U 1W=\'0\' 2d=\'0\' L=\'"+1E[0]+"\' 5=\'15\' 1v=\'15"+1f.2c(1f.1y()*2b)+"\' 1g=\'1m()\' J=\'z:"+(W+29)+"p;A:"+(V+17)+"p;\' > </U>")}n{$("#B").N();$("#8").q("<U 1W=\'0\' 2d=\'0\' L=\'"+1E[0]+"\' 5=\'15\' 1v=\'15"+1f.2c(1f.1y()*2b)+"\' 1g=\'1m()\' J=\'z:"+(W+29)+"p;A:"+(V+17)+"p;\'> </U>")}}n{3($("#8").r("Y")!="T"){3(m[\'1A\']!="1b"){$("#8").q("<4 5=\'2f\'><4 5=\'1H\'>"+d+"</4><4 5=\'2e\'><a u=\'#\' 5=\'Z\'>1l</a> 1k 1j 1s</4></4><4 5=\'F\' J=\'z:"+W+"p;A:"+V+"p\'></4>")}n{$("#B").N();$("#8").q("<4 5=\'F\' 3c=\'3b\' J=\'z:"+W+"p;A:"+V+"p;\'></4>")}}n{$("#F")[0].J.z=W+"p";$("#F")[0].J.A=V+"p";$("#F")[0].3a=0;$("#1H").11(d)}}$("#Z").s(G);3(f.O(\'37\')!=-1){$("#F").q($(\'#\'+m[\'26\']).1T());$("#8").24(9(){$(\'#\'+m[\'26\']).q($("#F").1T())});16();$("#K").C();$("#8").r({Y:"T"})}n 3(f.O(\'2j\')!=-1){16();3($.1q.35){$("#K").C();$("#8").r({Y:"T"})}}n{$("#F").34(f+="&1y="+(1p 33().32()),9(){16();$("#K").C();1u("#F a.18");$("#8").r({Y:"T"})})}}3(!m[\'1A\']){o.21=9(e){3(e==M){I=2w.2v}n{I=e.2u}3(I==27){G()}}}}31(e){}}9 1m(){$("#K").C();$("#8").r({Y:"T"})}9 G(){$("#2Y").N("s");$("#Z").N("s");$("#8").2X("2W",9(){$(\'#8,#B,#1F\').2V("24").N().C()});$("#K").C();3(2t o.v.J.2i=="2g"){$("v","11").r({A:"1Z",z:"1Z"});$("11").r("22","")}o.1h="";o.21="";H P}9 16(){$("#8").r({2U:\'-\'+20((13/2),10)+\'p\',z:13+\'p\'});3(!(1V.1q.2Q&&1V.1q.2P<7)){$("#8").r({38:\'-\'+20((1a/2),10)+\'p\'})}}9 2p(a){6 b={};3(!a){H b}6 c=a.1B(/[;&]/);25(6 i=0;i<c.1c;i++){6 d=c[i].1B(\'=\');3(!d||d.1c!=2){39}6 e=2a(d[0]);6 f=2a(d[1]);f=f.2r(/\\+/g,\' \');b[e]=f}H b}9 2x(){6 a=o.2M;6 w=1S.2o||1R.2o||(a&&a.1Q)||o.v.1Q;6 h=1S.1P||1R.1P||(a&&a.2n)||o.v.2n;1O=[w,h];H 1O}9 1K(){6 a=2K.2J.1C();3(a.O(\'2I\')!=-1&&a.O(\'3o\')!=-1){H 1b}}',62,211,'|||if|div|id|var||TB_window|function||||||||||||||else|document|px|append|css|click||href|body||||width|height|TB_overlay|remove|TB_Counter|TB_TempArray|TB_ajaxContent|tb_remove|return|keycode|style|TB_load|src|null|unbind|indexOf|false|title|TB_NextHTML|imgPreloader|block|iframe|ajaxContentH|ajaxContentW|this|display|TB_closeWindowButton||html|goPrev|TB_WIDTH|TB_PrevHTML|TB_iframeContent|tb_position||thickbox|tb_show|TB_HEIGHT|true|length|nbsp|span|Math|onload|onkeydown|goNext| | |Fermer|tb_showIframe|TB_imageCount|Close|new|browser|TB_FoundURL| |Image|tb_init|name|imgLoader|TB_NextURL|random|TB_NextCaption|modal|split|toLowerCase|TB_PrevCaption|urlNoQuery|TB_HideSelect|TB_PrevURL|TB_ajaxWindowTitle|img|addClass|tb_detectMacXFF|TB_ImageOff|150|rel|arrayPageSize|innerHeight|clientWidth|self|window|children|TB_prev|jQuery|frameborder|TB_next|getElementById|auto|parseInt|onkeyup|overflow|alt|unload|for|inlineId||100||unescape|1000|round|hspace|TB_closeAjaxWindow|TB_title|undefined|match|maxHeight|TB_iframe|bmp|gif|png|clientHeight|innerWidth|tb_parseQuery|jpeg|replace|jpg|typeof|which|keyCode|event|tb_getPageSize|show|TB_overlayBG|TB_closeWindow|TB_overlayMacFFBGHack|TB_secondLine|TB_caption|blur|TB_Image|60|tb_pathToImage|mac|userAgent|navigator|of|documentElement|Prev|lt|version|msie|gt|ready|Next|marginLeft|trigger|fast|fadeOut|TB_imageOff|hidden||catch|getTime|Date|load|safari|get|TB_inline|marginTop|continue|scrollTop|TB_modal|class|TB_|45|440|40|630|input|188|190|substr|try|area|firefox'.split('|'),0,{}))
;

function displayThickbox(title,innerHTML,width,height){// width & height must be specified in innerHTML
	var html='<a href="#TB_inline?height='+height+'&width='+width+'&inlineId=thickboxcontent&modal=false" id="thickbox-id" title="'+title+'"  class="thickbox"></a>'+
	'<div id="thickboxcontent" class="thickbox" style="display:none">'+innerHTML+'</div>';
		
	document.getElementById('div-thickbox').innerHTML = html;

    var a = document.getElementById('thickbox-id');
    var t = a.title || a.name || null;
    var l = a.href || a.alt;
    var g = a.rel || false;
    tb_show(t,l,g);
    a.focus();		
}

;
/*
 * jQuery Autocomplete plugin 1.1
 *
 * Copyright (c) 2009 JÃ¶rn Zaefferer
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.autocomplete.js 15 2009-08-22 10:30:27Z joern.zaefferer $
 */
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}(';(3($){$.2e.1u({19:3(b,d){5 c=W b=="1B";d=$.1u({},$.M.1T,{Y:c?b:P,y:c?P:b,1J:c?$.M.1T.1J:10,X:d&&!d.1D?10:48},d);d.1y=d.1y||3(a){6 a};d.1v=d.1v||d.1R;6 A.I(3(){1M $.M(A,d)})},L:3(a){6 A.11("L",a)},1k:3(a){6 A.14("1k",[a])},2b:3(){6 A.14("2b")},28:3(a){6 A.14("28",[a])},24:3(){6 A.14("24")}});$.M=3(o,r){5 t={2Y:38,2S:40,2N:46,2I:9,2E:13,2B:27,2x:3I,2v:33,2p:34,2n:8};5 u=$(o).3r("19","3o").Q(r.2Q);5 p;5 m="";5 n=$.M.3c(r);5 s=0;5 k;5 h={1F:C};5 l=$.M.32(r,o,1Z,h);5 j;$.1Y.2X&&$(o.2U).11("45.19",3(){4(j){j=C;6 C}});u.11(($.1Y.2X?"43":"42")+".19",3(a){s=1;k=a.2M;3V(a.2M){O t.2Y:a.1d();4(l.N()){l.30()}w{12(0,D)}R;O t.2S:a.1d();4(l.N()){l.2D()}w{12(0,D)}R;O t.2v:a.1d();4(l.N()){l.2C()}w{12(0,D)}R;O t.2p:a.1d();4(l.N()){l.2A()}w{12(0,D)}R;O r.17&&$.1c(r.S)==","&&t.2x:O t.2I:O t.2E:4(1Z()){a.1d();j=D;6 C}R;O t.2B:l.Z();R;3J:1P(p);p=1O(12,r.1J);R}}).2t(3(){s++}).3E(3(){s=0;4(!h.1F){2r()}}).2q(3(){4(s++>1&&!l.N()){12(0,D)}}).11("1k",3(){5 c=(1r.7>1)?1r[1]:P;3 1N(q,a){5 b;4(a&&a.7){16(5 i=0;i<a.7;i++){4(a[i].L.J()==q.J()){b=a[i];R}}}4(W c=="3")c(b);w u.14("L",b&&[b.y,b.F])}$.I(15(u.K()),3(i,a){21(a,1N,1N)})}).11("2b",3(){n.1o()}).11("28",3(){$.1u(r,1r[1]);4("y"2h 1r[1])n.1e()}).11("24",3(){l.1p();u.1p();$(o.2U).1p(".19")});3 1Z(){5 e=l.2g();4(!e)6 C;5 v=e.L;m=v;4(r.17){5 b=15(u.K());4(b.7>1){5 f=r.S.7;5 c=$(o).18().1I;5 d,1H=0;$.I(b,3(i,a){1H+=a.7;4(c<=1H){d=i;6 C}1H+=f});b[d]=v;v=b.3f(r.S)}v+=r.S}u.K(v);1l();u.14("L",[e.y,e.F]);6 D}3 12(b,c){4(k==t.2N){l.Z();6}5 a=u.K();4(!c&&a==m)6;m=a;a=1m(a);4(a.7>=r.29){u.Q(r.26);4(!r.1s)a=a.J();21(a,3a,1l)}w{1q();l.Z()}};3 15(b){4(!b)6[""];4(!r.17)6[$.1c(b)];6 $.4h(b.23(r.S),3(a){6 $.1c(b).7?$.1c(a):P})}3 1m(a){4(!r.17)6 a;5 c=15(a);4(c.7==1)6 c[0];5 b=$(o).18().1I;4(b==a.7){c=15(a)}w{c=15(a.22(a.37(b),""))}6 c[c.7-1]}3 1G(q,a){4(r.1G&&(1m(u.K()).J()==q.J())&&k!=t.2n){u.K(u.K()+a.37(1m(m).7));$(o).18(m.7,m.7+a.7)}};3 2r(){1P(p);p=1O(1l,4g)};3 1l(){5 c=l.N();l.Z();1P(p);1q();4(r.36){u.1k(3(a){4(!a){4(r.17){5 b=15(u.K()).1n(0,-1);u.K(b.3f(r.S)+(b.7?r.S:""))}w{u.K("");u.14("L",P)}}})}};3 3a(q,a){4(a&&a.7&&s){1q();l.35(a,q);1G(q,a[0].F);l.20()}w{1l()}};3 21(f,d,g){4(!r.1s)f=f.J();5 e=n.31(f);4(e&&e.7){d(f,e)}w 4((W r.Y=="1B")&&(r.Y.7>0)){5 c={4f:+1M 4e()};$.I(r.2Z,3(a,b){c[a]=W b=="3"?b():b});$.4d({4c:"4b",4a:"19"+o.49,2V:r.2V,Y:r.Y,y:$.1u({q:1m(f),47:r.X},c),44:3(a){5 b=r.1A&&r.1A(a)||1A(a);n.1i(f,b);d(f,b)}})}w{l.2T();g(f)}};3 1A(c){5 d=[];5 b=c.23("\\n");16(5 i=0;i<b.7;i++){5 a=$.1c(b[i]);4(a){a=a.23("|");d[d.7]={y:a,F:a[0],L:r.1z&&r.1z(a,a[0])||a[0]}}}6 d};3 1q(){u.1h(r.26)}};$.M.1T={2Q:"41",2P:"3Z",26:"3Y",29:1,1J:3W,1s:C,1f:D,1w:C,1g:10,X:3U,36:C,2Z:{},1X:D,1R:3(a){6 a[0]},1v:P,1G:C,E:0,17:C,S:", ",1y:3(b,a){6 b.22(1M 3T("(?![^&;]+;)(?!<[^<>]*)("+a.22(/([\\^\\$\\(\\)\\[\\]\\{\\}\\*\\.\\+\\?\\|\\\\])/2K,"\\\\$1")+")(?![^<>]*>)(?![^&;]+;)","2K"),"<2J>$1</2J>")},1D:D,1E:3S};$.M.3c=3(g){5 h={};5 j=0;3 1f(s,a){4(!g.1s)s=s.J();5 i=s.2H(a);4(g.1w=="3R"){i=s.J().1k("\\\\b"+a.J())}4(i==-1)6 C;6 i==0||g.1w};3 1i(q,a){4(j>g.1g){1o()}4(!h[q]){j++}h[q]=a}3 1e(){4(!g.y)6 C;5 f={},2G=0;4(!g.Y)g.1g=1;f[""]=[];16(5 i=0,2F=g.y.7;i<2F;i++){5 c=g.y[i];c=(W c=="1B")?[c]:c;5 d=g.1v(c,i+1,g.y.7);4(d===C)1V;5 e=d.3Q(0).J();4(!f[e])f[e]=[];5 b={F:d,y:c,L:g.1z&&g.1z(c)||d};f[e].1U(b);4(2G++<g.X){f[""].1U(b)}};$.I(f,3(i,a){g.1g++;1i(i,a)})}1O(1e,25);3 1o(){h={};j=0}6{1o:1o,1i:1i,1e:1e,31:3(q){4(!g.1g||!j)6 P;4(!g.Y&&g.1w){5 a=[];16(5 k 2h h){4(k.7>0){5 c=h[k];$.I(c,3(i,x){4(1f(x.F,q)){a.1U(x)}})}}6 a}w 4(h[q]){6 h[q]}w 4(g.1f){16(5 i=q.7-1;i>=g.29;i--){5 c=h[q.3O(0,i)];4(c){5 a=[];$.I(c,3(i,x){4(1f(x.F,q)){a[a.7]=x}});6 a}}}6 P}}};$.M.32=3(e,g,f,k){5 h={H:"3N"};5 j,z=-1,y,1t="",1S=D,G,B;3 2y(){4(!1S)6;G=$("<3M/>").Z().Q(e.2P).T("3L","3K").1Q(1K.2w);B=$("<3H/>").1Q(G).3G(3(a){4(U(a).2u&&U(a).2u.3F()==\'2s\'){z=$("1L",B).1h(h.H).3D(U(a));$(U(a)).Q(h.H)}}).2q(3(a){$(U(a)).Q(h.H);f();g.2t();6 C}).3C(3(){k.1F=D}).3B(3(){k.1F=C});4(e.E>0)G.T("E",e.E);1S=C}3 U(a){5 b=a.U;3A(b&&b.3z!="2s")b=b.3y;4(!b)6[];6 b}3 V(b){j.1n(z,z+1).1h(h.H);2o(b);5 a=j.1n(z,z+1).Q(h.H);4(e.1D){5 c=0;j.1n(0,z).I(3(){c+=A.1a});4((c+a[0].1a-B.1b())>B[0].3x){B.1b(c+a[0].1a-B.3w())}w 4(c<B.1b()){B.1b(c)}}};3 2o(a){z+=a;4(z<0){z=j.1j()-1}w 4(z>=j.1j()){z=0}}3 2m(a){6 e.X&&e.X<a?e.X:a}3 2l(){B.2z();5 b=2m(y.7);16(5 i=0;i<b;i++){4(!y[i])1V;5 a=e.1R(y[i].y,i+1,b,y[i].F,1t);4(a===C)1V;5 c=$("<1L/>").3v(e.1y(a,1t)).Q(i%2==0?"3u":"3P").1Q(B)[0];$.y(c,"2k",y[i])}j=B.3t("1L");4(e.1X){j.1n(0,1).Q(h.H);z=0}4($.2e.2W)B.2W()}6{35:3(d,q){2y();y=d;1t=q;2l()},2D:3(){V(1)},30:3(){V(-1)},2C:3(){4(z!=0&&z-8<0){V(-z)}w{V(-8)}},2A:3(){4(z!=j.1j()-1&&z+8>j.1j()){V(j.1j()-1-z)}w{V(8)}},Z:3(){G&&G.Z();j&&j.1h(h.H);z=-1},N:3(){6 G&&G.3s(":N")},3q:3(){6 A.N()&&(j.2j("."+h.H)[0]||e.1X&&j[0])},20:3(){5 a=$(g).3p();G.T({E:W e.E=="1B"||e.E>0?e.E:$(g).E(),2i:a.2i+g.1a,1W:a.1W}).20();4(e.1D){B.1b(0);B.T({2L:e.1E,3n:\'3X\'});4($.1Y.3m&&W 1K.2w.3l.2L==="1x"){5 c=0;j.I(3(){c+=A.1a});5 b=c>e.1E;B.T(\'3k\',b?e.1E:c);4(!b){j.E(B.E()-2R(j.T("2O-1W"))-2R(j.T("2O-3j")))}}}},2g:3(){5 a=j&&j.2j("."+h.H).1h(h.H);6 a&&a.7&&$.y(a[0],"2k")},2T:3(){B&&B.2z()},1p:3(){G&&G.3i()}}};$.2e.18=3(b,f){4(b!==1x){6 A.I(3(){4(A.2d){5 a=A.2d();4(f===1x||b==f){a.4n("2c",b);a.3h()}w{a.4m(D);a.4l("2c",b);a.4k("2c",f);a.3h()}}w 4(A.3g){A.3g(b,f)}w 4(A.1C){A.1C=b;A.3e=f}})}5 c=A[0];4(c.2d){5 e=1K.18.4j(),3d=c.F,2a="<->",2f=e.3b.7;e.3b=2a;5 d=c.F.2H(2a);c.F=3d;A.18(d,d+2f);6{1I:d,39:d+2f}}w 4(c.1C!==1x){6{1I:c.1C,39:c.3e}}}})(4i);',62,272,'|||function|if|var|return|length|||||||||||||||||||||||||else||data|active|this|list|false|true|width|value|element|ACTIVE|each|toLowerCase|val|result|Autocompleter|visible|case|null|addClass|break|multipleSeparator|css|target|moveSelect|typeof|max|url|hide||bind|onChange||trigger|trimWords|for|multiple|selection|autocomplete|offsetHeight|scrollTop|trim|preventDefault|populate|matchSubset|cacheLength|removeClass|add|size|search|hideResultsNow|lastWord|slice|flush|unbind|stopLoading|arguments|matchCase|term|extend|formatMatch|matchContains|undefined|highlight|formatResult|parse|string|selectionStart|scroll|scrollHeight|mouseDownOnSelect|autoFill|progress|start|delay|document|li|new|findValueCallback|setTimeout|clearTimeout|appendTo|formatItem|needsInit|defaults|push|continue|left|selectFirst|browser|selectCurrent|show|request|replace|split|unautocomplete||loadingClass||setOptions|minChars|teststring|flushCache|character|createTextRange|fn|textLength|selected|in|top|filter|ac_data|fillList|limitNumberOfItems|BACKSPACE|movePosition|PAGEDOWN|click|hideResults|LI|focus|nodeName|PAGEUP|body|COMMA|init|empty|pageDown|ESC|pageUp|next|RETURN|ol|nullData|indexOf|TAB|strong|gi|maxHeight|keyCode|DEL|padding|resultsClass|inputClass|parseInt|DOWN|emptyList|form|dataType|bgiframe|opera|UP|extraParams|prev|load|Select|||display|mustMatch|substring||end|receiveData|text|Cache|orig|selectionEnd|join|setSelectionRange|select|remove|right|height|style|msie|overflow|off|offset|current|attr|is|find|ac_even|html|innerHeight|clientHeight|parentNode|tagName|while|mouseup|mousedown|index|blur|toUpperCase|mouseover|ul|188|default|absolute|position|div|ac_over|substr|ac_odd|charAt|word|180|RegExp|100|switch|400|auto|ac_loading|ac_results||ac_input|keydown|keypress|success|submit||limit|150|name|port|abort|mode|ajax|Date|timestamp|200|map|jQuery|createRange|moveEnd|moveStart|collapse|move'.split('|'),0,{}))
;
/* 
    Document   : search header js
    Author     : ibasset
*/

var searchHeader = new function(){

	var CONSTANTS_RECHERCHE_SOCIETE = 0;
	var CONSTANTS_RECHERCHE_UTILISATEUR = 1;
	var CONSTANTS_RECHERCHE_SECTEUR_ACTIVITE = 2;
	
	var CONSTANTS_MIN_SEARCH_LENGTH = 1;
	
	var typeSearch;
	var searchValue;
	var contextPath;
	var searchlist;
	
	return {

		processSearch: function (){	
			
			typeSearch = document.getElementById('typeSearch').value;
			searchValue = document.getElementById('headerSearch').value;
			
			//convert searchValue into societelogin or userlogin
			var classname=$('input[id=headerSearch]').attr('class');
			
			if (classname == 'champ defaultState'){
				searchValue='';
			}else{
				searchValue = searchHeader.getLogin(searchValue);
			}
			alert(searchValue);
		
			document.location.href=contextPath+"/Search.do?typeSearch="+typeSearch+"&search="+searchValue;
		},
		
		checkTypeSearch:function(form) {
			var classname=$('input[id=headerSearch]').attr('class');
			if (classname == 'champ defaultState'){
				form.headerSearch.value = '';
				form.dispatch.value = 'view';
			}
			return true;
		},
		
		callSearchServlet: function (context_path){
			if (!contextPath) contextPath = context_path;//if contextPath is null, set value

			typeSearch = document.getElementById('typeSearch').value;
			searchValue = document.getElementById('headerSearch').value;
		 
			if (searchValue.length==CONSTANTS_MIN_SEARCH_LENGTH){//rechercher is the default value of textbox, when page loads
				
					var servlet;
				switch (parseInt(typeSearch)){
					case CONSTANTS_RECHERCHE_SOCIETE:
						servlet = '/SearchCompany_Servlet';
						break;
					case CONSTANTS_RECHERCHE_UTILISATEUR:
						servlet = '/SearchUser_Servlet';
						break;
					case CONSTANTS_RECHERCHE_SECTEUR_ACTIVITE:
						servlet = '/SearchSecteurActivite_Servlet';
						break;
					default:
						servlet = '/SearchCompany_Servlet';
						break;
					
				}
				//method AJAXInteractionServlet (from ajaxServlet.js) used to call the servlet
				var ai = new AJAXInteractionServlet(servlet+'?mot='+searchValue,function (responseJSON){
								searchHeader.returnSearchResult(responseJSON);
							});	
				ai.doGet();
			}
			
		},
		returnSearchResult: function(responseJSON){

			$("#headerSearch").unautocomplete();//remove previous suggestion values 
			
			var xmlDoc = responseJSON.documentElement;
			var xRows = xmlDoc.getElementsByTagName('list');
		
			searchlist = eval('('+xRows[0].firstChild.nodeValue+')');
		
			switch (parseInt(typeSearch)){
					
					case CONSTANTS_RECHERCHE_SOCIETE:
						//set autocomplete on search textbox
						$("#headerSearch").autocomplete(searchlist, {
								minChars: 1, //min. letter typed in textbox
								width: 390,
								matchContains: "word", // true: search in whole word, word: search only beginning of word
								autoFill: false, //text box filled with first match
								formatItem: function(row, i, max) {
									return url.decode(row.nom).ReplaceAll('+',' ');
								},
								formatMatch: function(row, i, max) {
									return url.decode(row.nom).ReplaceAll('+',' ');
								},
								formatResult: function(row) {
									return url.decode(row.nom).ReplaceAll('+',' ');
								},
								highlight: function(value, term) {
									return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<span style='color:#0099cc'><strong>$1</strong></span>");
								}
							});
						break;
					case CONSTANTS_RECHERCHE_UTILISATEUR:
						//set autocomplete on search textbox
						$("#headerSearch").autocomplete(searchlist, {
								minChars: 1, //min. letter typed in textbox
								width: 390,
								matchContains: "word", 
								autoFill: false, //text box filled with first match
								formatItem: function(row, i, max) {
									if (row.fonction && row.fonction != 'undefined')
										return url.decode(row.nom).ReplaceAll('+',' ')+' - '+url.decode(row.company).ReplaceAll('+',' ')+'<br/>'+url.decode(row.fonction).ReplaceAll('+',' ')+'<br/>';
									else
										return url.decode(row.nom).ReplaceAll('+',' ')+' - '+url.decode(row.company).ReplaceAll('+',' ')+'<br/> - <br/>';
								},
								formatMatch: function(row, i, max) {
									return url.decode(row.nom).ReplaceAll('+',' ');
								},
								formatResult: function(row) {
									
									return url.decode(row.nom).ReplaceAll('+',' ');
								},
								highlight: function(value, term) {
									return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<span style='color:#0099cc'><strong>$1</strong></span>");
								}
							});
						break;
					case CONSTANTS_RECHERCHE_SECTEUR_ACTIVITE:
						//set autocomplete on search textbox
						$("#headerSearch").autocomplete(searchlist, {
								minChars: 1, //min. letter typed in textbox
								width: 390,
								matchContains: "word", 
								autoFill: false, //text box filled with first match
								formatItem: function(row, i, max) {
										return url.decode(row.secteurlabel).ReplaceAll('+',' ');
								},
								formatMatch: function(row, i, max) {
									return url.decode(row.secteurlabel).ReplaceAll('+',' ');
								},
								formatResult: function(row) {
									return url.decode(row.secteurlabel).ReplaceAll('+',' ');
								},
								highlight: function(value, term) {
									return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<span style='color:#0099cc'><strong>$1</strong></span>");
								}
							});
						break;
				
					
				}

		},
		getLogin:function(searchVal){
			if (searchlist){
				for (var i=0;i<searchlist.length;i++){
					if (searchlist[i].nom==searchVal){
						return searchlist[i].login;
					}
				}
			}else
				return document.getElementById('headerSearch').value;
		},
		submitVoirPlus:function(){
			document.searchComplexActionForm.dispatch.value='showMoreResults';
			document.searchComplexActionForm.submit();
		},
		
		selectSecteur:function(sousSecteurId){
		var secteurId = parseInt(sousSecteurId / 100);
		if (document.getElementById(secteurId).checked == false){
			document.getElementById(secteurId).checked = true;
		}
	},
	
	checkUncheckAll:function(secteurId,type) {
		var id = secteurId.replace(type,"");
		var lowerIndex = parseInt(id) *100 + 1;
		var upperIndex = lowerIndex + 99;
		var check = document.getElementById(secteurId).checked ;
		// Unselect all sousSecteur between lowerIndex and UpperIndex
		for (var i=lowerIndex;i<upperIndex;i++) {
			if (document.getElementById(type+i) != null){
				document.getElementById(type+i).checked = check;
			}
		}
		/*var typeId;
		if (type == 'M') {
			typeId = 1;
		} else if (type == 'P') {
			typeId = 2;
		} else if (type == 'MEDIA') {
			typeId = 3;
		}
		document.getElementById(typeId).checked = check;*/
	}	,
	
	checkUncheck:function(secteurId,type) {
		var check = document.getElementById(secteurId).checked ;
		if (secteurId > 1 ) {
			secteurId = secteurId -1
		}
		var lowerIndex = secteurId *100 + 1;
		var upperIndex = lowerIndex + 99;
		
		// Unselect all sousSecteur between lowerIndex and UpperIndex
		
		var end=0;
		if (type == 'M') {
			end = 16;
			upperIndex = 1502;
		} else if (type == 'P') {
			end = 9;
			upperIndex = 811;
		} else if (type == 'MEDIA') {
			end = 18;
		}
		for (var j=1;j<end;j++) {
			document.getElementById(type+j).checked = check;
		}
		
		
		
		for (var i=lowerIndex;i<upperIndex;i++) {
			if (document.getElementById(type+i) != null){
				document.getElementById(type+i).checked = check;
			}
		}
	}
	
	};

}
;
/* 
    Document   : search complex js
    Author     : ibasset
    Description: methods to display Secteur & Localisation fields for the search
*/

var searchComplex = new function(){

	
	
	return {
		displaySecteurFromMetier:function(chosenmetier){
			
			switch (parseInt(chosenmetier)){
				case TYPE_METIER.MARCHAND:
					document.getElementById('divMarchand').style.display='';
					document.getElementById('divPrestataire').style.display='none';
					document.getElementById('divMedia').style.display='none';
					break;
				case TYPE_METIER.PRESTATAIRE:
					document.getElementById('divMarchand').style.display='none';
					document.getElementById('divPrestataire').style.display='';
					document.getElementById('divMedia').style.display='none';
					break;
				case TYPE_METIER.MEDIA:
					document.getElementById('divMarchand').style.display='none';
					document.getElementById('divPrestataire').style.display='none';
					document.getElementById('divMedia').style.display='';
					break;
				default:
					document.getElementById('divMarchand').style.display='none';
					document.getElementById('divPrestataire').style.display='none';
					document.getElementById('divMedia').style.display='none';
					break;	
			}
		},
		
		insertSecteur: function(){
			
			//MARCHAND
			//get chosen value
			var chosenSecteurAndSousSecteur="";
			
			//get chosen secteur list
			var secteurMarchand = document.getElementsByName('allchosenSousSecteursMarchand');
			var sousSecteurMarchand = document.getElementsByName('chosenSousSecteursMarchand');

			//loop to add secteur
			for (var i=0;i<secteurMarchand.length;i++){
				if (secteurMarchand[i].checked)
					chosenSecteurAndSousSecteur+=secteurMarchand[i].value+"; ";
			}
			
			//loop to add sous-secteur
			for (var i=0;i<sousSecteurMarchand.length;i++){
				if (sousSecteurMarchand[i].checked)
					chosenSecteurAndSousSecteur+=sousSecteurMarchand[i].value+"; ";
			}
			
			
			//PRESTATAIRE
			//get chosen secteur list
			var secteurPrestataire = document.getElementsByName('allchosenSousSecteursPrestataire');
			var sousSecteurPrestataire = document.getElementsByName('chosenSousSecteursPrestataire');

			//loop to add secteur
			for (var i=0;i<secteurPrestataire.length;i++){
				if (secteurPrestataire[i].checked)
					chosenSecteurAndSousSecteur+=secteurPrestataire[i].value+"; ";
			}
			
			//loop to add sous-secteur
			for (var i=0;i<sousSecteurPrestataire.length;i++){
				if (sousSecteurPrestataire[i].checked)
					chosenSecteurAndSousSecteur+=sousSecteurPrestataire[i].value+"; ";
			}
			
			//MEDIA
			//get chosen secteur list
				var sousSecteurMedia = document.getElementsByName('chosenSousSecteursMedia');

			//loop to add soussecteur
			for (var i=0;i<sousSecteurMedia.length;i++){
				if (sousSecteurMedia[i].checked)
					chosenSecteurAndSousSecteur+=sousSecteurMedia[i].value+"; ";
			}

			
			chosenSecteurAndSousSecteur = chosenSecteurAndSousSecteur.replace(chosenSecteurAndSousSecteur.length,"");
			
			// construst long string & insert in textfield
			document.getElementById('keyword').value=chosenSecteurAndSousSecteur;
			
			tb_remove();

		},
		displayRegion:function(chosenType){
				
//				var chosenType = document.forms[0].regionOrDepartment.value;
				
				//get selected pays
					var selectedPays = document.getElementById('numPays').value;
//				alert(chosenType+" "+selectedPays);
				//display region for each pays
				if (parseInt(chosenType)==0){
					
					switch (parseInt(selectedPays)){
						case PAYS.FRANCE:
							document.getElementById('div-region-france').style.display='';
							document.getElementById('div-region-belgique').style.display='none';
							document.getElementById('div-region-suisse').style.display='none';
							break;
						case PAYS.BELGIQUE:
							document.getElementById('div-region-belgique').style.display='';
							document.getElementById('div-region-france').style.display='none';
							document.getElementById('div-region-suisse').style.display='none';
							break;
						case PAYS.LUXEMBOURGH:
							//has no region
							document.getElementById('div-region-suisse').style.display='none';
							document.getElementById('div-region-belgique').style.display='none';
							document.getElementById('div-region-france').style.display='none';
							break;
						case PAYS.SUISSE:
							document.getElementById('div-region-suisse').style.display='';
							document.getElementById('div-region-belgique').style.display='none';
							document.getElementById('div-region-france').style.display='none';
							break;
						default:
							document.getElementById('div-region-suisse').style.display='none';
							document.getElementById('div-region-belgique').style.display='none';
							document.getElementById('div-region-france').style.display='none';
							break;
					}
				}else if (parseInt(chosenType)==1){ //department chosen
					document.getElementById('div-region-suisse').style.display='none';
							document.getElementById('div-region-belgique').style.display='none';
							document.getElementById('div-region-france').style.display='none';
//					alert(parseInt(selectedPays)==PAYS.FRANCE);
					//only France has department
					if (parseInt(selectedPays)==PAYS.FRANCE){
						document.getElementById('div-departement').style.display='';
					}else{
						document.getElementById('div-departement').style.display='none';
					}
				}
				
			
				
		},
		insertLocalisation:function(){

			var chosenRegionAndDepartment="";
			
			var selectedRegion = document.getElementsByName('numRegion');
			//loop to add secteur
			for (var i=0;i<selectedRegion.length;i++){
				if (selectedRegion[i].checked && selectedRegion[i].value.length>0)
					chosenRegionAndDepartment+=selectedRegion[i].value+"; ";
			}
			
			var selectedDepartment = document.getElementsByName('numDepartment');
			//loop to add secteur
			for (var i=0;i<selectedDepartment.length;i++){
				if (selectedDepartment[i].checked && selectedDepartment[i].value.length>0)
					chosenRegionAndDepartment+=selectedDepartment[i].value+"; ";
			}
			
			
			
			// construst long string & insert in textfield
			document.getElementById('location').value=chosenRegionAndDepartment;
			
			tb_remove();
			
		},resetRegionAndDepartment:function(){
			var regions = document.getElementsByName('numRegion');
			for (var i=0;i<regions.length;i++){
				if (regions[i].checked)
					document.getElementsByName('numRegion')[i].checked=false;
			}
			
			var deptartments = document.getElementsByName('numDepartment');
			for (var i=0;i<deptartments.length;i++){
				if (deptartments[i].checked)
					document.getElementsByName('numDepartment')[i].checked=false;
			}
			
			document.getElementById('region').checked=true;
		}
		
	};

}
;
var handleHtmlElements={
	
	//delete element from its id
	removeElement:function (id) {
		  var element = document.getElementById(id);
		  element.parentNode.removeChild(element);
		},
		
	// change innerHTML in a div
	editInnerHtml:function(id,innerhtml){
		var element = document.getElementById(id);
		if (null != element)
			element.innerHTML=innerhtml;
	}
}
;

INSCRIPTION_TEXT = {
	NOM_REQUIRED : "Veuillez entrer votre nom de famille",
	NOM_MINLENGTH: "Votre nom de famille doit avoir au moins 2 caracteres",
	
	PRENOM_REQUIRED: "Veuillez entrer votre pr\u00E9nom",
	PRENOM_MINLENGTH: "Votre pr\u00E9nom doit avoir au moins 2 caracteres",
	
	FONCTION_REQUIRED: "Veuillez entrer votre fonction",
	FONCTION_MINLENGTH: "Votre fonction doit avoir au moins 2 caracteres",

	MDP_REQUIRED: "Veuillez entrer votre mot de passe",
	MDP_MINLENGTH: "Votre mot de passe doit avoir au moins 7 caracteres",

	CONFIRMMDP_REQUIRED: "Veuillez confirmer votre mot de passe ",
	CONFIRMMDP_MINLENGTH: "Votre mot de passe doit avoir au moins 7 caracteres",
	CONFIRMMDP_EQUAL: "Veuillez entrer le m\u00EAme mot de passe",

	CHOSEN_ACTIVITE: "Veuillez choisir une activit\u00E9",
	
	TYPE_METIER: "Veuillez choisr un type de membre",

	NOMSITE_REQUIRED: "Veuillez entrer le nom de votre site",
	NOMSITE_MINLENGTH: "Le nom de votre site doit avoir au moins 2 caracteres",
	
	URL_REQUIRED: "Veuillez entrer l'URL de votre site",
	URL: "Votre URL est invalide",
	
	DESCRIPTION_MAXLENGTH: "Description ne doit pas depasser 140 caract\u00E8res",
	
	ACCEPTCOND_REQUIRED: "Veuillez accepter le CGU pour vous inscrire",
	
	TELEPHONE_MINLENGTH: "Votre num\u00E9ro de t\u00E9l\u00E9phone doit avoir au moins 7 caract\u00E8res",	
	TELEPHONE_MAXLENGTH: "Votre num\u00E9ro de t\u00E9l\u00E9phone doit <br> avoir au moins 15 caract\u00E8res",
	
	CODE_POSTAL_NUMBER_ONLY: "Valeurs num\u00E9riques svp",
	CODE_POSTAL_MAXLENGTH: "Votre code postal doit <br> avoir au moins 5 caract\u00E8res"
}
;function AJAXInteractionServlet(url, callback) {

    var req = init();
    req.onreadystatechange = processRequest;
        
    function init() {
        if (window.XMLHttpRequest) {
            return new XMLHttpRequest();
        } else if (window.ActiveXObject) {
            return new ActiveXObject("Microsoft.XMLHTTP");
        }
    }
    
    function processRequest() {
        if (req.readyState == 4) {
            if (req.status == 200) {
                if (callback) callback(req.responseXML);
            }
        }
    }

    this.doGet = function() {
        //add a timestamp to url to avoid cache problems
        var now = new Date();
        url += "&timestamp=" + now.getMinutes()+now.getMilliseconds();
        req.open("GET", url, true);
        req.send(null);
    }
    
    this.doPost = function(body) {
        req.open("POST", url, true);
        req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        req.send(body);
    }
}

function AJAXInteractionSyncServlet(url, func2call) {

    var req = init();
        
    function init() {
        if (window.XMLHttpRequest) {
            return new XMLHttpRequest();
        } else if (window.ActiveXObject) {
            return new ActiveXObject("Microsoft.XMLHTTP");
        }
    }
    
    function processRequest() {
        if (req.status == 200) {
            if (func2call) func2call(req.responseXML);
        }
    }

    this.doGet = function() {
        req.open("GET", url, false);
        req.send(null);
        processRequest();
    }
    
    this.doPost = function(body) {
        req.open("POST", url, false);
        req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        req.send(body);
        processRequest();
    }
}

function doPost(url, parameters) {
  // create the AJAX object
  var xmlHttp = undefined;
  if (window.ActiveXObject){
    try {
      xmlHttp = new ActiveXObject("MSXML2.XMLHTTP");
    } catch (othermicrosoft){
      try {
        xmlHttp = new ActiveXObject(
            "Microsoft.XMLHTTP");
      } catch (failed) {}
    }
  }    

  if (xmlHttp == undefined && window.XMLHttpRequest) {
    // If IE7, Mozilla, Safari, etc: Use native object
    xmlHttp = new XMLHttpRequest();
  }  

  if (xmlHttp != undefined) {
    // open the connections
    xmlHttp.open("POST", url, true);
    // callback handler
    xmlHttp.onreadystatechange = function() {
      // test if the response was totally sent
      if (xmlHttp.readyState == 4
            && xmlHttp.status == 200) {
        // so far so good
        // do something useful with the response
      }
    }  

    // create the parameter string
    // iterate the parameters array
    var parameterString;  

    for (var i = 0; i < n; i++) {
      parameterString += (i > 0 ? "&" : "")
          + parameters[i][0] + "="
          + encodeURI(parameters[i][1]);
    }  

    // set the necessary request headers
    xmlHttp.setRequestHeader("Content-type",
        "application/x-www-form-urlencoded");
    xmlHttp.setRequestHeader("Content-length",
        parameterString.length);
    xmlHttp.setRequestHeader("Connection", "close");  

    // send request
    xmlHttp.send(parameterString);
  }
}

;

var actionfeedback = new function() {
    return {
        /*
		 * Calls servlet to send mail
		 * feedbackid: html element id to  be changed / removed in actionFeedbackResponse
		 * servletToCall: string containing servlet to call and its params (separate servlet and params with ? )
		 */
        doActionFeedback:function(feedbackid,servletToCall,params){
            var ai = new AJAXInteractionServlet( servletToCall, function (responseXML){
                actionfeedback.actionFeedbackResponse(feedbackid,responseXML);
            });
            ai.doPost(params);
        },
        /*
         * Handles action feedback response
         * feedbackid : html element id to change / remove
         * responseXML: xml containing servlet response
         */
        actionFeedbackResponse:function(feedbackid,responseXML){
        	
            var xmlDoc = responseXML.documentElement;
            if (xmlDoc !=null){
                var type = xmlDoc.getElementsByTagName('type')[0].firstChild.nodeValue;
                var text = url.decode(xmlDoc.getElementsByTagName('text')[0].firstChild.nodeValue);
                text = text.ReplaceAll("+"," ");
				
				//page must redirect if inscription
				if (type == RESPONSE_TYPE.VALID ){
					try{
						if (feedbackid == 'errLoginProfilMsg'){
							$('#alreadyRegistered').val(true);
							$('#frontPageRegisterForm').submit();
							return;
						}else if (feedbackid == 'errLoginMsg' || feedbackid == 'errLoginPrestataire'){
							tb_remove();
							return;
						}
					}catch (e){;
						return;
					}

				}
			

	                 $("#"+feedbackid).each(function(){
		                if (type == RESPONSE_TYPE.ERROR){
		                    $(this).html(url.decode(text));
		                    if (feedbackid!='errLoginProfilMsg')
		                    	$(this).removeClass();
		                    	
		                    $(this).css('color','red');
		                }else if (type == RESPONSE_TYPE.INFO){
		                    $(this).html(url.decode(text));
		                     if (feedbackid!='errLoginProfilMsg')
		                   		$(this).removeClass();
		                    $(this).addClass('details');
		                    $(this).css('color','#ababab');
		                }else if (type == RESPONSE_TYPE.VALID){
		                    $(this).html(url.decode(text));
		                  	$(this).removeClass();
		                    $(this).css('color','green');
		                    $(this).css('background-color','#FFFFFF');
		                } else if (type == RESPONSE_TYPE.CLOSEDEAL){
		                    $(this).html(url.decode(text));
		                  	$(this).removeClass();
		                    $(this).css('color','green');
		                    $(this).css('background-color','#FFFFFF');
		                    $('div[id=tbAction]').css('display','none');
		                }
		                else if (type == RESPONSE_TYPE.BROADCAST1BY1){		                	
		                	 $(this).html(url.decode(text));        	
		                	 $(this).css('color','#00CC00');
		                   	 $(this).css('background-color','#FFFFFF');      	 
						} else if (type == RESPONSE_TYPE.NOSTYLE){
		                    $(this).html(url.decode(text));
		                } else if (type == RESPONSE_TYPE.PARTICIPATE_EVENT){
		                    $(this).html(url.decode(text));
		                  	$(this).removeClass();		                  			                   
		                    $(this).css('background-color','#FFFFFF');
		                } else if (type == RESPONSE_TYPE.PARTICIPATE_EVENT_DROP){
		                    $(this).html(url.decode(text));
		                  	$(this).removeClass();		                  			                   
		                    $(this).css('background-color','#FFFFFF');
		                }
		                
		                
		                $(this).removeAttr('href');
		                $(this).removeAttr('onclick');
		                
		                //$(this).href="#";
		                //$(this).onclick="#";
		                });
		                
		                //necessary for action DealProposalAction.FOLLOW
	                 $("."+feedbackid).each(function(){
		                if (type == RESPONSE_TYPE.ERROR){
		                    $(this).html(url.decode(text));
		                    $(this).removeClass();
//		                    $(this).addClass('error');
		                    $(this).css('color','red');
		                }else if (type == RESPONSE_TYPE.INFO){
		                    $(this).html(url.decode(text));
		                    $(this).removeClass();
//		                    $(this).addClass('details');
		                    $(this).css('color','#ababab;');
		                }else if (type == RESPONSE_TYPE.VALID){
		                    $(this).html(url.decode(text));
		                    $(this).removeClass();
//		                    $(this).addClass('success');
		                    $(this).css('color','green');
		                    $(this).css('background-color','#FFFFFF');
		                }
		                else if (type == RESPONSE_TYPE.NOSTYLE){
		                    $(this).html(url.decode(text));
		                }
//		                $(this).href="#";
//		                $(this).onclick="#";
		                
		                $(this).removeAttr('href');
		                $(this).removeAttr('onclick');
		                });
	                
//                }
            }
        }
    }
}
RESPONSE_TYPE = {
    ERROR: "ERROR",
    INFO: "INFO",
    VALID: "VALID",
    NOSTYLE: "NOSTYLE",
    BROADCAST1BY1: "BROADCAST1BY1",
    CLOSEDEAL: "CLOSEDEAL",
    PARTICIPATE_EVENT: "PARTICIPATE_EVENT",
    PARTICIPATE_EVENT_DROP: "PARTICIPATE_EVENT_DROP"
}


;var mailfeedback = new function(){
	
	return {
		/*
		 * Calls servlet to send mail
		 * feedbackid: html element id to  be changed / removed in mailFeedbackResponse
		 * changestate: true / false - in addition with jGrowl message, whether change or not html element
		 * servletToCall: string containing servlet to call and its params (separate servlet and params with ? )
		 */
		doMailFeedback:function(feedackid,changestate,servletToCall,params){
			var ai = new AJAXInteractionServlet( servletToCall,function (responseXML){
                mailfeedback.mailFeedbackResponse(feedackid,changestate,responseXML);
            });
            ai.doPost(params);
        },
        /*
         * Handles mail response
         * feedbackid : html element id to change / remove. If null, set messages in div mailresponse
         * changestate: true / false - in addition with jGrowl message, whether change or not html element
         * responseXML: xml containing servlet response
         */
        mailFeedbackResponse:function(feedbackid,changestate,responseXML){
            var xmlDoc = responseXML.documentElement;
            if (xmlDoc !=null){
                var type = xmlDoc.getElementsByTagName('type')[0].firstChild.nodeValue;
                var text = url.decode(xmlDoc.getElementsByTagName('text')[0].firstChild.nodeValue);
                text = text.ReplaceAll("+"," ");
                if (type == RESPONSE_TYPE.ERROR){
					if (feedbackid == 'mailresponse_new'){
                		document.getElementById('mailresponse_new').innerHTML=url.decode(text);
                	}else if (feedbackid=='forwardmailresponse'){
                    	document.getElementById('forwardmailresponse').innerHTML=url.decode(text);
                    }else if (feedbackid=='mailresponsemail'){
                    	document.getElementById('mailresponsemail').innerHTML=url.decode(text);
                    }else if (feedbackid=='inviteCompanymailresponse'){
                    	document.getElementById('inviteCompanymailresponse').innerHTML=url.decode(text);
                    }else if (feedbackid=='askfeedbackRequestmailresponse'){
                    	document.getElementById('askfeedbackRequestmailresponse').innerHTML=url.decode(text);
                    }else if (feedbackid=='errLoginMsg'){
                    	document.getElementById('errLoginMsg').innerHTML=url.decode(text);                    	
                    }else if (feedbackid=='errLoginPrestataire'){
                    	document.getElementById('errLoginPrestataire').innerHTML=url.decode(text);                    	
                    }else if (feedbackid=='errLoginPublicMsg'){
                    	document.getElementById('errLoginPublicMsg').innerHTML=url.decode(text);                    	
                    }else if (feedbackid=='errMailContact'){
                    	document.getElementById('errMailContact').innerHTML=url.decode(text);                    	
                    }else if (feedbackid=='errMailContactLogged'){                    	
                    	document.getElementById('errMailContactLogged').innerHTML=url.decode(text); 
                    }else{
                    	document.getElementById('mailresponse').innerHTML=url.decode(text);
                    }
                   
                }else if (type == RESPONSE_TYPE.INFO){
                    	document.getElementById('mailresponse').innerHTML=url.decode(text);
                }else if (type == RESPONSE_TYPE.VALID){
                  	
                    
                    if (feedbackid!='errLoginPrestataire' && feedbackid!='errLoginMsg' && feedbackid!='errMailContact' 
                    	&& feedbackid!='errMailContactLogged' && feedbackid!='errMailContactLogged' ) {                    	
                    	  tb_remove();
                    	   $.jGrowl(EU_TEXT.MAIL_SENT, { life: 1000 });
                    
	                    if (changestate){
	                    	var link = document.getElementById(feedbackid);
	                    	var span = document.createElement("a");
	                    	span.className = "mailNotif";
	                   		var txt = url.decode(text);
	                   		var textNode= document.createTextNode(txt);
	          				span.appendChild(textNode);
	          				
	         				link.parentNode.replaceChild(span, link);
	                    }
                    } else {
                    	mailfeedback.resetForm(feedbackid);
                    	tb_remove();
                    }
                }                
                return text;
            }

        },
        
        resetForm:function (feedbackid){        	
        	 if (feedbackid=='errLoginMsg'){        	 	
        	 	 document.getElementById('userregister').value = " ";
              	 document.getElementById('cbSecteur').value=0; 
              	 document.getElementById('errLoginMsg').innerHTML = "";  	
             } else  if (feedbackid=='errLoginPrestataire'){
             	 document.getElementById('txtEmailPrestataire').value = "";
              	 document.getElementById('cbSecteurPrestataire').value=0; 
              	 document.getElementById('errLoginPrestataire').innerHTML = "";
             } else  if (feedbackid=='errMailContact'){
             	 document.getElementById('txtMailContact').value = "";
              	 document.getElementById('txtSujet').value= "";
              	 document.getElementById('txtMessage').value= "";  
              	 document.getElementById('errMailContact').innerHTML = ""; 
             } else  if (feedbackid=='errMailContactLogged'){             	
             	 document.getElementById('txtSujetLogged').value= "";
              	 document.getElementById('txtMessageLogged').value= "";
              	 document.getElementById('errMailContactLogged').innerHTML = "";   
             }            
        }
	}
	
}
;

var followers = new function(){
	
	return{
		
		follow: function(societelogin,feedbackId){

			var params='login='+societelogin+'&action=follow';
			actionfeedback.doActionFeedback(feedbackId,'/Follow_Servlet',params);


		},
		followdrop: function(societelogin,feedbackId){

			var params='login='+societelogin+'&action=followdrop';
			actionfeedback.doActionFeedback(feedbackId,'/Follow_Servlet',params);


		},
		blockfollower: function(societelogin,feedbackId){

			var params='login='+societelogin+'&action=blockfollower';
			actionfeedback.doActionFeedback(feedbackId,'/Follow_Servlet',params);


		}
	}
	

}
;

var relation = new function(){
	
	return{
		
		drop: function(societelogin,feedbackId){

			var params='login='+societelogin;
			actionfeedback.doActionFeedback(feedbackId,'/DropRelation_Servlet',params);


		}
	}
	

}
;
EU_TEXT = {
	ENVOYER : "Envoyer",
	A: "A",
	DE: "De",
	SUJET: "Sujet",
	MESSAGE: "Message",
	TITRE: "Envoyer un message",
	INVITATION_TITRE: "Envoyer une demande de connexion",
	ARCHIVER: "Veuillez choisir au moins un mail \u00E0 archiver",
	MAIL_SENT: "Message envoy\u00E9",
	INVITATION_SENT: "Demande envoy\u00E9e",
	INVITATION_SUBJECT: " vous invite \u00e0 faire partie de son r\u00E9seau ",
	INVITATION_MESSAGE_TEXT: "Bonjour, \n\nJe vous propose de devenir relation directe de ma soci\u00E9t\u00E9, \n\nCeci nous permettra d'\u00E9changer des informations \nplus facilement, \n\nMerci de bien vouloir accepter cette demande,\n\nCordialement,\n\n",
	MAIL_TO_COMPANY: "Veuillez saisir votre message pour la soci\u00e9t\u00e9 ",
	DEAL_PROPOSAL_SUBSCRIPTION_TITRE: "S\u2019inscrire \u00E0 cette offre",
	DEAL_PROPOSAL_SUBSCRIPTION_MESSAGE: "Je demande \u00E0 m\u2019inscrire \u00E0 cette offre, je joins un message ou une proposition (recommand\u00E9)",
	DEAL_PROPOSAL_SUBSCRIPTION_PROPOSITION: "message ou proposition",
	DEAL_PROPOSAL_SUBSCRIPTION_ENVOYER_DEMANDE:"Envoyer ma demande d\u2019inscription",
	DEAL_PROPOSAL_FORWARD_TITRE:"Transmettre une offre",
	DEAL_PROPOSAL_FORWARD_MESSAGE:"Merci de s\u00E9lectionner un destinataire parmi vos relations directes en cliquant sur l\u2019image \u00E0 droite",
	DEAL_PROPOSAL_FORWARD_SUJET:"Je vous transmets cette offre",
	DEAL_PROPOSAL_FORWARD_MESSAGE1:"Bonjour,",
	DEAL_PROPOSAL_FORWARD_MESSAGE2:"Je vous invite \u00E0 d\u00E9couvrir l'offre suivante :",
	DEAL_PROPOSAL_FORWARD_MESSAGE3:"Vous trouverez plus d\u2019informations \u00E0 l\u2019adresse suivante :",
	DEAL_PROPOSAL_FORWARD_MESSAGE4:"Cordialement,",
	DEAL_PROPOSAL_FORWARD_MESSAGE5:"Veuillez saisir au moins un destinataire parmi vos relations directes.",
	DEAL_MESSAGE_TIME : "il y a moins de 5 minutes",
	MESSAGE_ERREUR_PERMUTER_DROITS: "\u00cates vous s\u00fbr de vouloir permuter vos droits d\u2019acc\u00e8s?",
	HP_NEWS_PUBLIC:"<strong>publique</strong> : vos suiveurs re\u00E7oivent votre offre, les autres membres peuvent <br/>la voir sur votre profil et dans les offres publiques<br/>",
	HP_NEWS_CONFIDENTIELLE:"<strong>confidentielle</strong> : vos suiveurs re\u00E7oivent votre nouvelle, les autres membres ne peuvent <br/>pas la voir",
	HP_DEAL_PUBLIC:"<strong>publique</strong> : vos suiveurs re\u00E7oivent votre proposition, les autres membres peuvent<br/> la voir et elle est index\u00e9e dans les moteurs (ex: google)<br/>",
	HP_DEAL_INTERNE:"<strong>interne</strong> : vos suiveurs re\u00E7oivent votre proposition, les autres membres peuvent la voir<br/>",
	HP_DEAL_CONFIDENTIELLE:"<strong>confidentielle</strong> : seuls vos suiveurs re\u00E7oivent votre proposition<br/>",
	CALLBACK_NOT_AVAILABLE:"D\u00E9sol\u00E9 personne n\u2019est disponible",
	CALLBACK_CHOOSE_TEL:"Choisissez le t\u00E9l\u00E9phone sur lequel vous voulez \u00eatre rappel\u00E9 :",
	HP_NEWS_STATIC_TEXT:"posez une question, diffusez un bon plan, passez une annonce",
	HP_TITLE_STATIC_TEXT:"\u00E9change de lien, \u00E9change de mails, offre commerciale ...",
	HP_SUMMARY_STATIC_TEXT:"expliquez votre proposition",
	FRONTPAGE_TEMPLATE_EMAIL:"saisissez votre e-mail",
	FRONTPAGE_TEMPLATE_SECTEUR:"choisissez un secteur",
	AJOUTER_TITRE: "Inviter une soci\u00E9t\u00E9 \u00e0 rejoindre Ecommerce United",
	AJOUTER_MESSAGE: " n\u2019est pas encore inscrit, pour l\u2019inviter dans Ecommerce United <br/>veuillez adresser votre demande directement \u00E0 la personne que vous connaissez :",
	AJOUTER_A_MESSAGE: "e-mail",
	AJOUTER_SUJET_TEXT: " vous invite sur Ecommerce United",
	AJOUTER_MESSAGE_TEXT: "Bonjour, \n\nJe souhaite vous inviter \u00E0 rejoindre Ecommerce United, \nle premier r\u00E9seau social de l\u2019e-commerce, \n\nCordialement, \n\n",
	AJOUTER_MAIL_NULL: "Veuillez ajouter un email pour envoyer l\u2019invitation",
	NEWS_COMMENTAIRE: "Effacer cette nouvelle et ses commentaires ?",
	HP_ERROR_TYPE_PARTENARIAT: "veuillez s\u00E9lectionner un type d\u2019offre",
	HIGHCHART_ZOOM:"Initialiser le zoom",
	HIGHCHART_BUDGET_0_A_50:"0 \u00E0 500 \u20ac ht",
	HIGHCHART_BUDGET_500_A_1000:"500 \u00E0 1000 \u20ac ht",
	HIGHCHART_BUDGET_1000_A_2500:"1000 \u00E0 2500 \u20ac ht",
	HIGHCHART_BUDGET_2500_A_5000:"2500 \u00E0 5000 \u20ac ht",
	HIGHCHART_BUDGET_5000:"plus de 5000 \u20ac ht",
	HIGHCHART_MOYENNE:"Moyenne",
	HIGHCHART_BUDGET_DE:"budget de ",
	HIGHCHART_HISTORIQUE_7_JOURS:"Historiques des 7 derniers jours",
	INVITATION_SOCIETE_MESSAGE1:"vous invite sur Ecommerce United",
	INVITATION_SOCIETE_MESSAGE2:"Bonjour,",
	INVITATION_SOCIETE_MESSAGE3:"J\u2019aimerais vous inviter \u00e0 rejoindre Ecommerce United sur",
	INVITATION_SOCIETE_MESSAGE4:"le premier r\u00E9seau social e-commerce,",
	INVITATION_SOCIETE_MESSAGE5:"Cordialement,",
	INVITATION_SOCIETE_MESSAGE_ERROR:"Veuillez saisir un email valide",
	INVITATION_SOCIETE_EMAIL_MESSAGE:"email de la personne que vous souhaitez inviter",
	FEEDBACK_DETAIL_LENGTH:"L'explication de votre recommandation doit contenir moins de 500 caracteres svp",
	FEEDBACK_DETAIL_EMPTY:"L'explication de votre recommandation ne doit pas \u00eatre vide",
	FEEDBACK_TITLE_EMPTY:"Le titre de votre recommandation ne doit pas \u00eatre vide",
	DEMANDE_AVIS_MAIL_SUJET:"demande votre recommandation",
	DEMANDE_AVIS_MAIL_CONTENT1:"Bonjour, \n\nJe vous serais reconnaisant de bien vouloir recommander ma soci\u00E9t\u00E9, pour cela je vous propose de suivre le lien suivant et de cliquer sur \u0022recommander\u0022",
	DEMANDE_AVIS_MAIL_CONTENT2:"Je vous remercie, \n\nCordialement, \n\n",
	DEMANDE_AVIS_EXTERNAL_MAIL_CONTENT1:"Bonjour, \n\nJe vous serais reconnaisant de bien vouloir recommander ma soci\u00E9t\u00E9, pour cela je vous propose de rendre sur le site Ecommerce United,",
	DEMANDE_AVIS_EXTERNAL_MAIL_CONTENT2:"Voici la page de ma soci\u00E9t\u00E9",
	PUSH_DEAL_OPTION_UNSELECTED: "Veuillez saisir une offre",
	SEE_ALL_SUBSCRIPTION: ">> voir les services premium",
	CLOSE: ">> Fermer",
	EXEMPLE:"exemple: www.societe.fr, www.monpartenaire.fr",
	CLOSE_DEAL_PROPOSAL: "Etes-vous s\u00FBr de vouloir fermer cette offre ?",
	HOMEPAGE_SEARCH:"rechercher",
	INVITEMAIL_TEXT:"Joindre un mot \u00E0 votre invitation \u00E0 la soci\u00E9t\u00E9",
	DEAL_SEND_MESSAGE:"envoyer un message au cr\u00E9ateur de l\u2019appel d\u2019offre",
	DEAL_REPLY_NOUVELLE:"r\u00E9pondre \u00e0 cette nouvelle",
	DEAL_REPLY:"Envoyer un message au cr\u00E9ateur de l\u2019offre",
	DEAL_BROADCAST_ONE_FOLLOWER:"diffuser \u00e0 mon suiveur",
	DEAL_REPLY:"Envoyer un message au cr\u00E9ateur de l\u2019offre",
	DEAL_PARTICIPATE_REPLY:"Envoyer un message au cr\u00E9ateur de cette offre",
	SOCIETE_GROUPE_EXEMPLE:"exemple: www.societe.fr, www.mon-groupe.com",
	SOCIETE_REFERENCE_EXEMPLE:"exemple: www.societe.fr, www.monpartenaire.fr",
	FEEDBACK_EXEMPLE:"exemple: www.site.com, www.partenaire.com, www.client.com",
	AJOUTERCONTACTS_EXEMPLE:"exemple: patrick@societe.fr, paul@monpartenaire.fr",
	REGISTER_WRONG_EMAIL:"Merci de saisir un e-mail valide",
	REGISTER_NULL_EMAIL:"saisissez votre e-mail",
	REGISTER_WRONG_SECTEUR:"Merci de saisie un secteur valide",
	USER_FREEMIUM_CANNOT_INVITE:"Pour inviter vos contacts, nous vous invitons \u00e0 modifier votre abonnement",
	USER_FREEMIUM_CANNOT_MAIL:"Pour envoyer un message, nous vous invitons \u00e0 modifier votre abonnement",
	USER_FREEMIUM_CANNOT_REPLY_DEAL:"Pour r\u00E9pondre \u00e0 cette offre, nous vous invitons \u00e0 modifier votre abonnement",
	USER_FREEMIUM_CANNOT_PARTICIPATE_DEAL:"Pour participer \u00e0 cette \u00E9v\u00E9nement, nous vous invitons \u00e0 modifier votre abonnement",
	REPONDRE_PUBLIQUEMENT:"r\u00E9pondre publiquement",
	TEXT_REPONSES:"r\u00E9ponses"
};

INSCRIPTION_TEXT = {
	NOM_REQUIRED : "Veuillez entrer votre nom de famille",
	NOM_MINLENGTH: "Votre nom de famille doit avoir au moins 2 caracteres",
	
	PRENOM_REQUIRED: "Veuillez entrer votre pr\u00E9nom",
	PRENOM_MINLENGTH: "Votre pr\u00E9nom doit avoir au moins 2 caracteres",
	
	FONCTION_REQUIRED: "Veuillez entrer votre fonction",
	FONCTION_MINLENGTH: "Votre fonction doit avoir au moins 2 caracteres",

	MDP_REQUIRED: "Veuillez entrer votre mot de passe",
	MDP_MINLENGTH: "Votre mot de passe doit avoir au moins 7 caracteres",

	CONFIRMMDP_REQUIRED: "Veuillez confirmer votre mot de passe ",
	CONFIRMMDP_MINLENGTH: "Votre mot de passe doit avoir au moins 7 caracteres",
	CONFIRMMDP_EQUAL: "Veuillez entrer le m\u00EAme mot de passe",

	CHOSEN_ACTIVITE: "Veuillez choisir une activit\u00E9",
	
	TYPE_METIER: "Veuillez choisr un type de membre",

	NOMSITE_REQUIRED: "Veuillez entrer le nom de votre site",
	NOMSITE_MINLENGTH: "Le nom de votre site doit avoir au moins 2 caracteres",
	
	URL_REQUIRED: "Veuillez entrer l\u2019URL de votre site",
	URL: "Votre URL est invalide",
	
	ACCEPTCOND_REQUIRED: "Veuillez cocher les CGU",
	
	DESCRIPTION_MAXLENGTH: "La description ne doit pas depasser 140 caract\u00E8res",
	DESCRIPTION_MINLENGTH: "Le description de votre site doit avoir au moins 2 caract\u00E8res",
	
	INTEREST_MINLENGTH: "Les besoins doivent avoir au moins 2 caract\u00E8res",
	INTEREST_MAXLENGTH: "Vos besoins ne doivent pas depasser 1000 caract\u00E8res",
	
	TELEPHONE_MINLENGTH: "Votre num\u00E9ro de t\u00E9l\u00E9phone doit <br> avoir au moins 7 caract\u00E8res",
	TELEPHONE_MAXLENGTH: "Votre num\u00E9ro de t\u00E9l\u00E9phone doit <br> avoir au moins 15 caract\u00E8res",
	
	CODE_POSTAL_NUMBER_ONLY: "Valeurs num\u00E9riques svp",
	CODE_POSTAL_MAXLENGTH: "Votre code postal doit <br> avoir au moins 5 caract\u00E8res"

};
JS_MONTH_ENG = {
	JANUARY:"January",
	FEBRUARY:"February",
	MARCH:"March",
	APRIL:"April",
	MAY:"May",
	JUNE:"June",
	JULY:"July",
	AUGUST:"August",
	SEPTEMBER:"September",
	OCTOBER:"October",
	NOVEMBER:"November",
	DECEMBER:"December"
};

JS_MONTH_FR = {
	JANUARY:"Janvier",
	FEBRUARY:"F\u00E9vrier",
	MARCH:"Mars",
	APRIL:"Avril",
	MAY:"Mai",
	JUNE:"Juin",
	JULY:"Juillet",
	AUGUST:"Ao\u00fbt",
	SEPTEMBER:"Septembre",
	OCTOBER:"Octobre",
	NOVEMBER:"Novembre",
	DECEMBER:"D\u00E9cembre"
};


;

// equivalent of MailType.java 
MAIL_TYPE = {
	SIMPLEMAIL : 0,
    INVITATION : 1,
    WELCOME : 3,
    USER_NOWHITELIST_TOADMI : 4,
    USER_WHITELIST_TOADMIN : 5,
    SIMPLEMAIL_REPONSE : 6,
    SIMPLEMAILSOCIETE : 8,
    INVITATIONSOCIETE : 9,
    MODERATE_FOLLOWERS : 19,
    CALLBACK : 10,
    SUBSCRIPTION_TO_DEAL_PROPOSAL : 13,
    FORWARD_DEAL_PROPOSAL:15,
    SIMPLE_MESSAGE_TO_DEALAUTHOR:20,
    FEEDBACK_REQUEST:22,
    SIMPLE_MESSAGE_TO_DEALAUTHOR_REPONSE:23
}
;

/**
*
*  URL encode / decode
*  http://www.webtoolkit.info/
*
**/
 
var url = new function(){
 return {
	// public method for url encoding
	encode : function (string) {
		return escape(this._utf8_encode(string));
	},
 
	// public method for url decoding
	decode : function (string) {
		return this._utf8_decode(unescape(string));
	},
 
	// private method for UTF-8 encoding
	_utf8_encode : function (string) {
		string = string.replace(/\r\n/g,"\n");
		var utftext = "";
 
		for (var n = 0; n < string.length; n++) {
 
			var c = string.charCodeAt(n);
 
			if (c < 128) {
				utftext += String.fromCharCode(c);
			}
			else if((c > 127) && (c < 2048)) {
				utftext += String.fromCharCode((c >> 6) | 192);
				utftext += String.fromCharCode((c & 63) | 128);
			}
			else {
				utftext += String.fromCharCode((c >> 12) | 224);
				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
				utftext += String.fromCharCode((c & 63) | 128);
			}
 
		}
 
		return utftext;
	},
 
	// private method for UTF-8 decoding
	_utf8_decode : function (utftext) {
		var string = "";
		var i = 0;
		var c = c1 = c2 = 0;
 
		while ( i < utftext.length ) {
 
			c = utftext.charCodeAt(i);
 
			if (c < 128) {
				string += String.fromCharCode(c);
				i++;
			}
			else if((c > 191) && (c < 224)) {
				c2 = utftext.charCodeAt(i+1);
				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
				i += 2;
			}
			else {
				c2 = utftext.charCodeAt(i+1);
				c3 = utftext.charCodeAt(i+2);
				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}
 
		}
 
		return string;
	}
 }
}
;

var logindestinataire;
var mailtype;

var innermailcode='<table cellpadding="10" cellspacing="10">'+
		'<tr><th colspan="2" id="maillabel"></th></tr>'+
		'<tr><td colspan="2" id="mailresponsemail" style="color:red"></td></tr>'+
		'<tr><th>'+EU_TEXT.A+':</th><td id="maildestinataire"><input type="text" name="destinataire" id="destinataire"  style="width:400px"/></td></tr>'+
		'<tr><th>'+EU_TEXT.SUJET+':</th><td id="mailsujet"><input type="text" name="sujet" id="sujet"  maxlength="200"  style="width:400px"/></td></tr>'+
		'<tr><th valign="top">'+EU_TEXT.MESSAGE+':</th><td><textarea name="message" id="message" rows="15"  style="width:400px"></textarea></td></tr>'+
		'<tr><th></th><td><input style="width:100px;float:right" type="button" value="'+EU_TEXT.ENVOYER+'" class="button" style="float:right" onclick="mail.sendMail();"/></td></tr>'+
	'</table>';


var mail = new function(){

	return {
		//envoyer un nouveau message
		newMail: function (){
			displayThickbox(EU_TEXT.TITRE,innermailcode,500,350);
			mailtype=MAIL_TYPE.SIMPLEMAIL; // assuming that utilisateurtoken parameter in eu.addressbooktag is true (i.e. sending mail to a user, not a society)
		},
		
		//mail response - whether sent correctly or exception occured		
		mailResponse: function (responseXML){
			var xmlDoc = responseXML.documentElement;
			if (xmlDoc !=null){
				var xRows = xmlDoc.getElementsByTagName('error');
				if (xRows[0].firstChild==null){//mail sent
					tb_remove();
					$.jGrowl(EU_TEXT.MAIL_SENT, { life: 1000 });// display message - inform that mail is sent
				}else{
//					tb_remove();
//					$.jGrowl(url.decode(xRows[0].firstChild.nodeValue).ReplaceAll('+',' '));
					document.getElementById('mailresponsemail').innerHTML=xRows[0].firstChild.nodeValue; // display message - error occured
				}
					
			}
		
		},
		sendMail:function (){
				document.getElementById('mailresponsemail').innerHTML='';
				var sujet = document.getElementById('sujet').value;
				var message = document.getElementById('message').value;
				var destinataire = logindestinataire;

				var params = 'sujet='+url.encode(sujet)+'&text='+url.encode(message)+'&mail_type='+mailtype;

				if (mailtype==MAIL_TYPE.SIMPLEMAILSOCIETE)
					params+='&loginRecipientCompany='+destinataire;
				else 
					params+='&loginRecipient='+destinataire;
					
				if (mailtype==MAIL_TYPE.SIMPLEMAIL_REPONSE || mailtype==MAIL_TYPE.SIMPLE_MESSAGE_TO_DEALAUTHOR_REPONSE)	//changed for trac#1012
					params+='&miniUUID='+mailReply.getMiniUUID();

				if (destinataire!=null && destinataire.length>0){
					mailfeedback.doMailFeedback('mailresponsemail',false,'/Mail_Servlet',params);
				}

		}
	
	}
	
	
}
;
var mailReply = new function() {
	var miniUUID;
	
	return {
		mailToReply: function (){ // reply mail simple
			
			var sujet = mailReply.decodeXSS(Encoder.htmlDecode(document.seeMailActionForm.subject.value));
			var expediteur = document.seeMailActionForm.mailReceivedFrom.value;
			var expediteurSociete = document.seeMailActionForm.mailReceivedFromCompany.value;

			var destinataire = document.seeMailActionForm.mailReceivedFromForReply.value;

			miniUUID = document.seeMailActionForm.UUID.value;
			var destinatairelogin = document.seeMailActionForm.mailReceivedFromLogin.value;

			var message = mailReply.decodeXSS(Encoder.htmlDecode(document.seeMailActionForm.originalText.value)); //convert all XSS to tags
			message = message.ReplaceAll("<br/>","\n");

			
			var datereceived = document.seeMailActionForm.date.value;
			
			var mailreceivedContent = '\n\n----- Le '+datereceived+' '+expediteur+' de '+expediteurSociete+' a \u00E9crit:\n\n'+message;
		      
			displayThickbox(EU_TEXT.TITRE,innermailcode,600,350);
			
			//set login & nom
			document.getElementById('destinataire').value=destinataire; //repondre a l'expediteur
			document.getElementById('destinataire').disabled="disabled";
			document.getElementById('sujet').value=sujet;
			document.getElementById('message').value=mailreceivedContent;
			document.getElementById('mailresponsemail').innerHTML='';
			document.getElementById('message').focus();
			
			logindestinataire=destinatairelogin;
			mailtype=MAIL_TYPE.SIMPLEMAIL_REPONSE;//mail simple
			
			
			
		},
		//trac#1012
		mailDealToReply:function(){
			var sujet = mailReply.decodeXSS(Encoder.htmlDecode(document.seeMailActionForm.subject.value));
			var expediteur = document.seeMailActionForm.mailReceivedFrom.value;
			var expediteurSociete = document.seeMailActionForm.mailReceivedFromCompany.value;

			var destinataire = document.seeMailActionForm.mailReceivedFromForReply.value;

			miniUUID = document.seeMailActionForm.UUID.value;
			var destinatairelogin = document.seeMailActionForm.mailReceivedFromLogin.value;

			var message = mailReply.decodeXSS(Encoder.htmlDecode(document.seeMailActionForm.originalText.value)); //convert all XSS to tags
			message = message.ReplaceAll("<br/>","\n");

			
			var datereceived = document.seeMailActionForm.date.value;
			
			var mailreceivedContent = '\n\n----- Le '+datereceived+' '+expediteur+' de '+expediteurSociete+' a \u00E9crit:\n\n'+message;
		      
			displayThickbox(EU_TEXT.TITRE,innermailcode,600,350);
			
			//set login & nom
			document.getElementById('destinataire').value=destinataire; //repondre a l'expediteur
			document.getElementById('destinataire').disabled="disabled";
			document.getElementById('sujet').value=sujet;
			document.getElementById('message').value=mailreceivedContent;
			document.getElementById('mailresponsemail').innerHTML='';
			document.getElementById('message').focus();
			
			logindestinataire=destinatairelogin;
			mailtype=MAIL_TYPE.SIMPLE_MESSAGE_TO_DEALAUTHOR_REPONSE;
			
			
			
		},
		
		getMiniUUID: function (){
			return miniUUID;
			
		},
		
		decodeXSS:function(textToConvert){
			textToConvert=textToConvert.ReplaceAll("&lt;", "<").ReplaceAll("&gt;", ">");
            textToConvert=textToConvert.ReplaceAll("&#60;", "<").ReplaceAll("&#62;", ">");
            textToConvert=textToConvert.ReplaceAll("&#40;", "\\(").ReplaceAll("&#41;", "\\)");
            textToConvert=textToConvert.ReplaceAll("&#39;", "'");
            
            
            return convertHTMLToJSTxt(textToConvert); //convert all tags to JS text
		}
	}
}
;

var mailToTag = new function() {
	
	
	return {
			mailToUser: function (mailType, utilisateurLogin, utilisateurNom, title){ //used in UserTag
			displayThickbox(title,innermailcode,500,400);
			
			//set login & nom
			document.getElementById('destinataire').value=utilisateurNom;
			document.getElementById('destinataire').disabled=true;
			document.getElementById('sujet').value='';
			document.getElementById('message').value='';
			document.getElementById('mailresponsemail').innerHTML='';
			
			logindestinataire=utilisateurLogin;
			mailtype=mailType;
			     
		},
		
		mailToCompany: function (subject,societelogin,societenom,adminName){ //used in CompanyAction
		

			displayThickbox(EU_TEXT.TITRE,innermailcode,500,400);
			//set login & nom
			document.getElementById('destinataire').value=adminName;
			document.getElementById('destinataire').disabled=true;
			document.getElementById('sujet').value=subject;
			document.getElementById('message').value='';
			document.getElementById('mailresponsemail').innerHTML='';
			document.getElementById('maillabel').innerHTML=EU_TEXT.MAIL_TO_COMPANY+societenom+'<br/>';
			
			logindestinataire=societelogin;
			mailtype=MAIL_TYPE.SIMPLEMAILSOCIETE;//mail simple to societe
		}		
	}
	
}
;
var invitemail = new function() {

	var logindestinataire_invitemail;
	var mailtype;
	var feedbackId;
	
	var invitemailcode=
		'<table cellpadding="2" cellspacing="2">'+
			'<tr><td colspan="2" id="invitemaillabel"></td></tr>'+
			'<tr><td colspan="2" id="mailresponse" style="color:red"></td></tr>'+
			'<tr><th valign="top">'+EU_TEXT.SUJET+':</th><td><input type="text" name="sujet" id="sujet"  style="width: 400px" maxlength="200"/></td></tr>'+
			'<tr><th valign="top">'+EU_TEXT.MESSAGE+':</th><td><textarea name="message" id="message" style="width: 400px" rows="12" cols="50"></textarea></td></tr>'+
			'<tr><th></th><td><br/>'+'<input type="button" style="width:100px;float:right" value="'+EU_TEXT.ENVOYER+'" class="button" style="float:right" onclick="invitemail.sendInvitationMail();"/></td></tr>'+
		'</table>';
		
	var inviteMailCodeAbonnement= 
	//text +  a button
			'<table cellpadding="2" cellspacing="2">'+
			'<tr><td colspan="2" id="labelText"></td></tr>'+
			'<tr><td colspan="2">&nbsp;</td></tr>'+
			'<tr><th></th><td><br/>'+'<a id="abonnementButton" style="color:#FFFFFF;" href="/Subscription.do?dispatch=view">'+EU_TEXT.SEE_ALL_SUBSCRIPTION+
            		'</a></td></tr>'+
		'</table>';
		

	return {
		inviteMailCompany: function (societelogin,nom,feedbackid,companyNom){
			logindestinataire_invitemail=societelogin;
			displayThickbox(EU_TEXT.INVITATION_TITRE,invitemailcode,500,350);
		
			document.getElementById('invitemaillabel').innerHTML='<h4>'+nom+'</h4><br/>';
			document.getElementById('message').value=EU_TEXT.INVITATION_MESSAGE_TEXT + companyNom;
			document.getElementById('sujet').value=companyNom + EU_TEXT.INVITATION_SUBJECT;
			document.getElementById('mailresponse').innerHTML='';
			mailtype=MAIL_TYPE.INVITATIONSOCIETE;
			feedbackId=feedbackid;		
		},
		
		displayMessageLimitsReached: function(title,text, type){			
			displayThickbox(title,inviteMailCodeAbonnement,450,250);
			
			document.getElementById('labelText').innerHTML=text;
			
			if (type == '4'){
				document.getElementById('abonnementButton').innerHTML=EU_TEXT.CLOSE;
				document.getElementsByName('abonnementButton').width = '125px';
			}
			
		},
		
		sendInvitationMail:function(){
			document.getElementById('mailresponse').innerHTML='';
			var message = document.getElementById('message').value;
			var sujet = document.getElementById('sujet').value;
			var params = 'text='+message+'&mail_type='+mailtype+'&loginRecipientCompany='+logindestinataire_invitemail+'&sujet='+sujet;
			
			if (logindestinataire_invitemail!=null && logindestinataire_invitemail.length>0){
				mailfeedback.doMailFeedback(feedbackId,true,'/Invitation_Servlet',params);
			}
				
			
		},
		
		resetTextbox:function(){
			if(document.getElementById('inviteCompany_destinataire').value==EU_TEXT.INVITATION_SOCIETE_EMAIL_MESSAGE){
				document.getElementById('inviteCompany_destinataire').value='';				
			}	
		},

		
		loadmailinvitation:function (loggedUserName, urlSite, urlEcommerceUnited){
			document.getElementById('inviteCompanymailresponse').innerHTML='';
			document.getElementById('inviteCompany_destinataire').value=EU_TEXT.INVITATION_SOCIETE_EMAIL_MESSAGE;
			document.getElementById('inviteCompany_urlSite').innerHTML=urlSite;
			document.getElementById('inviteCompany_sujet').value=loggedUserName + ' ' + EU_TEXT.INVITATION_SOCIETE_MESSAGE1;
			document.getElementById('inviteCompany_message').innerHTML=EU_TEXT.INVITATION_SOCIETE_MESSAGE2 + '\n\n' + 
												EU_TEXT.INVITATION_SOCIETE_MESSAGE3+'\n\n'+urlEcommerceUnited+'\n\n'+
												EU_TEXT.INVITATION_SOCIETE_MESSAGE4+'\n\n'+
												EU_TEXT.INVITATION_SOCIETE_MESSAGE5+'\n\n'+loggedUserName;
			
		},
		
		echeck:function(str) {

		var at="@"
		var dot="."
		var lat=str.indexOf(at)
		var lstr=str.length
		var ldot=str.indexOf(dot)
		if (str.indexOf(at)==-1){
		   return false
		}

		if (str.indexOf(at)==-1 || str.indexOf(at)==0 || str.indexOf(at)==lstr){
		   return false
		}

		if (str.indexOf(dot)==-1 || str.indexOf(dot)==0 || str.indexOf(dot)==lstr){
		    return false
		}

		 if (str.indexOf(at,(lat+1))!=-1){
		    return false
		 }

		 if (str.substring(lat-1,lat)==dot || str.substring(lat+1,lat+2)==dot){
		    return false
		 }

		 if (str.indexOf(dot,(lat+2))==-1){
		    return false
		 }
		
		 if (str.indexOf(" ")!=-1){
		    return false
		 }

 		 return true					
	},
	
		sendmailinvitation:function (){
			
			var dest = document.getElementById('inviteCompany_destinataire').value;	
			var sujet= url.encode(document.getElementById('inviteCompany_sujet').value);
			var message =  url.encode(document.getElementById('inviteCompany_message').value);//method getSource found in ecomutd.js
			var text=EU_TEXT.INVITATION_SOCIETE_MESSAGE_ERROR;
			var isfeedback=false;
			var params = 'sujet='+sujet+'&text='+message+'&externalRecipient='+dest+'&isFeedback='+isfeedback;
			if (dest.length > 0){
				if (invitemail.echeck(dest)==false){
					document.getElementById('inviteCompanymailresponse').innerHTML=text;
				}else
					mailfeedback.doMailFeedback('inviteCompanymailresponse',false,'/InvitationNewExternalCompany_Servlet',params);
			}else{				
				if(dest==null || (dest=="")){
					document.getElementById('inviteCompanymailresponse').innerHTML=text;
				}
			}
			
		},
		
		loadmailinvitationuser:function (loggedUserName, email, urlEcommerceUnited){
			document.getElementById('inviteCompanymailresponse').innerHTML='';
			document.getElementById('inviteCompany_destinataire').value=email;
			document.getElementById('inviteCompany_urlSite').innerHTML=email;
			document.getElementById('inviteCompany_sujet').value=loggedUserName + ' ' + EU_TEXT.INVITATION_SOCIETE_MESSAGE1;
			document.getElementById('inviteCompany_message').innerHTML=EU_TEXT.INVITATION_SOCIETE_MESSAGE2 + '\n\n' + 
												EU_TEXT.INVITATION_SOCIETE_MESSAGE3+'\n\n'+urlEcommerceUnited+'\n\n'+
												EU_TEXT.INVITATION_SOCIETE_MESSAGE4+'\n\n'+
												EU_TEXT.INVITATION_SOCIETE_MESSAGE5+'\n\n'+loggedUserName;
			
		}
		
	}	
	
	
	
}

;

/*
 * File:        jquery.dataTables.js
 * Version:     1.5.2
 * CVS:         $Id$
 * Description: Paginate, search and sort HTML tables
 * Author:      Allan Jardine (www.sprymedia.co.uk)
 * Created:     28/3/2008
 * Modified:    $Date$ by $Author$
 * Language:    Javascript
 * License:     GPL v2 or BSD 3 point style
 * Project:     Mtaala
 * Contact:     allan.jardine@sprymedia.co.uk
 * 
 * Copyright 2008-2009 Allan Jardine, all rights reserved.
 *
 * This source file is free software, under either the GPL v2 license or a
 * BSD style license, as supplied with this software.
 * 
 * This source file 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 license files for details.
 * 
 * For details pleease refer to: http://www.datatables.net
 */

/*
 * When considering jsLint, we need to allow eval() as it it is used for reading cookies and 
 * building the dynamic multi-column sort functions.
 */
/*jslint evil: true, undef: true, browser: true */
/*globals $, jQuery,_fnReadCookie,_fnProcessingDisplay,_fnDraw,_fnSort,_fnReDraw,_fnDetectType,_fnSortingClasses,_fnSettingsFromNode,_fnBuildSearchArray,_fnCalculateEnd,_fnFeatureHtmlProcessing,_fnFeatureHtmlPaginate,_fnFeatureHtmlInfo,_fnFeatureHtmlFilter,_fnFilter,_fnSaveState,_fnFilterColumn,_fnEscapeRegex,_fnFilterComplete,_fnFeatureHtmlLength,_fnGetDataMaster,_fnVisibleToColumnIndex,_fnDrawHead,_fnAddData,_fnGetTrNodes,_fnColumnIndexToVisible,_fnCreateCookie,_fnAddOptionsHtml,_fnMap,_fnClearTable,_fnDataToSearch,_fnReOrderIndex,_fnFilterCustom,_fnVisbleColumns,_fnAjaxUpdate,_fnAjaxUpdateDraw,_fnColumnOrdering,fnGetMaxLenString*/

(function($) {
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
	 * DataTables variables
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	
	/*
	 * Variable: dataTableSettings
	 * Purpose:  Store the settings for each dataTables instance
	 * Scope:    jQuery.fn
	 */
	$.fn.dataTableSettings = [];
	
	/*
	 * Variable: dataTableExt
	 * Purpose:  Container for customisable parts of DataTables
	 * Scope:    jQuery.fn
	 */
	$.fn.dataTableExt = {};
	var _oExt = $.fn.dataTableExt; /* Short reference for fast internal lookup */
	
	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
	 * DataTables extensible objects
	 * 
	 * The _oExt object is used to provide an area where user dfined plugins can be 
	 * added to DataTables. The following properties of the object are used:
	 *   oApi - Plug-in API functions
	 *   aTypes - Auto-detection of types
	 *   oSort - Sorting functions used by DataTables (based on the type)
	 *   oPagination - Pagination functions for different input styles
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	
	/*
	 * Variable: sVersion
	 * Purpose:  Version string for plug-ins to check compatibility
	 * Scope:    jQuery.fn.dataTableExt
	 */
	_oExt.sVersion = "1.5.2";
	
	/*
	 * Variable: iApiIndex
	 * Purpose:  Index for what 'this' index API functions should use
	 * Scope:    jQuery.fn.dataTableExt
	 */
	_oExt.iApiIndex = 0;
	
	/*
	 * Variable: oApi
	 * Purpose:  Container for plugin API functions
	 * Scope:    jQuery.fn.dataTableExt
	 */
	_oExt.oApi = { };
	
	/*
	 * Variable: aFiltering
	 * Purpose:  Container for plugin filtering functions
	 * Scope:    jQuery.fn.dataTableExt
	 */
	_oExt.afnFiltering = [ ];
	
	/*
	 * Variable: aoFeatures
	 * Purpose:  Container for plugin function functions
	 * Scope:    jQuery.fn.dataTableExt
	 * Notes:    Array of objects with the following parameters:
	 *   fnInit: Function for initialisation of Feature. Takes oSettings and returns node
	 *   cFeature: Character that will be matched in sDom - case sensitive
	 *   sFeature: Feature name - just for completeness :-)
	 */
	_oExt.aoFeatures = [ ];
	
	/*
	 * Variable: ofnSearch
	 * Purpose:  Container for custom filtering functions
	 * Scope:    jQuery.fn.dataTableExt
	 * Notes:    This is an object (the name should match the type) for custom filtering function,
	 *   which can be used for live DOM checking or formatted text filtering
	 */
	_oExt.ofnSearch = { };
	
	/*
	 * Variable: oStdClasses
	 * Purpose:  Storage for the various classes that DataTables uses
	 * Scope:    jQuery.fn.dataTableExt
	 */
	_oExt.oStdClasses = {
		/* Two buttons buttons */
		"sPagePrevEnabled": "paginate_enabled_previous",
		"sPagePrevDisabled": "paginate_disabled_previous",
		"sPageNextEnabled": "paginate_enabled_next",
		"sPageNextDisabled": "paginate_disabled_next",
		"sPageJUINext": "",
		"sPageJUIPrev": "",
		
		/* Full numbers paging buttons */
		"sPageButton": "paginate_button",
		"sPageButtonActive": "paginate_active",
		"sPageButtonStaticActive": "paginate_button",
		"sPageFirst": "first",
		"sPagePrevious": "previous",
		"sPageNext": "next",
		"sPageLast": "last",
		
		/* Stripping classes */
		"sStripOdd": "odd",
		"sStripEven": "even",
		
		/* Empty row */
		"sRowEmpty": "dataTables_empty",
		
		/* Features */
		"sWrapper": "dataTables_wrapper",
		"sFilter": "dataTables_filter",
		"sInfo": "dataTables_info",
		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
		"sLength": "dataTables_length",
		"sProcessing": "dataTables_processing",
		
		/* Sorting */
		"sSortAsc": "sorting_asc",
		"sSortDesc": "sorting_desc",
		"sSortable": "sorting",
		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
		"sSortJUIAsc": "",
		"sSortJUIDesc": "",
		"sSortJUI": ""
	};
	
	/*
	 * Variable: oJUIClasses
	 * Purpose:  Storage for the various classes that DataTables uses - jQuery UI suitable
	 * Scope:    jQuery.fn.dataTableExt
	 */
	_oExt.oJUIClasses = {
		/* Two buttons buttons */
		"sPagePrevEnabled": "fg-button ui-state-default ui-corner-left",
		"sPagePrevDisabled": "fg-button ui-state-default ui-corner-left ui-state-disabled",
		"sPageNextEnabled": "fg-button ui-state-default ui-corner-right",
		"sPageNextDisabled": "fg-button ui-state-default ui-corner-right ui-state-disabled",
		"sPageJUINext": "ui-icon ui-icon-circle-arrow-e",
		"sPageJUIPrev": "ui-icon ui-icon-circle-arrow-w",
		
		/* Full numbers paging buttons */
		"sPageButton": "fg-button ui-state-default",
		"sPageButtonActive": "fg-button ui-state-default ui-state-disabled",
		"sPageButtonStaticActive": "fg-button ui-state-default ui-state-disabled",
		"sPageFirst": "first ui-corner-tl ui-corner-bl",
		"sPagePrevious": "previous",
		"sPageNext": "next",
		"sPageLast": "last ui-corner-tr ui-corner-br",
		
		/* Stripping classes */
		"sStripOdd": "odd",
		"sStripEven": "even",
		
		/* Empty row */
		"sRowEmpty": "dataTables_empty",
		
		/* Features */
		"sWrapper": "dataTables_wrapper",
		"sFilter": "dataTables_filter",
		"sInfo": "dataTables_info",
		"sPaging": "dataTables_paginate fg-buttonset fg-buttonset-multi paging_", /* Note that the type is postfixed */
		"sLength": "dataTables_length",
		"sProcessing": "dataTables_processing",
		
		/* Sorting */
		"sSortAsc": "ui-state-default",
		"sSortDesc": "ui-state-default",
		"sSortable": "ui-state-default",
		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
		"sSortJUIAsc": "css_right ui-icon ui-icon-triangle-1-n",
		"sSortJUIDesc": "css_right ui-icon ui-icon-triangle-1-s",
		"sSortJUI": "css_right ui-icon ui-icon-triangle-2-n-s"
	};
	
	/*
	 * Variable: oPagination
	 * Purpose:  Container for the various type of pagination that dataTables supports
	 * Scope:    jQuery.fn.dataTableExt
	 */
	_oExt.oPagination = {
		/*
		 * Variable: two_button
		 * Purpose:  Standard two button (forward/back) pagination
	 	 * Scope:    jQuery.fn.dataTableExt.oPagination
		 */
		"two_button": {
			/*
			 * Function: oPagination.two_button.fnInit
			 * Purpose:  Initalise dom elements required for pagination with forward/back buttons only
			 * Returns:  -
	 		 * Inputs:   object:oSettings - dataTables settings object
			 *           function:fnCallbackDraw - draw function which must be called on update
			 */
			"fnInit": function ( oSettings, fnCallbackDraw )
			{
				var nPaging = oSettings.anFeatures.p;
				
				/* Store the next and previous elements in the oSettings object as they can be very
				 * usful for automation - particularly testing
				 */
				if ( !oSettings.bJUI )
				{
					oSettings.nPrevious = document.createElement( 'div' );
					oSettings.nNext = document.createElement( 'div' );
				}
				else
				{
					oSettings.nPrevious = document.createElement( 'a' );
					oSettings.nNext = document.createElement( 'a' );
					
					var nNextInner = document.createElement('span');
					nNextInner.className = oSettings.oClasses.sPageJUINext;
					oSettings.nNext.appendChild( nNextInner );
					
					var nPreviousInner = document.createElement('span');
					nPreviousInner.className = oSettings.oClasses.sPageJUIPrev;
					oSettings.nPrevious.appendChild( nPreviousInner );
				}
				
				if ( oSettings.sTableId !== '' )
				{
					nPaging.setAttribute( 'id', oSettings.sTableId+'_paginate' );
					oSettings.nPrevious.setAttribute( 'id', oSettings.sTableId+'_previous' );
					oSettings.nNext.setAttribute( 'id', oSettings.sTableId+'_next' );
				}
				
				oSettings.nPrevious.className = oSettings.oClasses.sPagePrevDisabled;
				oSettings.nNext.className = oSettings.oClasses.sPageNextDisabled;
				
				oSettings.nPrevious.title = oSettings.oLanguage.oPaginate.sPrevious;
				oSettings.nNext.title = oSettings.oLanguage.oPaginate.sNext;
				
				nPaging.appendChild( oSettings.nPrevious );
				nPaging.appendChild( oSettings.nNext );
				$(nPaging).insertAfter( oSettings.nTable );
				
				$(oSettings.nPrevious).click( function() {
					oSettings._iDisplayStart -= oSettings._iDisplayLength;
					
					/* Correct for underrun */
					if ( oSettings._iDisplayStart < 0 )
					{
					  oSettings._iDisplayStart = 0;
					}
					
					fnCallbackDraw( oSettings );
				} );
				
				$(oSettings.nNext).click( function() {
					/* Make sure we are not over running the display array */
					if ( oSettings._iDisplayStart + oSettings._iDisplayLength < oSettings.fnRecordsDisplay() )
					{
						oSettings._iDisplayStart += oSettings._iDisplayLength;
					}
					
					fnCallbackDraw( oSettings );
				} );
				
				/* Take the brutal approach to cancelling text selection */
				$(oSettings.nPrevious).bind( 'selectstart', function () { return false; } );
				$(oSettings.nNext).bind( 'selectstart', function () { return false; } );
			},
			
			/*
			 * Function: oPagination.two_button.fnUpdate
			 * Purpose:  Update the two button pagination at the end of the draw
			 * Returns:  -
	 		 * Inputs:   object:oSettings - dataTables settings object
			 *           function:fnCallbackDraw - draw function which must be called on update
			 */
			"fnUpdate": function ( oSettings, fnCallbackDraw )
			{
				if ( !oSettings.anFeatures.p )
				{
					return;
				}
				
				oSettings.nPrevious.className = 
					( oSettings._iDisplayStart === 0 ) ? 
					oSettings.oClasses.sPagePrevDisabled : oSettings.oClasses.sPagePrevEnabled;
				
				oSettings.nNext.className = 
					( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) ? 
					oSettings.oClasses.sPageNextDisabled : oSettings.oClasses.sPageNextEnabled;
			}
		},
		
		
		/*
		 * Variable: iFullNumbersShowPages
		 * Purpose:  Change the number of pages which can be seen
	 	 * Scope:    jQuery.fn.dataTableExt.oPagination
		 */
		"iFullNumbersShowPages": 5,
		
		/*
		 * Variable: full_numbers
		 * Purpose:  Full numbers pagination
	 	 * Scope:    jQuery.fn.dataTableExt.oPagination
		 */
		"full_numbers": {
			/*
			 * Function: oPagination.full_numbers.fnInit
			 * Purpose:  Initalise dom elements required for pagination with a list of the pages
			 * Returns:  -
	 		 * Inputs:   object:oSettings - dataTables settings object
			 *           function:fnCallbackDraw - draw function which must be called on update
			 */
			"fnInit": function ( oSettings, fnCallbackDraw )
			{
				var nPaging = oSettings.anFeatures.p;
				var nFirst = document.createElement( 'span' );
				var nPrevious = document.createElement( 'span' );
				var nList = document.createElement( 'span' );
				var nNext = document.createElement( 'span' );
				var nLast = document.createElement( 'span' );
				
				nFirst.innerHTML = oSettings.oLanguage.oPaginate.sFirst;
				nPrevious.innerHTML = oSettings.oLanguage.oPaginate.sPrevious;
				nNext.innerHTML = oSettings.oLanguage.oPaginate.sNext;
				nLast.innerHTML = oSettings.oLanguage.oPaginate.sLast;
				
				var oClasses = oSettings.oClasses;
				nFirst.className = oClasses.sPageButton+" "+oClasses.sPageFirst;
				nPrevious.className = oClasses.sPageButton+" "+oClasses.sPagePrevious;
				nNext.className= oClasses.sPageButton+" "+oClasses.sPageNext;
				nLast.className = oClasses.sPageButton+" "+oClasses.sPageLast;
				
				if ( oSettings.sTableId !== '' )
				{
					nPaging.setAttribute( 'id', oSettings.sTableId+'_paginate' );
					nFirst.setAttribute( 'id', oSettings.sTableId+'_first' );
					nPrevious.setAttribute( 'id', oSettings.sTableId+'_previous' );
					nNext.setAttribute( 'id', oSettings.sTableId+'_next' );
					nLast.setAttribute( 'id', oSettings.sTableId+'_last' );
				}
				
				nPaging.appendChild( nFirst );
				nPaging.appendChild( nPrevious );
				nPaging.appendChild( nList );
				nPaging.appendChild( nNext );
				nPaging.appendChild( nLast );
				
				$(nFirst).click( function () {
					oSettings._iDisplayStart = 0;
					fnCallbackDraw( oSettings );
				} );
				
				$(nPrevious).click( function() {
					oSettings._iDisplayStart -= oSettings._iDisplayLength;
					
					/* Correct for underrun */
					if ( oSettings._iDisplayStart < 0 )
					{
					  oSettings._iDisplayStart = 0;
					}
					
					fnCallbackDraw( oSettings );
				} );
				
				$(nNext).click( function() {
					/* Make sure we are not over running the display array */
					if ( oSettings._iDisplayStart + oSettings._iDisplayLength < oSettings.fnRecordsDisplay() )
					{
						oSettings._iDisplayStart += oSettings._iDisplayLength;
					}
					
					fnCallbackDraw( oSettings );
				} );
				
				$(nLast).click( function() {
					var iPages = parseInt( (oSettings.fnRecordsDisplay()-1) / oSettings._iDisplayLength, 10 ) + 1;
					oSettings._iDisplayStart = (iPages-1) * oSettings._iDisplayLength;
					
					fnCallbackDraw( oSettings );
				} );
				
				/* Take the brutal approach to cancelling text selection */
				$('span', nPaging).bind( 'mousedown', function () { return false; } );
				$('span', nPaging).bind( 'selectstart', function () { return false; } );
				
				oSettings.nPaginateList = nList;
			},
			
			/*
			 * Function: oPagination.full_numbers.fnUpdate
			 * Purpose:  Update the list of page buttons shows
			 * Returns:  -
	 		 * Inputs:   object:oSettings - dataTables settings object
			 *           function:fnCallbackDraw - draw function which must be called on update
			 */
			"fnUpdate": function ( oSettings, fnCallbackDraw )
			{
				if ( !oSettings.anFeatures.p )
				{
					return;
				}
				
				var iPageCount = jQuery.fn.dataTableExt.oPagination.iFullNumbersShowPages;
				var iPageCountHalf = Math.floor(iPageCount / 2);
				var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength);
				var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
				var sList = "";
				var iStartButton;
				var iEndButton;
				var oClasses = oSettings.oClasses;
				
				if (iPages < iPageCount)
				{
					iStartButton = 1;
					iEndButton = iPages;
				}
				else
				{
					if (iCurrentPage <= iPageCountHalf)
					{
						iStartButton = 1;
						iEndButton = iPageCount;
					}
					else
					{
						if (iCurrentPage >= (iPages - iPageCountHalf))
						{
							iStartButton = iPages - iPageCount + 1;
							iEndButton = iPages;
						}
						else
						{
							iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1;
							iEndButton = iStartButton + iPageCount - 1;
						}
					}
				}
				
				for ( var i=iStartButton ; i<=iEndButton ; i++ )
				{
					if ( iCurrentPage != i )
					{
						sList += '<span class="'+oClasses.sPageButton+'">'+i+'</span>';
					}
					else
					{
						sList += '<span class="'+oClasses.sPageButtonActive+'">'+i+'</span>';
					}
				}
				
				oSettings.nPaginateList.innerHTML = sList;
				
				/* Take the brutal approach to cancelling text selection */
				$('span', oSettings.nPaginateList).bind( 'mousedown', function () { return false; } );
				$('span', oSettings.nPaginateList).bind( 'selectstart', function () { return false; } );
				
				$('span', oSettings.nPaginateList).click( function() {
					var iTarget = (this.innerHTML * 1) - 1;
					oSettings._iDisplayStart = iTarget * oSettings._iDisplayLength;
					
					fnCallbackDraw( oSettings );
					return false;
				} );
				
				/* Update the 'premanent botton's classes */
				var nButtons = $('span', oSettings.anFeatures.p);
				var nStatic = [ nButtons[0], nButtons[1], nButtons[nButtons.length-2], nButtons[nButtons.length-1] ];
				$(nStatic).removeClass( oClasses.sPageButton+" "+oClasses.sPageButtonActive );
				if ( iCurrentPage == 1 )
				{
					nStatic[0].className += " "+oClasses.sPageButtonStaticActive;
					nStatic[1].className += " "+oClasses.sPageButtonStaticActive;
				}
				else
				{
					nStatic[0].className += " "+oClasses.sPageButton;
					nStatic[1].className += " "+oClasses.sPageButton;
				}
				
				if ( iCurrentPage == iPages )
				{
					nStatic[2].className += " "+oClasses.sPageButtonStaticActive;
					nStatic[3].className += " "+oClasses.sPageButtonStaticActive;
				}
				else
				{
					nStatic[2].className += " "+oClasses.sPageButton;
					nStatic[3].className += " "+oClasses.sPageButton;
				}
			}
		}
	};
	
	/*
	 * Variable: oSort
	 * Purpose:  Wrapper for the sorting functions that can be used in DataTables
	 * Scope:    jQuery.fn.dataTableExt
	 * Notes:    The functions provided in this object are basically standard javascript sort
	 *   functions - they expect two inputs which they then compare and then return a priority
	 *   result. For each sort method added, two functions need to be defined, an ascending sort and
	 *   a descending sort.
	 */
	_oExt.oSort = {
		/*
		 * text sorting
		 */
		"string-asc": function ( a, b )
		{
			var x = a.toLowerCase();
			var y = b.toLowerCase();
			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
		},
		
		"string-desc": function ( a, b )
		{
			var x = a.toLowerCase();
			var y = b.toLowerCase();
			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
		},
		
		
		/*
		 * html sorting (ignore html tags)
		 */
		"html-asc": function ( a, b )
		{
			var x = a.replace( /<.*?>/g, "" ).toLowerCase();
			var y = b.replace( /<.*?>/g, "" ).toLowerCase();
			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
		},
		
		"html-desc": function ( a, b )
		{
			var x = a.replace( /<.*?>/g, "" ).toLowerCase();
			var y = b.replace( /<.*?>/g, "" ).toLowerCase();
			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
		},
		
		
		/*
		 * date sorting
		 */
		"date-asc": function ( a, b )
		{
			var x = Date.parse( a );
			var y = Date.parse( b );
			
			if ( isNaN( x ) )
			{
    		x = Date.parse( "01/01/1970 00:00:00" );
			}
			if ( isNaN( y ) )
			{
				y =	Date.parse( "01/01/1970 00:00:00" );
			}
			
			return x - y;
		},
		
		"date-desc": function ( a, b )
		{
			var x = Date.parse( a );
			var y = Date.parse( b );
			
			if ( isNaN( x ) )
			{
    		x = Date.parse( "01/01/1970 00:00:00" );
			}
			if ( isNaN( y ) )
			{
				y =	Date.parse( "01/01/1970 00:00:00" );
			}
			
			return y - x;
		},
		
		
		/*
		 * numerical sorting
		 */
		"numeric-asc": function ( a, b )
		{
			var x = a == "-" ? 0 : a;
			var y = b == "-" ? 0 : b;
			return x - y;
		},
		
		"numeric-desc": function ( a, b )
		{
			var x = a == "-" ? 0 : a;
			var y = b == "-" ? 0 : b;
			return y - x;
		}
	};
	
	
	/*
	 * Variable: aTypes
	 * Purpose:  Container for the various type of type detection that dataTables supports
	 * Scope:    jQuery.fn.dataTableExt
	 * Notes:    The functions in this array are expected to parse a string to see if it is a data
	 *   type that it recognises. If so then the function should return the name of the type (a
	 *   corresponding sort function should be defined!), if the type is not recognised then the
	 *   function should return null such that the parser and move on to check the next type.
	 *   Note that ordering is important in this array - the functions are processed linearly,
	 *   starting at index 0.
	 */
	_oExt.aTypes = [
		/*
		 * Function: -
		 * Purpose:  Check to see if a string is numeric
		 * Returns:  string:'numeric' or null
		 * Inputs:   string:sText - string to check
		 */
		function ( sData )
		{
			/* Snaity check that we are dealing with a string or quick return for a number */
			if ( typeof sData == 'number' )
			{
				return 'numeric';
			}
			else if ( typeof sData.charAt != 'function' )
			{
				return null;
			}
			
			var sValidFirstChars = "0123456789-";
			var sValidChars = "0123456789.";
			var Char;
			var bDecimal = false;
			
			/* Check for a valid first char (no period and allow negatives) */
			Char = sData.charAt(0); 
			if (sValidFirstChars.indexOf(Char) == -1) 
			{
				return null;
			}
			
			/* Check all the other characters are valid */
			for ( var i=1 ; i<sData.length ; i++ ) 
			{
				Char = sData.charAt(i); 
				if (sValidChars.indexOf(Char) == -1) 
				{
					return null;
				}
				
				/* Only allowed one decimal place... */
				if ( Char == "." )
				{
					if ( bDecimal )
					{
						return null;
					}
					bDecimal = true;
				}
			}
			
			return 'numeric';
		},
		
		/*
		 * Function: -
		 * Purpose:  Check to see if a string is actually a formatted date
		 * Returns:  string:'date' or null
		 * Inputs:   string:sText - string to check
		 */
		function ( sData )
		{
			var iParse = Date.parse(sData);
			if ( iParse !== null && !isNaN(iParse) )
			{
				return 'date';
			}
			return null;
		}
	];
	
	
	/*
	 * Variable: _oExternConfig
	 * Purpose:  Store information for DataTables to access globally about other instances
	 * Scope:    jQuery.fn.dataTableExt
	 */
	_oExt._oExternConfig = {
		/* int:iNextUnique - next unique number for an instance */
		"iNextUnique": 0
	};
	
	
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
	 * DataTables prototype
	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
	
	/*
	 * Function: dataTable
	 * Purpose:  DataTables information
	 * Returns:  -
	 * Inputs:   object:oInit - initalisation options for the table
	 */
	$.fn.dataTable = function( oInit )
	{
		/*
		 * Variable: _aoSettings
		 * Purpose:  Easy reference to data table settings
		 * Scope:    jQuery.dataTable
		 */
		var _aoSettings = $.fn.dataTableSettings;
		
		/*
		 * Function: classSettings
		 * Purpose:  Settings container function for all 'class' properties which are required
		 *   by dataTables
		 * Returns:  -
		 * Inputs:   -
		 */
		function classSettings ()
		{
			this.fnRecordsTotal = function ()
			{
				if ( this.oFeatures.bServerSide ) {
					return this._iRecordsTotal;
				} else {
					return this.aiDisplayMaster.length;
				}
			};
			
			this.fnRecordsDisplay = function ()
			{
				if ( this.oFeatures.bServerSide ) {
					return this._iRecordsDisplay;
				} else {
					return this.aiDisplay.length;
				}
			};
			
			this.fnDisplayEnd = function ()
			{
				if ( this.oFeatures.bServerSide ) {
					return this._iDisplayStart + this.aiDisplay.length;
				} else {
					return this._iDisplayEnd;
				}
			};
			
			/*
			 * Variable: sInstance
			 * Purpose:  Unique idendifier for each instance of the DataTables object
			 * Scope:    jQuery.dataTable.classSettings 
			 */
			this.sInstance = null;
			
			/*
			 * Variable: oFeatures
			 * Purpose:  Indicate the enablement of key dataTable features
			 * Scope:    jQuery.dataTable.classSettings 
			 */
			this.oFeatures = {
				"bPaginate": true,
				"bLengthChange": true,
				"bFilter": true,
				"bSort": true,
				"bInfo": true,
				"bAutoWidth": false,
				"bProcessing": false,
				"bSortClasses": true,
				"bStateSave": false,
				"bServerSide": false
			};
			
			/*
			 * Variable: anFeatures
			 * Purpose:  Array referencing the nodes which are used for the features
			 * Scope:    jQuery.dataTable.classSettings 
			 * Notes:    The parameters of this object match what is allowed by sDom - i.e.
			 *   'l' - Length changing
			 *   'f' - Filtering input
			 *   't' - The table!
			 *   'i' - Information
			 *   'p' - Pagination
			 *   'r' - pRocessing
			 */
			this.anFeatures = [];
			
			/*
			 * Variable: oLanguage
			 * Purpose:  Store the language strings used by dataTables
			 * Scope:    jQuery.dataTable.classSettings
			 * Notes:    The words in the format _VAR_ are variables which are dynamically replaced
			 *   by javascript
			 */
			this.oLanguage = {
				"sProcessing": "En cours...",
				"sLengthMenu": "Afficher _MENU_ messages",
				"sZeroRecords": "Aucune message correspondante trouv\u00E9e",
				"sInfo": "Afficher _START_ \u00E0 _END_ de _TOTAL_ message(s)",
				"sInfoEmpty": "Afficher 0 \u00E0 0 de 0 messages",
				"sInfoFiltered": "(filtr\u00E9 de _MAX_ messages)",
				"sInfoPostFix": "",
				"sSearch": 'Rechercher:',
				"sUrl": "",
				"oPaginate": {
					"sFirst":    "Premier",
					"sPrevious": "Pr\u00E9c\u00E9dent",
					"sNext":     "Suivant",
					"sLast":     "Dernier"
				}
			};
			
			/*
			 * Variable: aoData
			 * Purpose:  Store data information
			 * Scope:    jQuery.dataTable.classSettings 
			 * Notes:    This is an array of objects with the following parameters:
			 *   int: _iId - internal id for tracking
			 *   array: _aData - internal data - used for sorting / filtering etc
			 *   node: nTr - display node
			 *   array node: _anHidden - hidden TD nodes
			 */
			this.aoData = [];
			
			/*
			 * Variable: aiDisplay
			 * Purpose:  Array of indexes which are in the current display (after filtering etc)
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.aiDisplay = [];
			
			/*
			 * Variable: aiDisplayMaster
			 * Purpose:  Array of indexes for display - no filtering
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.aiDisplayMaster = [];
							
			/*
			 * Variable: aoColumns
			 * Purpose:  Store information about each column that is in use
			 * Scope:    jQuery.dataTable.classSettings 
			 */
			this.aoColumns = [];
			
			/*
			 * Variable: iNextId
			 * Purpose:  Store the next unique id to be used for a new row
			 * Scope:    jQuery.dataTable.classSettings 
			 */
			this.iNextId = 0;
			
			/*
			 * Variable: asDataSearch
			 * Purpose:  Search data array for regular expression searching
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.asDataSearch = [];
			
			/*
			 * Variable: oPreviousSearch
			 * Purpose:  Store the previous search incase we want to force a re-search
			 *   or compare the old search to a new one
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.oPreviousSearch = {
				"sSearch": "",
				"bEscapeRegex": true
			};
			
			/*
			 * Variable: aoPreSearchCols
			 * Purpose:  Store the previous search for each column
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.aoPreSearchCols = [];
			
			/*
			 * Variable: aaSorting
			 * Purpose:  Sorting information
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.aaSorting = [ [0, 'asc'] ];
			
			/*
			 * Variable: aaSortingFixed
			 * Purpose:  Sorting information that is always applied
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.aaSortingFixed = null;
			
			/*
			 * Variable: asStripClasses
			 * Purpose:  Classes to use for the striping of a table
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.asStripClasses = [];
			
			/*
			 * Variable: fnRowCallback
			 * Purpose:  Call this function every time a row is inserted (draw)
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.fnRowCallback = null;
			
			/*
			 * Variable: fnHeaderCallback
			 * Purpose:  Callback function for the header on each draw
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.fnHeaderCallback = null;
			
			/*
			 * Variable: fnFooterCallback
			 * Purpose:  Callback function for the footer on each draw
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.fnFooterCallback = null;
			
			/*
			 * Variable: fnDrawCallback
			 * Purpose:  Callback function for the whole table on each draw
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.fnDrawCallback = null;
			
			/*
			 * Variable: fnInitComplete
			 * Purpose:  Callback function for when the table has been initalised
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.fnInitComplete = null;
			
			/*
			 * Variable: sTableId
			 * Purpose:  Cache the table ID for quick access
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.sTableId = "";
			
			/*
			 * Variable: nTable
			 * Purpose:  Cache the table node for quick access
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.nTable = null;
			
			/*
			 * Variable: iDefaultSortIndex
			 * Purpose:  Sorting index which will be used by default
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.iDefaultSortIndex = 0;
			
			/*
			 * Variable: bInitialised
			 * Purpose:  Indicate if all required information has been read in
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.bInitialised = false;
			
			/*
			 * Variable: aoOpenRows
			 * Purpose:  Information about open rows
			 * Scope:    jQuery.dataTable.classSettings
			 * Notes:    Has the parameters 'nTr' and 'nParent'
			 */
			this.aoOpenRows = [];
			
			/*
			 * Variable: sDomPositioning
			 * Purpose:  Dictate the positioning that the created elements will take
			 * Scope:    jQuery.dataTable.classSettings
			 * Notes:    The following syntax is expected:
			 *   'l' - Length changing
			 *   'f' - Filtering input
			 *   't' - The table!
			 *   'i' - Information
			 *   'p' - Pagination
			 *   'r' - pRocessing
			 *   '<' and '>' - div elements
			 *   '<"class" and '>' - div with a class
			 *    Examples: '<"wrapper"flipt>', '<lf<t>ip>'
			 */
			this.sDomPositioning = 'lfrtip';
			
			/*
			 * Variable: sPaginationType
			 * Purpose:  Note which type of sorting should be used
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.sPaginationType = "two_button";
			
			/*
			 * Variable: iCookieDuration
			 * Purpose:  The cookie duration (for bStateSave) in seconds - default 2 hours
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.iCookieDuration = 60 * 60 * 2;
			
			/*
			 * Variable: sAjaxSource
			 * Purpose:  Source url for AJAX data for the table
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.sAjaxSource = null;
			
			/*
			 * Variable: bAjaxDataGet
			 * Purpose:  Note if draw should be blocked while getting data
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.bAjaxDataGet = true;
			
			/*
			 * Variable: fnServerData
			 * Purpose:  Function to get the server-side data - can be overruled by the developer
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.fnServerData = $.getJSON;
			
			/*
			 * Variable: iServerDraw
			 * Purpose:  Counter and tracker for server-side processing draws
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.iServerDraw = 0;
			
			/*
			 * Variable: _iDisplayLength, _iDisplayStart, _iDisplayEnd
			 * Purpose:  Display length variables
			 * Scope:    jQuery.dataTable.classSettings
			 * Notes:    These variable must NOT be used externally to get the data length. Rather, use
			 *   the fnRecordsTotal() (etc) functions.
			 */
			this._iDisplayLength = 10;
			this._iDisplayStart = 0;
			this._iDisplayEnd = 10;
			
			/*
			 * Variable: _iRecordsTotal, _iRecordsDisplay
			 * Purpose:  Display length variables used for server side processing
			 * Scope:    jQuery.dataTable.classSettings
			 * Notes:    These variable must NOT be used externally to get the data length. Rather, use
			 *   the fnRecordsTotal() (etc) functions.
			 */
			this._iRecordsTotal = 0;
			this._iRecordsDisplay = 0;
			
			/*
			 * Variable: bJUI
			 * Purpose:  Should we add the markup needed for jQuery UI theming?
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.bJUI = false;
			
			/*
			 * Variable: bJUI
			 * Purpose:  Should we add the markup needed for jQuery UI theming?
			 * Scope:    jQuery.dataTable.classSettings
			 */
			this.oClasses = _oExt.oStdClasses;
		}
		
		/*
		 * Variable: oApi
		 * Purpose:  Container for publicly exposed 'private' functions
		 * Scope:    jQuery.dataTable
		 */
		this.oApi = {};
		
		
		/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
		 * API functions
		 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
		
		/*
		 * Function: fnDraw
		 * Purpose:  Redraw the table
		 * Returns:  -
		 * Inputs:   -
		 */
		this.fnDraw = function()
		{
			_fnReDraw( _fnSettingsFromNode( this[_oExt.iApiIndex] ) );
		};
		
		/*
		 * Function: fnFilter
		 * Purpose:  Filter the input based on data
		 * Returns:  -
		 * Inputs:   string:sInput - string to filter the table on
		 *           int:iColumn - optional - column to limit filtering to
		 *           bool:bEscapeRegex - optional - escape regex characters or not - default true
		 */
		this.fnFilter = function( sInput, iColumn, bEscapeRegex )
		{
			var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
			
			if ( typeof bEscapeRegex == 'undefined' )
			{
				bEscapeRegex = true;
			}
			
			if ( typeof iColumn == "undefined" || iColumn === null )
			{
				/* Global filter */
				_fnFilterComplete( oSettings, {"sSearch":sInput, "bEscapeRegex": bEscapeRegex}, 1 );
			}
			else
			{
				/* Single column filter */
				oSettings.aoPreSearchCols[ iColumn ].sSearch = sInput;
				oSettings.aoPreSearchCols[ iColumn ].bEscapeRegex = bEscapeRegex;
				_fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 );
			}
		};
		
		/*
		 * Function: fnSettings
		 * Purpose:  Get the settings for a particular table for extern. manipulation
		 * Returns:  -
		 * Inputs:   -
		 */
		this.fnSettings = function( nNode  )
		{
			return _fnSettingsFromNode( this[_oExt.iApiIndex] );
		};
		
		/*
		 * Function: fnSort
		 * Purpose:  Sort the table by a particular row
		 * Returns:  -
		 * Inputs:   int:iCol - the data index to sort on. Note that this will
		 *   not match the 'display index' if you have hidden data entries
		 */
		this.fnSort = function( aaSort )
		{
			var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
			oSettings.aaSorting = aaSort;
			_fnSort( oSettings );
		};
		
		/*
		 * Function: fnAddData
		 * Purpose:  Add new row(s) into the table
		 * Returns:  array int: array of indexes (aoData) which have been added (zero length on error)
		 * Inputs:   array:mData - the data to be added. The length must match
		 *               the original data from the DOM
		 *             or
		 *             array array:mData - 2D array of data to be added
		 *           bool:bRedraw - redraw the table or not - default true
		 * Notes:    Warning - the refilter here will cause the table to redraw
		 *             starting at zero
		 * Notes:    Thanks to Yekimov Denis for contributing the basis for this function!
		 */
		this.fnAddData = function( mData, bRedraw )
		{
			var aiReturn = [];
			var iTest;
			if ( typeof bRedraw == 'undefined' )
			{
				bRedraw = true;
			}
			
			/* Find settings from table node */
			var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
			
			/* Check if we want to add multiple rows or not */
			if ( typeof mData[0] == "object" )
			{
				for ( var i=0 ; i<mData.length ; i++ )
				{
					iTest = _fnAddData( oSettings, mData[i] );
					if ( iTest == -1 )
					{
						return aiReturn;
					}
					aiReturn.push( iTest );
				}
			}
			else
			{
				iTest = _fnAddData( oSettings, mData );
				if ( iTest == -1 )
				{
					return aiReturn;
				}
				aiReturn.push( iTest );
			}
			
			oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
			
			/* Rebuild the search */
			_fnBuildSearchArray( oSettings, 1 );
			
			if ( bRedraw )
			{
				_fnReDraw( oSettings );
			}
			return aiReturn;
		};
		
		/*
		 * Function: fnDeleteRow
		 * Purpose:  Remove a row for the table
		 * Returns:  array:aReturn - the row that was deleted
		 * Inputs:   int:iIndex - index of aoData to be deleted
		 *           function:fnCallBack - callback function - default null
		 *           bool:bNullRow - remove the row information from aoData by setting the value to
		 *             null - default false
		 * Notes:    This function requires a little explanation - we don't actually delete the data
		 *   from aoData - rather we remove it's references from aiDisplayMastr and aiDisplay. This
		 *   in effect prevnts DataTables from drawing it (hence deleting it) - it could be restored
		 *   if you really wanted. The reason for this is that actually removing the aoData object
		 *   would mess up all the subsequent indexes in the display arrays (they could be ajusted - 
		 *   but this appears to do what is required).
		 */
		this.fnDeleteRow = function( iAODataIndex, fnCallBack, bNullRow )
		{
			/* Find settings from table node */
			var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
			var i;
			
			/* Delete from the display master */
			for ( i=0 ; i<oSettings.aiDisplayMaster.length ; i++ )
			{
				if ( oSettings.aiDisplayMaster[i] == iAODataIndex )
				{
					oSettings.aiDisplayMaster.splice( i, 1 );
					break;
				}
			}
			
			/* Delete from the current display index */
			for ( i=0 ; i<oSettings.aiDisplay.length ; i++ )
			{
				if ( oSettings.aiDisplay[i] == iAODataIndex )
				{
					oSettings.aiDisplay.splice( i, 1 );
					break;
				}
			}
			
			/* Rebuild the search */
			_fnBuildSearchArray( oSettings, 1 );
			
			/* If there is a user callback function - call it */
			if ( typeof fnCallBack == "function" )
			{
				fnCallBack.call( this );
			}
			
			/* Check for an 'overflow' they case for dislaying the table */
			if ( oSettings._iDisplayStart >= oSettings.aiDisplay.length )
			{
				oSettings._iDisplayStart -= oSettings._iDisplayLength;
				if ( oSettings._iDisplayStart < 0 )
				{
					oSettings._iDisplayStart = 0;
				}
			}
			
			_fnCalculateEnd( oSettings );
			_fnDraw( oSettings );
			
			/* Return the data array from this row */
			var aData = oSettings.aoData[iAODataIndex]._aData.slice();
			
			if ( typeof bNullRow != "undefined" && bNullRow === true )
			{
				oSettings.aoData[iAODataIndex] = null;
			}
			
			return aData;
		};
		
		/*
		 * Function: fnClearTable
		 * Purpose:  Quickly and simply clear a table
		 * Returns:  -
		 * Inputs:   bool:bRedraw - redraw the table or not - default true
		 * Notes:    Thanks to Yekimov Denis for contributing the basis for this function!
		 */
		this.fnClearTable = function( bRedraw )
		{
			/* Find settings from table node */
			var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
			_fnClearTable( oSettings );
			
			if ( typeof bRedraw == 'undefined' || bRedraw )
			{
				_fnDraw( oSettings );
			}
		};
		
		/*
		 * Function: fnOpen
		 * Purpose:  Open a display row (append a row after the row in question)
		 * Returns:  -
		 * Inputs:   node:nTr - the table row to 'open'
		 *           string:sHtml - the HTML to put into the row
		 *           string:sClass - class to give the new cell
		 */
		this.fnOpen = function( nTr, sHtml, sClass )
		{
			/* Find settings from table node */
			var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
			
			/* the old open one if there is one */
			this.fnClose( nTr );
			
			
			var nNewRow = document.createElement("tr");
			var nNewCell = document.createElement("td");
			nNewRow.appendChild( nNewCell );
			nNewCell.className = sClass;
			nNewCell.colSpan = _fnVisbleColumns( oSettings );
			nNewCell.innerHTML = sHtml;
			
			$(nNewRow).insertAfter(nTr);
			
			/* No point in storing the row if using server-side processing since the nParent will be
			 * nuked on a re-draw anyway
			 */
			if ( !oSettings.oFeatures.bServerSide )
			{
				oSettings.aoOpenRows.push( {
					"nTr": nNewRow,
					"nParent": nTr
				} );
			}
		};
		
		/*
		 * Function: fnClose
		 * Purpose:  Close a display row
		 * Returns:  int: 0 (success) or 1 (failed)
		 * Inputs:   node:nTr - the table row to 'close'
		 */
		this.fnClose = function( nTr )
		{
			/* Find settings from table node */
			var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
			
			for ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ )
			{
				if ( oSettings.aoOpenRows[i].nParent == nTr )
				{
					var nTrParent = oSettings.aoOpenRows[i].nTr.parentNode;
					if ( nTrParent )
					{
						/* Remove it if it is currently on display */
						nTrParent.removeChild( oSettings.aoOpenRows[i].nTr );
					}
					oSettings.aoOpenRows.splice( i, 1 );
					return 0;
				}
			}
			return 1;
		};
		
		/*
		 * Function: fnGetData
		 * Purpose:  Return an array with the data which is used to make up the table
		 * Returns:  array array string: 2d data array ([row][column]) or array string: 1d data array
		 *           or
		 *           array string (if iRow specified)
		 * Inputs:   int:iRow - optional - if present then the array returned will be the data for
		 *             the row with the index 'iRow'
		 */
		this.fnGetData = function( iRow )
		{
			var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
			
			if ( typeof iRow != 'undefined' )
			{
				return oSettings.aoData[iRow]._aData;
			}
			return _fnGetDataMaster( oSettings );
		};
		
		/*
		 * Function: fnGetNodes
		 * Purpose:  Return an array with the TR nodes used for drawing the table
		 * Returns:  array node: TR elements
		 *           or
		 *           node (if iRow specified)
		 * Inputs:   int:iRow - optional - if present then the array returned will be the node for
		 *             the row with the index 'iRow'
		 */
		this.fnGetNodes = function( iRow )
		{
			var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
			
			if ( typeof iRow != 'undefined' )
			{
				return oSettings.aoData[iRow].nTr;
			}
			return _fnGetTrNodes( oSettings );
		};
		
		/*
		 * Function: fnGetPosition
		 * Purpose:  Get the array indexes of a particular cell from it's DOM element
		 * Returns:  int: - row index, or array[ int, int ]: - row index and column index
		 * Inputs:   node:nNode - this can either be a TR or a TD in the table, the return is
		 *             dependent on this input
		 */
		this.fnGetPosition = function( nNode )
		{
			var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
			var i;
			
			if ( nNode.nodeName == "TR" )
			{
				for ( i=0 ; i<oSettings.aoData.length ; i++ )
				{
					if ( oSettings.aoData[i] !== null && oSettings.aoData[i].nTr == nNode )
					{
						return i;
					}
				}
			}
			else if ( nNode.nodeName == "TD" )
			{
				for ( i=0 ; i<oSettings.aoData.length ; i++ )
				{
					var iCorrector = 0;
					for ( var j=0 ; j<oSettings.aoColumns.length ; j++ )
					{
						if ( oSettings.aoColumns[j].bVisible )
						{
							//$('>td', oSettings.aoData[i].nTr)[j-iCorrector] == nNode )
							if ( oSettings.aoData[i] !== null &&
								oSettings.aoData[i].nTr.getElementsByTagName('td')[j-iCorrector] == nNode )
							{
								return [ i, j-iCorrector, j ];
							}
						}
						else
						{
							iCorrector++;
						}
					}
				}
			}
			return null;
		};
		
		/*
		 * Function: fnUpdate
		 * Purpose:  Update a table cell or row
		 * Returns:  int: 0 okay, 1 error
		 * Inputs:   array string 'or' string:mData - data to update the cell/row with
		 *           int:iRow - the row (from aoData) to update
		 *           int:iColumn - the column to update
		 *           bool:bRedraw - redraw the table or not - default true
		 */
		this.fnUpdate = function( mData, iRow, iColumn, bRedraw )
		{
			var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
			var iVisibleColumn;
			var sDisplay;
			if ( typeof bRedraw == 'undefined' )
			{
				bRedraw = true;
			}
			
			if ( typeof mData != 'object' )
			{
				sDisplay = mData;
				oSettings.aoData[iRow]._aData[iColumn] = sDisplay;
				
				if ( oSettings.aoColumns[iColumn].fnRender !== null )
				{
					sDisplay = oSettings.aoColumns[iColumn].fnRender( {
						"iDataRow": iRow,
						"iDataColumn": iColumn,
						"aData": oSettings.aoData[iRow]._aData
					} );
					
					if ( oSettings.aoColumns[iColumn].bUseRendered )
					{
						oSettings.aoData[iRow]._aData[iColumn] = sDisplay;
					}
				}
				
				iVisibleColumn = _fnColumnIndexToVisible( oSettings, iColumn );
				if ( iVisibleColumn !== null )
				{
					oSettings.aoData[iRow].nTr.getElementsByTagName('td')[iVisibleColumn].innerHTML = 
						sDisplay;
				}
			}
			else
			{
				if ( mData.length != oSettings.aoColumns.length )
				{
					alert( 'Warning: An array passed to fnUpdate must have the same number of columns as '+
						'the table in question - in this case '+oSettings.aoColumns.length );
					return 1;
				}
				
				for ( var i=0 ; i<mData.length ; i++ )
				{
					sDisplay = mData[i];
					oSettings.aoData[iRow]._aData[i] = sDisplay;
					
					if ( oSettings.aoColumns[i].fnRender !== null )
					{
						sDisplay = oSettings.aoColumns[i].fnRender( {
							"iDataRow": iRow,
							"iDataColumn": i,
							"aData": oSettings.aoData[iRow]._aData
						} );
						
						if ( oSettings.aoColumns[i].bUseRendered )
						{
							oSettings.aoData[iRow]._aData[i] = sDisplay;
						}
					}
					
					iVisibleColumn = _fnColumnIndexToVisible( oSettings, i );
					if ( iVisibleColumn !== null )
					{
						oSettings.aoData[iRow].nTr.getElementsByTagName('td')[iVisibleColumn].innerHTML = 
							sDisplay;
					}
				}
			}
			
			/* Update the search array */
			_fnBuildSearchArray( oSettings, 1 );
			
			/* Redraw the table */
			if ( bRedraw )
			{
				_fnReDraw( oSettings );
			}
			return 0;
		};
		
		
		/*
		 * Function: fnShowColoumn
		 * Purpose:  Show a particular column
		 * Returns:  -
		 * Inputs:   int:iCol - the column whose display should be changed
		 *           bool:bShow - show (true) or hide (false) the column
		 */
		this.fnSetColumnVis = function ( iCol, bShow )
		{
			var oSettings = _fnSettingsFromNode( this[_oExt.iApiIndex] );
			var i, iLen;
			var iColumns = oSettings.aoColumns.length;
			var nTd;
			
			/* No point in doing anything if we are requesting what is already true */
			if ( oSettings.aoColumns[iCol].bVisible == bShow )
			{
				return;
			}
			
			var nTrHead = $('thead tr', oSettings.nTable)[0];
			var nTrFoot = $('tfoot tr', oSettings.nTable)[0];
			var anTheadTh = [];
			var anTfootTh = [];
			for ( i=0 ; i<iColumns ; i++ )
			{
				anTheadTh.push( oSettings.aoColumns[i].nTh );
				anTfootTh.push( oSettings.aoColumns[i].nTf );
			}
			
			/* Show the column */
			if ( bShow )
			{
				var iInsert = 0;
				for ( i=0 ; i<iCol ; i++ )
				{
					if ( oSettings.aoColumns[i].bVisible )
					{
						iInsert++;
					}
				}
				
				/* Need to decide if we should use appendChild or insertBefore */
				if ( iInsert >= _fnVisbleColumns( oSettings ) )
				{
					nTrHead.appendChild( anTheadTh[iCol] );
					if ( nTrFoot )
					{
						nTrFoot.appendChild( anTfootTh[iCol] );
					}
					
					for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
					{
						nTd = oSettings.aoData[i]._anHidden[iCol];
						oSettings.aoData[i].nTr.appendChild( nTd );
					}
				}
				else
				{
					/* Which coloumn should we be inserting before? */
					var iBefore;
					for ( i=iCol ; i<iColumns ; i++ )
					{
						iBefore = _fnColumnIndexToVisible( oSettings, i );
						if ( iBefore !== null )
						{
							break;
						}
					}
					
					nTrHead.insertBefore( anTheadTh[iCol], nTrHead.getElementsByTagName('th')[iBefore] );
					if ( nTrFoot )
					{
						nTrFoot.insertBefore( anTfootTh[iCol], nTrFoot.getElementsByTagName('th')[iBefore] );
					}
					
					for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
					{
						nTd = oSettings.aoData[i]._anHidden[iCol];
						oSettings.aoData[i].nTr.insertBefore( nTd, oSettings.aoData[i].nTr.getElementsByTagName('td')[iBefore] );
					}
				}
				
				oSettings.aoColumns[iCol].bVisible = true;
			}
			else
			{
				/* Remove a column from display */
				nTrHead.removeChild( anTheadTh[iCol] );
				if ( nTrFoot )
				{
					nTrFoot.removeChild( anTfootTh[iCol] );
				}
				
				var iVisCol = _fnColumnIndexToVisible(oSettings, iCol);
				for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
				{
					nTd = oSettings.aoData[i].nTr.getElementsByTagName('td')[ iVisCol ];
					oSettings.aoData[i]._anHidden[iCol] = nTd;
					nTd.parentNode.removeChild( nTd );
				}
				
				oSettings.aoColumns[iCol].bVisible = false;
			}
			
			/* If there are any 'open' rows, then we need to alter the colspan for this col change */
			for ( i=0, iLen=oSettings.aoOpenRows.length ; i<iLen ; i++ )
			{
				oSettings.aoOpenRows[i].nTr.colSpan = _fnVisbleColumns( oSettings );
			}
			
			/* Since there is no redraw done here, we need to save the state manually */
			_fnSaveState( oSettings );
		};
		
		
		/*
		 * Plugin API functions
		 * 
		 * This call will add the functions which are defined in _oExt.oApi to the
		 * DataTables object, providing a rather nice way to allow plug-in API functions. Note that
		 * this is done here, so that API function can actually override the built in API functions if
		 * required for a particular purpose.
		 */
		
		/*
		 * Function: _fnExternApiFunc
		 * Purpose:  Create a wrapper function for exporting an internal func to an external API func
		 * Returns:  function: - wrapped function
		 * Inputs:   string:sFunc - API function name
		 */
		function _fnExternApiFunc (sFunc)
		{
			return function() {
					var aArgs = [_fnSettingsFromNode(this[_oExt.iApiIndex])].concat( 
						Array.prototype.slice.call(arguments) );
					return _oExt.oApi[sFunc].apply( this, aArgs );
				};
		}
		
		for ( var sFunc in _oExt.oApi )
		{
			if ( sFunc )
			{
				/*
				 * Function: anon
				 * Purpose:  Wrap the plug-in API functions in order to provide the settings as 1st arg 
				 *   and execute in this scope
				 * Returns:  -
				 * Inputs:   -
				 */
				this[sFunc] = _fnExternApiFunc(sFunc);
			}
		}
		
		
		
		/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
		 * Local functions
		 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
		
		/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
		 * Initalisation
		 */
		
		/*
		 * Function: _fnInitalise
		 * Purpose:  Draw the table for the first time, adding all required features
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnInitalise ( oSettings )
		{
			/* Ensure that the table data is fully initialised */
			if ( oSettings.bInitialised === false )
			{
				setTimeout( function(){ _fnInitalise( oSettings ); }, 200 );
				return;
			}
			
			/* Show the display HTML options */
			_fnAddOptionsHtml( oSettings );
			
			/* Draw the headers for the table */
			_fnDrawHead( oSettings );
			
			/* If there is default sorting required - let's do it. The sort function
			 * will do the drawing for us. Otherwise we draw the table
			 */
			if ( oSettings.oFeatures.bSort )
			{
				_fnSort( oSettings, false );
				/*
				 * Add the sorting classes to the header and the body (if needed).
				 * Reason for doing it here after the first draw is to stop classes being applied to the
				 * 'static' table.
				 */
				_fnSortingClasses( oSettings );
			}
			else
			{
				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
				_fnCalculateEnd( oSettings );
				_fnDraw( oSettings );
			}
			
			/* if there is an ajax source */
			if ( oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide )
			{
				_fnProcessingDisplay( oSettings, true );
				
				$.getJSON( oSettings.sAjaxSource, null, function(json) {
					
					/* Got the data - add it to the table */
					for ( var i=0 ; i<json.aaData.length ; i++ )
					{
						_fnAddData( oSettings, json.aaData[i] );
					}
					
					/* Reset the init display for cookie saving. We've already done a filter, and
					 * therefore cleared it before. So we need to make it appear 'fresh'
					 */
					oSettings.iInitDisplayStart = oSettings._iDisplayStart;
					
					if ( oSettings.oFeatures.bSort )
					{
						_fnSort( oSettings );
					}
					else
					{
						oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
						_fnCalculateEnd( oSettings );
						_fnDraw( oSettings );
					}
					_fnProcessingDisplay( oSettings, false );
					
					/* Run the init callback if there is one */
					if ( typeof oSettings.fnInitComplete == 'function' )
					{
						oSettings.fnInitComplete( oSettings, json );
					}
				} );
				return;
			}
			
			/* Run the init callback if there is one */
			if ( typeof oSettings.fnInitComplete == 'function' )
			{
				oSettings.fnInitComplete( oSettings );
			}
			_fnProcessingDisplay( oSettings, false );
		}
		
		/*
		 * Function: _fnLanguageProcess
		 * Purpose:  Copy language variables from remote object to a local one
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 *           object:oLanguage - Language information
		 *           bool:bInit - init once complete
		 */
		function _fnLanguageProcess( oSettings, oLanguage, bInit )
		{
			_fnMap( oSettings.oLanguage, oLanguage, 'sProcessing' );
			_fnMap( oSettings.oLanguage, oLanguage, 'sLengthMenu' );
			_fnMap( oSettings.oLanguage, oLanguage, 'sZeroRecords' );
			_fnMap( oSettings.oLanguage, oLanguage, 'sInfo' );
			_fnMap( oSettings.oLanguage, oLanguage, 'sInfoEmpty' );
			_fnMap( oSettings.oLanguage, oLanguage, 'sInfoFiltered' );
			_fnMap( oSettings.oLanguage, oLanguage, 'sInfoPostFix' );
			_fnMap( oSettings.oLanguage, oLanguage, 'sSearch' );
			
			if ( typeof oLanguage.oPaginate != 'undefined' )
			{
				_fnMap( oSettings.oLanguage.oPaginate, oLanguage.oPaginate, 'sFirst' );
				_fnMap( oSettings.oLanguage.oPaginate, oLanguage.oPaginate, 'sPrevious' );
				_fnMap( oSettings.oLanguage.oPaginate, oLanguage.oPaginate, 'sNext' );
				_fnMap( oSettings.oLanguage.oPaginate, oLanguage.oPaginate, 'sLast' );
			}
			
			if ( bInit )
			{
				_fnInitalise( oSettings );
			}
		}
		
		/*
		 * Function: _fnAddColumn
		 * Purpose:  Add a column to the list used for the table
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 *           object:oOptions - object with sType, bVisible and bSearchable
		 *           node:nTh - the th element for this column
		 * Notes:    All options in enter column can be over-ridden by the user
		 *   initialisation of dataTables
		 */
		function _fnAddColumn( oSettings, oOptions, nTh )
		{
			oSettings.aoColumns[ oSettings.aoColumns.length++ ] = {
				"sType": null,
				"_bAutoType": true,
				"bVisible": true,
				"bSearchable": true,
				"bSortable": true,
				"sTitle": nTh ? nTh.innerHTML : '',
				"sName": '',
				"sWidth": null,
				"sClass": null,
				"fnRender": null,
				"bUseRendered": true,
				"iDataSort": oSettings.aoColumns.length-1,
				"nTh": nTh ? nTh : document.createElement('th'),
				"nTf": null
			};
			
			/* User specified column options */
			var iLength = oSettings.aoColumns.length-1;
			if ( typeof oOptions != 'undefined' && oOptions !== null )
			{
				var oCol = oSettings.aoColumns[ iLength ];
				
				if ( typeof oOptions.sType != 'undefined' )
				{
					oCol.sType = oOptions.sType;
					oCol._bAutoType = false;
				}
				
				_fnMap( oCol, oOptions, "bVisible" );
				_fnMap( oCol, oOptions, "bSearchable" );
				_fnMap( oCol, oOptions, "bSortable" );
				_fnMap( oCol, oOptions, "sTitle" );
				_fnMap( oCol, oOptions, "sName" );
				_fnMap( oCol, oOptions, "sWidth" );
				_fnMap( oCol, oOptions, "sClass" );
				_fnMap( oCol, oOptions, "fnRender" );
				_fnMap( oCol, oOptions, "bUseRendered" );
				_fnMap( oCol, oOptions, "iDataSort" );
			}
			
			/* Add a column specific filter */
			if ( typeof oSettings.aoPreSearchCols[ iLength ] == 'undefined' ||
			     oSettings.aoPreSearchCols[ iLength ] === null )
			{
				oSettings.aoPreSearchCols[ iLength ] = {
					"sSearch": "",
					"bEscapeRegex": true
				};
			}
			else if ( typeof oSettings.aoPreSearchCols[ iLength ].bEscapeRegex == 'undefined' )
			{
				/* Don't require that the user must specify bEscapeRegex */
				oSettings.aoPreSearchCols[ iLength ].bEscapeRegex = true;
			}
		}
		
		/*
		 * Function: _fnAddData
		 * Purpose:  Add a data array to the table, creating DOM node etc
		 * Returns:  int: - >=0 if successful (index of new aoData entry), -1 if failed
		 * Inputs:   object:oSettings - dataTables settings object
		 *           array:aData - data array to be added
		 */
		function _fnAddData ( oSettings, aData )
		{
			/* Sanity check the length of the new array */
			if ( aData.length != oSettings.aoColumns.length )
			{
				alert( "Warning - added data does not match known number of columns" );
				return -1;
			}
			
			/* Create the object for storing information about this new row */
			var iThisIndex = oSettings.aoData.length;
			oSettings.aoData.push( {
				"_iId": oSettings.iNextId++,
				"_aData": aData.slice(),
				"nTr": document.createElement('tr'),
				"_anHidden": []
			} );
			
			/* Create the cells */
			var nTd;
			for ( var i=0 ; i<aData.length ; i++ )
			{
				nTd = document.createElement('td');
				
				if ( typeof oSettings.aoColumns[i].fnRender == 'function' )
				{
					var sRendered = oSettings.aoColumns[i].fnRender( {
							"iDataRow": iThisIndex,
							"iDataColumn": i,
							"aData": aData
						} );
					nTd.innerHTML = sRendered;
					if ( oSettings.aoColumns[i].bUseRendered )
					{
						/* Use the rendered data for filtering/sorting */
						oSettings.aoData[iThisIndex]._aData[i] = sRendered;
					}
				}
				else
				{
					nTd.innerHTML = aData[i];
				}
				
				if ( oSettings.aoColumns[i].sClass !== null )
				{
					nTd.className = oSettings.aoColumns[i].sClass;
				}
				
				/* See if we should auto-detect the column type */
				if ( oSettings.aoColumns[i]._bAutoType && oSettings.aoColumns[i].sType != 'string' )
				{
					/* Attempt to auto detect the type - same as _fnGatherData() */
					if ( oSettings.aoColumns[i].sType === null )
					{
						oSettings.aoColumns[i].sType = _fnDetectType( aData[i] );
					}
					else if ( oSettings.aoColumns[i].sType == "date" || 
					          oSettings.aoColumns[i].sType == "numeric" )
					{
						oSettings.aoColumns[i].sType = _fnDetectType( aData[i] );
					}
				}
					
				if ( oSettings.aoColumns[i].bVisible )
				{
					oSettings.aoData[iThisIndex].nTr.appendChild( nTd );
				}
				else
				{
					oSettings.aoData[iThisIndex]._anHidden[i] = nTd;
				}
			}
			
			/* Add to the display array */
			oSettings.aiDisplayMaster.push( iThisIndex );
			return iThisIndex;
		}
		
		/*
		 * Function: _fnGatherData
		 * Purpose:  Read in the data from the target table
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnGatherData( oSettings )
		{
			var iLoop;
			var i, j;
			
			/*
			 * Process by row first
			 * Add the data object for the whole table - storing the tr node. Note - no point in getting
			 * DOM based data if we are going to go and replace it with Ajax source data.
			 */
			if ( oSettings.sAjaxSource === null )
			{
				$('tbody:eq(0)>tr', oSettings.nTable).each( function() {
					var iThisIndex = oSettings.aoData.length;
					oSettings.aoData.push( {
						"_iId": oSettings.iNextId++,
						"_aData": [],
						"nTr": this,
						"_anHidden": []
					} );
					
					oSettings.aiDisplayMaster.push( iThisIndex );
					
					/* Add the data for this column */
					var aLocalData = oSettings.aoData[iThisIndex]._aData;
					$('td', this).each( function( i ) {
						aLocalData[i] = this.innerHTML;
					} );
				} );
			}
			
			/*
			 * Now process by column
			 */
			var iCorrector = 0;
			for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
			{
				/* Get the title of the column - unless there is a user set one */
				if ( oSettings.aoColumns[i].sTitle === null )
				{
					oSettings.aoColumns[i].sTitle = oSettings.aoColumns[i].nTh.innerHTML;
				}
				
				var bAutoType = oSettings.aoColumns[i]._bAutoType;
				var bRender = typeof oSettings.aoColumns[i].fnRender == 'function';
				var bClass = oSettings.aoColumns[i].sClass !== null;
				var bVisible = oSettings.aoColumns[i].bVisible;
				
				/* A single loop to rule them all (and be more efficient) */
				if ( bAutoType || bRender || bClass || !bVisible )
				{
					iLoop = oSettings.aoData.length;
					for ( j=0 ; j<iLoop ; j++ )
					{
						var nCellNode = oSettings.aoData[j].nTr.getElementsByTagName('td')[ i-iCorrector ];
						
						if ( bAutoType )
						{
							if ( oSettings.aoColumns[i].sType === null )
							{
								oSettings.aoColumns[i].sType = _fnDetectType( oSettings.aoData[j]._aData[i] );
							}
							else if ( oSettings.aoColumns[i].sType == "date" || 
							          oSettings.aoColumns[i].sType == "numeric" )
							{
								/* If type is date or numeric - ensure that all collected data
								 * in the column is of the same type
								 */
								oSettings.aoColumns[i].sType = _fnDetectType( oSettings.aoData[j]._aData[i] );
							}
							/* The else would be 'type = string' we don't want to do anything
							 * if that is the case
							 */
						}
						
						if ( bRender )
						{
							var sRendered = oSettings.aoColumns[i].fnRender( {
									"iDataRow": j,
									"iDataColumn": i,
									"aData": oSettings.aoData[j]._aData
								} );
							nCellNode.innerHTML = sRendered;
							if ( oSettings.aoColumns[i].bUseRendered )
							{
								/* Use the rendered data for filtering/sorting */
								oSettings.aoData[j]._aData[i] = sRendered;
							}
						}
						
						if ( bClass )
						{
							nCellNode.className += ' '+oSettings.aoColumns[i].sClass;
						}
						
						if ( !bVisible )
						{
							oSettings.aoData[j]._anHidden[i] = nCellNode;
							nCellNode.parentNode.removeChild( nCellNode );
						}
					}
					
					/* Keep an index corrector for the next loop */
					if ( !bVisible )
					{
						iCorrector++;
					}
				}
			}	
		}
		
		
		
		/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
		 * Drawing functions
		 */
		
		/*
		 * Function: _fnDrawHead
		 * Purpose:  Create the HTML header for the table
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnDrawHead( oSettings )
		{
			var i, nTh, iLen;
			var iThs = oSettings.nTable.getElementsByTagName('thead')[0].getElementsByTagName('th').length;
			var iCorrector = 0;
			
			/* If there is a header in place - then use it - otherwise it's going to get nuked... */
			if ( iThs !== 0 )
			{
				/* We've got a thead from the DOM, so remove hidden columns and apply width to vis cols */
				for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
				{
					//oSettings.aoColumns[i].nTh = nThs[i];
					nTh = oSettings.aoColumns[i].nTh;
					
					if ( oSettings.aoColumns[i].bVisible )
					{
						/* Set width */
						if ( oSettings.aoColumns[i].sWidth !== null )
						{
							nTh.style.width = oSettings.aoColumns[i].sWidth;
						}
						
						/* Set the title of the column if it is user defined (not what was auto detected) */
						if ( oSettings.aoColumns[i].sTitle != nTh.innerHTML )
						{
							nTh.innerHTML = oSettings.aoColumns[i].sTitle;
						}
					}
					else
					{
						nTh.parentNode.removeChild( nTh );
						iCorrector++;
					}
				}
			}
			else
			{
				/* We don't have a header in the DOM - so we are going to have to create one */
				var nTr = document.createElement( "tr" );
				
				for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
				{
					if ( oSettings.aoColumns[i].bVisible )
					{
						nTh = oSettings.aoColumns[i].nTh;
						
						if ( oSettings.aoColumns[i].sClass !== null )
						{
							nTh.className = oSettings.aoColumns[i].sClass;
						}
						
						if ( oSettings.aoColumns[i].sWidth !== null )
						{
							nTh.style.width = oSettings.aoColumns[i].sWidth;
						}
						
						nTh.innerHTML = oSettings.aoColumns[i].sTitle;
						nTr.appendChild( nTh );
					}
				}
				$('thead', oSettings.nTable).html( '' )[0].appendChild( nTr );
			}
			
			/* Add the extra markup needed by jQuery UI's themes */
			if ( oSettings.bJUI )
			{
				for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
				{
					var nSpan = document.createElement('span');
					oSettings.aoColumns[i].nTh.appendChild( nSpan );
				}
			}
			
			/* Add sort listener */
			if ( oSettings.oFeatures.bSort )
			{
				for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
				{
					if ( oSettings.aoColumns[i].bSortable === false )
					{
						continue;
					}
					
					$(oSettings.aoColumns[i].nTh).click( function (e) {
						var iDataIndex;
						/* Find which column we are sorting on - can't use index() due to colspan etc */
						for ( var i=0 ; i<oSettings.aoColumns.length ; i++ )
						{
							if ( oSettings.aoColumns[i].nTh == this )
							{
								iDataIndex = i;
								break;
							}
						}
						
						/* If the column is not sortable - don't to anything */
						if ( oSettings.aoColumns[iDataIndex].bSortable === false )
						{
							return;
						}
						
						/*
						 * This is a little bit odd I admit... I declare a temporary function inside the scope of
						 * _fnDrawHead and the click handler in order that the code presented here can be used 
						 * twice - once for when bProcessing is enabled, and another time for when it is 
						 * disabled, as we need to perform slightly different actions.
						 *   Basically the issue here is that the Javascript engine in modern browsers don't 
						 * appear to allow the rendering engine to update the display while it is still excuting
						 * it's thread (well - it does but only after long intervals). This means that the 
						 * 'processing' display doesn't appear for a table sort. To break the js thread up a bit
						 * I force an execution break by using setTimeout - but this breaks the expected 
						 * thread continuation for the end-developer's point of view (their code would execute
						 * too early), so we on;y do it when we absolutely have to.
						 */
						var fnInnerSorting = function () {
							if ( e.shiftKey )
							{
								/* If the shift key is pressed then we are multipe column sorting */
								var bFound = false;
								for ( var i=0 ; i<oSettings.aaSorting.length ; i++ )
								{
									if ( oSettings.aaSorting[i][0] == iDataIndex )
									{
										if ( oSettings.aaSorting[i][1] == "asc" )
										{
											oSettings.aaSorting[i][1] = "desc";
										}
										else
										{
											oSettings.aaSorting.splice( i, 1 );
										}
										bFound = true;
										break;
									}
								}
								
								if ( bFound === false )
								{
									oSettings.aaSorting.push( [ iDataIndex, "asc" ] );
								}
							}
							else
							{
								/* If no shift key then single column sort */
								if ( oSettings.aaSorting.length == 1 && oSettings.aaSorting[0][0] == iDataIndex )
								{
									oSettings.aaSorting[0][1] = oSettings.aaSorting[0][1]=="asc" ? "desc" : "asc";
								}
								else
								{
									oSettings.aaSorting.splice( 0, oSettings.aaSorting.length );
									oSettings.aaSorting.push( [ iDataIndex, "asc" ] );
								}
							}
							
							/* Run the sort */
							_fnSort( oSettings );
						}; /* /fnInnerSorting */
						
						if ( !oSettings.oFeatures.bProcessing )
						{
							fnInnerSorting();
						}
						else
						{
							_fnProcessingDisplay( oSettings, true );
							setTimeout( function() {
								fnInnerSorting();
								if ( !oSettings.oFeatures.bServerSide )
								{
									_fnProcessingDisplay( oSettings, false );
								}
							}, 0 );
						}
					} ); /* /click */
				} /* For each column */
				
				/* Take the brutal approach to cancelling text selection due to the shift key */
				$('thead th', oSettings.nTable).mousedown( function (e) {
					if ( e.shiftKey )
					{
						this.onselectstart = function() { return false; };
						return false;
					}
				} );
			} /* /if feature sort */
			
			/* Set an absolute width for the table such that pagination doesn't
			 * cause the table to resize
			 */
			if ( oSettings.oFeatures.bAutoWidth )
			{
				oSettings.nTable.style.width = oSettings.nTable.offsetWidth+"px";
			}
			
			/* Cache the footer elements */
			var nTfoot = oSettings.nTable.getElementsByTagName('tfoot');
			if ( nTfoot.length !== 0 )
			{
				iCorrector = 0;
				var nTfs = nTfoot[0].getElementsByTagName('th');
				for ( i=0, iLen=nTfs.length ; i<iLen ; i++ )
				{
					oSettings.aoColumns[i].nTf = nTfs[i-iCorrector];
					if ( !oSettings.aoColumns[i].bVisible )
					{
						nTfs[i-iCorrector].parentNode.removeChild( nTfs[i-iCorrector] );
						iCorrector++;
					}
				}
			}
		}
		
		/*
		 * Function: _fnDraw
		 * Purpose:  Insert the required TR nodes into the table for display
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnDraw( oSettings )
		{
			var i;
			var anRows = [];
			var iRowCount = 0;
			var bRowError = false;
			var iStrips = oSettings.asStripClasses.length;
			var iOpenRows = oSettings.aoOpenRows.length;
			
			/* If we are dealing with Ajax - do it here */
			if ( oSettings.oFeatures.bServerSide && 
			     !_fnAjaxUpdate( oSettings ) )
			{
				return;
			}
			
			if ( oSettings.aiDisplay.length !== 0 )
			{
				var iStart = oSettings._iDisplayStart;
				var iEnd = oSettings._iDisplayEnd;
				
				if ( oSettings.oFeatures.bServerSide )
				{
					iStart = 0;
					iEnd = oSettings.aoData.length;
				}
				
				for ( var j=iStart ; j<iEnd ; j++ )
				{
					var nRow = oSettings.aoData[ oSettings.aiDisplay[j] ].nTr;
					
					/* Remove any old stripping classes and then add the new one */
					if ( iStrips !== 0 )
					{
						$(nRow).removeClass( oSettings.asStripClasses.join(' ') );
						$(nRow).addClass( oSettings.asStripClasses[ iRowCount % iStrips ] );
					}
					
					/* Custom row callback function - might want to manipule the row */
					if ( typeof oSettings.fnRowCallback == "function" )
					{
						nRow = oSettings.fnRowCallback( nRow, 
							oSettings.aoData[ oSettings.aiDisplay[j] ]._aData, iRowCount, j );
						if ( !nRow && !bRowError )
						{
							alert( "Error: A node was not returned by fnRowCallback" );
							bRowError = true;
						}
					}
					
					anRows.push( nRow );
					iRowCount++;
					
					/* If there is an open row - and it is attached to this parent - attach it on redraw */
					if ( iOpenRows !== 0 )
					{
						for ( var k=0 ; k<iOpenRows ; k++ )
						{
							if ( nRow == oSettings.aoOpenRows[k].nParent )
							{
								anRows.push( oSettings.aoOpenRows[k].nTr );
							}
						}
					}
				}
			}
			else
			{
				/* Table is empty - create a row with an empty message in it */
				anRows[ 0 ] = document.createElement( 'tr' );
				
				if ( typeof oSettings.asStripClasses[0] != 'undefined' )
				{
					anRows[ 0 ].className = oSettings.asStripClasses[0];
				}
				
				var nTd = document.createElement( 'td' );
				nTd.setAttribute( 'valign', "top" );
				nTd.colSpan = oSettings.aoColumns.length;
				nTd.className = oSettings.oClasses.sRowEmpty;
				nTd.innerHTML = oSettings.oLanguage.sZeroRecords;
				
				anRows[ iRowCount ].appendChild( nTd );
			}
			
			/* Callback the header and footer custom funcation if there is one */
			if ( typeof oSettings.fnHeaderCallback == 'function' )
			{
				oSettings.fnHeaderCallback( $('thead tr', oSettings.nTable)[0], 
					_fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(),
					oSettings.aiDisplay );
			}
			
			if ( typeof oSettings.fnFooterCallback == 'function' )
			{
				oSettings.fnFooterCallback( $('tfoot tr', oSettings.nTable)[0], 
					_fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(),
					oSettings.aiDisplay );
			}
			
			/* 
			 * Need to remove any old row from the display - note we can't just empty the tbody using
			 * .html('') since this will unbind the jQuery event handlers (even although the node still
			 * exists!) - note the initially odd ':eq(0)>tr' expression. This basically ensures that we
			 * only get tr elements of the tbody that the data table has been initialised on. If there
			 * are nested tables then we don't want to remove those elements.
			 */
			var nTrs = $('tbody:eq(0)>tr', oSettings.nTable);
			for ( i=0 ; i<nTrs.length ; i++ )
			{
				nTrs[i].parentNode.removeChild( nTrs[i] );
			}
			
			/* Put the draw table into the dom */
			var nBody = $('tbody:eq(0)', oSettings.nTable);
			if ( nBody[0] )
			{
				for ( i=0 ; i<anRows.length ; i++ )
				{
					nBody[0].appendChild( anRows[i] );
				}
			}
			
			/* Update the pagination display buttons */
			if ( oSettings.oFeatures.bPaginate )
			{
				_oExt.oPagination[ oSettings.sPaginationType ].fnUpdate( oSettings, function( oSettings ) {
					_fnCalculateEnd( oSettings );
					_fnDraw( oSettings );
				} );
			}
			
			/* Show information about the table */
			if ( oSettings.oFeatures.bInfo && oSettings.anFeatures.i )
			{
				/* Update the information */
				if ( oSettings.fnRecordsDisplay() === 0 && 
					   oSettings.fnRecordsDisplay() == oSettings.fnRecordsTotal() )
				{
					oSettings.anFeatures.i.innerHTML = 
						oSettings.oLanguage.sInfoEmpty+ oSettings.oLanguage.sInfoPostFix;
				}
				else if ( oSettings.fnRecordsDisplay() === 0 )
				{
					oSettings.anFeatures.i.innerHTML = oSettings.oLanguage.sInfoEmpty +' '+ 
						oSettings.oLanguage.sInfoFiltered.replace('_MAX_', 
							oSettings.fnRecordsTotal())+ oSettings.oLanguage.sInfoPostFix;
				}
				else if ( oSettings.fnRecordsDisplay() == oSettings.fnRecordsTotal() )
				{
					oSettings.anFeatures.i.innerHTML = 
						oSettings.oLanguage.sInfo.
							replace('_START_',oSettings._iDisplayStart+1).
							replace('_END_',oSettings.fnDisplayEnd()).
							replace('_TOTAL_',oSettings.fnRecordsDisplay())+ 
						oSettings.oLanguage.sInfoPostFix;
				}
				else
				{
					oSettings.anFeatures.i.innerHTML = 
						oSettings.oLanguage.sInfo.
							replace('_START_',oSettings._iDisplayStart+1).
							replace('_END_',oSettings.fnDisplayEnd()).
							replace('_TOTAL_',oSettings.fnRecordsDisplay()) +' '+ 
						oSettings.oLanguage.sInfoFiltered.replace('_MAX_', oSettings.fnRecordsTotal())+ 
						oSettings.oLanguage.sInfoPostFix;
				}
			}
			
			/* Alter the sorting classes to take account of the changes */
			if ( oSettings.oFeatures.bServerSide && oSettings.oFeatures.bSort )
			{
				_fnSortingClasses( oSettings );
			}
			
			/* Save the table state on each draw */
			_fnSaveState( oSettings );
			
			/* Drawing is finished - call the callback if there is one */
			if ( typeof oSettings.fnDrawCallback == 'function' )
			{
				oSettings.fnDrawCallback( oSettings );
			}
		}
		
		/*
		 * Function: _fnReDraw
		 * Purpose:  Redraw the table - taking account of the various features which are enabled
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnReDraw( oSettings )
		{
			if ( oSettings.oFeatures.bSort )
			{
				/* Sorting will refilter and draw for us */
				_fnSort( oSettings, oSettings.oPreviousSearch );
			}
			else if ( oSettings.oFeatures.bFilter )
			{
				/* Filtering will redraw for us */
				_fnFilterComplete( oSettings, oSettings.oPreviousSearch );
			}
			else
			{
				_fnCalculateEnd( oSettings );
				_fnDraw( oSettings );
			}
		}
		
		/*
		 * Function: _fnAjaxUpdate
		 * Purpose:  Update the table using an Ajax call
		 * Returns:  bool: block the table drawing or not
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnAjaxUpdate( oSettings )
		{
			if ( oSettings.bAjaxDataGet )
			{
				_fnProcessingDisplay( oSettings, true );
				var iColumns = oSettings.aoColumns.length;
				var aoData = [];
				var i;
				
				/* Paging and general */
				oSettings.iServerDraw++;
				aoData.push( { "name": "sEcho",          "value": oSettings.iServerDraw } );
				aoData.push( { "name": "iColumns",       "value": iColumns } );
				aoData.push( { "name": "sColumns",       "value": _fnColumnOrdering(oSettings) } );
				aoData.push( { "name": "iDisplayStart",  "value": oSettings._iDisplayStart } );
				aoData.push( { "name": "iDisplayLength", "value": oSettings.oFeatures.bPaginate !== false ?
					oSettings._iDisplayLength : -1 } );
				
				/* Filtering */
				if ( oSettings.oFeatures.bFilter !== false )
				{
					aoData.push( { "name": "sSearch",        "value": oSettings.oPreviousSearch.sSearch } );
					aoData.push( { "name": "bEscapeRegex",   "value": oSettings.oPreviousSearch.bEscapeRegex } );
					for ( i=0 ; i<iColumns ; i++ )
					{
						aoData.push( { "name": "sSearch_"+i,      "value": oSettings.aoPreSearchCols[i].sSearch } );
						aoData.push( { "name": "bEscapeRegex_"+i, "value": oSettings.aoPreSearchCols[i].bEscapeRegex } );
					}
				}
				
				/* Sorting */
				if ( oSettings.oFeatures.bSort !== false )
				{
					var iFixed = oSettings.aaSortingFixed !== null ? oSettings.aaSortingFixed.length : 0;
					var iUser = oSettings.aaSorting.length;
					aoData.push( { "name": "iSortingCols",   "value": iFixed+iUser } );
					for ( i=0 ; i<iFixed ; i++ )
					{
						aoData.push( { "name": "iSortCol_"+i,  "value": oSettings.aaSortingFixed[i][0] } );
						aoData.push( { "name": "iSortDir_"+i,  "value": oSettings.aaSortingFixed[i][1] } );
					}
					
					for ( i=0 ; i<iUser ; i++ )
					{
						aoData.push( { "name": "iSortCol_"+(i+iFixed),  "value": oSettings.aaSorting[i][0] } );
						aoData.push( { "name": "iSortDir_"+(i+iFixed),  "value": oSettings.aaSorting[i][1] } );
					}
				}
				
				oSettings.fnServerData( oSettings.sAjaxSource, aoData, function(json) {
					_fnAjaxUpdateDraw( oSettings, json );
				} );
				return false;
			}
			else
			{
				return true;
			}
		}
		
		/*
		 * Function: _fnAjaxUpdateDraw
		 * Purpose:  Data the data from the server (nuking the old) and redraw the table
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 *           object:json - json data return from the server.
		 *             The following must be defined:
		 *               iTotalRecords, iTotalDisplayRecords, aaData
		 *             The following may be defined:
		 *               sColumns
		 */
		function _fnAjaxUpdateDraw ( oSettings, json )
		{
			if ( typeof json.sEcho != 'undefined' )
			{
				/* Protect against old returns over-writing a new one. Possible when you get
				 * very fast interaction, and later queires are completed much faster
				 */
				if ( json.sEcho*1 < oSettings.iServerDraw )
				{
					return;
				}
				else
				{
					oSettings.iServerDraw = json.sEcho * 1;
				}
			}
			
			_fnClearTable( oSettings );
			oSettings._iRecordsTotal = json.iTotalRecords;
			oSettings._iRecordsDisplay = json.iTotalDisplayRecords;
			
			/* Determine if reordering is required */
			var sOrdering = _fnColumnOrdering(oSettings);
			var bReOrder = (json.sColumns != 'undefined' && sOrdering !== "" && json.sColumns != sOrdering );
			if ( bReOrder )
			{
				var aiIndex = _fnReOrderIndex( oSettings, json.sColumns );
			}
			
			for ( var i=0, iLen=json.aaData.length ; i<iLen ; i++ )
			{
				if ( bReOrder )
				{
					/* If we need to re-order, then create a new array with the correct order and add it */
					var aData = [];
					for ( var j=0, jLen=oSettings.aoColumns.length ; j<jLen ; j++ )
					{
						aData.push( json.aaData[i][ aiIndex[j] ] );
					}
					_fnAddData( oSettings, aData );
				}
				else
				{
					/* No re-order required, sever got it "right" - just straight add */
					_fnAddData( oSettings, json.aaData[i] );
				}
			}
			oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
			
			oSettings.bAjaxDataGet = false;
			_fnDraw( oSettings );
			oSettings.bAjaxDataGet = true;
			_fnProcessingDisplay( oSettings, false );
		}
		
		/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
		 * Options (features) HTML
		 */
		
		/*
		 * Function: _fnAddOptionsHtml
		 * Purpose:  Add the options to the page HTML for the table
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnAddOptionsHtml ( oSettings )
		{
			/*
			 * Create a temporary, empty, div which we can later on replace with what we have generated
			 * we do it this way to rendering the 'options' html offline - speed :-)
			 */
			var nHolding = document.createElement( 'div' );
			oSettings.nTable.parentNode.insertBefore( nHolding, oSettings.nTable );
			
			/* 
			 * All DataTables are wrapped in a div - this is not currently optional - backwards 
			 * compatability. It can be removed if you don't want it.
			 */
			var nWrapper = document.createElement( 'div' );
			nWrapper.className = oSettings.oClasses.sWrapper;
			if ( oSettings.sTableId !== '' )
			{
				nWrapper.setAttribute( 'id', oSettings.sTableId+'_wrapper' );
			}
			
			/* Track where we want to insert the option */
			var nInsertNode = nWrapper;
			
			/* IE don't treat strings as arrays */
			var sDom = oSettings.sDomPositioning.split('');
			
			/* Loop over the user set positioning and place the elements as needed */
			var nTmp;
			for ( var i=0 ; i<sDom.length ; i++ )
			{
				var cOption = sDom[i];
				
				if ( cOption == '<' )
				{
					/* New container div */
					var nNewNode = document.createElement( 'div' );
					
					/* Check to see if we should append a class name to the container */
					var cNext = sDom[i+1];
					if ( cNext == "'" || cNext == '"' )
					{
						var sClass = "";
						var j = 2;
						while ( sDom[i+j] != cNext )
						{
							sClass += sDom[i+j];
							j++;
						}
						nNewNode.className = sClass;
						i += j; /* Move along the position array */
					}
					
					nInsertNode.appendChild( nNewNode );
					nInsertNode = nNewNode;
				}
				else if ( cOption == '>' )
				{
					/* End container div */
					nInsertNode = nInsertNode.parentNode;
				}
				else if ( cOption == 'l' && oSettings.oFeatures.bPaginate && oSettings.oFeatures.bLengthChange )
				{
					/* Length */
					nTmp = _fnFeatureHtmlLength( oSettings );
					oSettings.anFeatures[cOption] = nTmp;
					nInsertNode.appendChild( nTmp );
				}
				else if ( cOption == 'f' && oSettings.oFeatures.bFilter )
				{
					/* Filter */
					nTmp = _fnFeatureHtmlFilter( oSettings );
					oSettings.anFeatures[cOption] = nTmp;
					nInsertNode.appendChild( nTmp );
				}
				else if ( cOption == 'r' && oSettings.oFeatures.bProcessing )
				{
					/* pRocessing */
					nTmp = _fnFeatureHtmlProcessing( oSettings );
					oSettings.anFeatures[cOption] = nTmp;
					nInsertNode.appendChild( nTmp );
				}
				else if ( cOption == 't' )
				{
					/* Table */
					oSettings.anFeatures[cOption] = oSettings.nTable;
					nInsertNode.appendChild( oSettings.nTable );
				}
				else if ( cOption ==  'i' && oSettings.oFeatures.bInfo )
				{
					/* Info */
					nTmp = _fnFeatureHtmlInfo( oSettings );
					oSettings.anFeatures[cOption] = nTmp;
					nInsertNode.appendChild( nTmp );
				}
				else if ( cOption == 'p' && oSettings.oFeatures.bPaginate )
				{
					/* Pagination */
					nTmp = _fnFeatureHtmlPaginate( oSettings );
					oSettings.anFeatures[cOption] = nTmp;
					nInsertNode.appendChild( nTmp );
				}
				else if ( _oExt.aoFeatures.length !== 0 )
				{
					var aoFeatures = _oExt.aoFeatures;
					for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
					{
						if ( cOption == aoFeatures[k].cFeature )
						{
							nTmp = aoFeatures[k].fnInit( oSettings );
							oSettings.anFeatures[cOption] = nTmp;
							nInsertNode.appendChild( nTmp );
							break;
						}
					}
				}
			}
			
			/* Built our DOM structure - replace the holding div with what we want */
			nHolding.parentNode.replaceChild( nWrapper, nHolding );
		}
		
		/*
		 * Function: _fnFeatureHtmlFilter
		 * Purpose:  Generate the node required for filtering text
		 * Returns:  node
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnFeatureHtmlFilter ( oSettings )
		{
			var nFilter = document.createElement( 'div' );
			if ( oSettings.sTableId !== '' )
			{
				nFilter.setAttribute( 'id', oSettings.sTableId+'_filter' );
			}
			nFilter.className = oSettings.oClasses.sFilter;
			var sSpace = oSettings.oLanguage.sSearch==="" ? "" : " ";
			nFilter.innerHTML = oSettings.oLanguage.sSearch+sSpace+'<input type="text" />';
			
			var jqFilter = $("input", nFilter);
			jqFilter.val( oSettings.oPreviousSearch.sSearch.replace('"','&quot;') );
			jqFilter.keyup( function(e) {
				_fnFilterComplete( oSettings, { 
					"sSearch": this.value, 
					"bEscapeRegex": oSettings.oPreviousSearch.bEscapeRegex 
				} );
				
				/* Prevent default */
				return false;
			} );
			
			return nFilter;
		}
		
		/*
		 * Function: _fnFeatureHtmlInfo
		 * Purpose:  Generate the node required for the info display
		 * Returns:  node
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnFeatureHtmlInfo ( oSettings )
		{
			var nInfo = document.createElement( 'div' );
			if ( oSettings.sTableId !== '' )
			{
				nInfo.setAttribute( 'id', oSettings.sTableId+'_info' );
			}
			nInfo.className = oSettings.oClasses.sInfo;
			return nInfo;
		}
		
		/*
		 * Function: _fnFeatureHtmlPaginate
		 * Purpose:  Generate the node required for default pagination
		 * Returns:  node
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnFeatureHtmlPaginate ( oSettings )
		{
			var nPaginate = document.createElement( 'div' );
			nPaginate.className = oSettings.oClasses.sPaging+oSettings.sPaginationType;
			oSettings.anFeatures.p = nPaginate; /* Need this stored in order to call paging plug-ins */
			
			_oExt.oPagination[ oSettings.sPaginationType ].fnInit( oSettings, function( oSettings ) {
				_fnCalculateEnd( oSettings );
				_fnDraw( oSettings );
			} );
			return nPaginate;
		}
		
		/*
		 * Function: _fnFeatureHtmlLength
		 * Purpose:  Generate the node required for user display length changing
		 * Returns:  node
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnFeatureHtmlLength ( oSettings )
		{
			/* This can be overruled by not using the _MENU_ var/macro in the language variable */
			var sName = (oSettings.sTableId === "") ? "" : 'name="'+oSettings.sTableId+'_length"';
			var sStdMenu = 
				'<select class="mailbox_select" size="1" '+sName+'>'+
					'<option value="10">10</option>'+
					'<option value="25">25</option>'+
					'<option value="50">50</option>'+
					'<option value="100">100</option>'+
				'</select>';
			
			var nLength = document.createElement( 'div' );
			if ( oSettings.sTableId !== '' )
			{
				nLength.setAttribute( 'id', oSettings.sTableId+'_length' );
			}
			nLength.className = oSettings.oClasses.sLength;
			nLength.innerHTML = oSettings.oLanguage.sLengthMenu.replace( '_MENU_', sStdMenu );
			
			/*
			 * Set the length to the current display length - thanks to Andrea Pavlovic for this fix,
			 * and Stefan Skopnik for fixing the fix!
			 */
			$('select option[value="'+oSettings._iDisplayLength+'"]',nLength).attr("selected",true);
			
			$('select', nLength).change( function(e) {
				oSettings._iDisplayLength = parseInt($(this).val(), 10);
				
				_fnCalculateEnd( oSettings );
				
				/* If we have space to show extra rows (backing up from the end point - then do so */
				if ( oSettings._iDisplayEnd == oSettings.aiDisplay.length )
				{
					oSettings._iDisplayStart = oSettings._iDisplayEnd - oSettings._iDisplayLength;
					if ( oSettings._iDisplayStart < 0 )
					{
						oSettings._iDisplayStart = 0;
					}
				}
				
				if ( oSettings._iDisplayLength == -1 )
				{
					oSettings._iDisplayStart = 0;
				}
				
				_fnDraw( oSettings );
			} );
			
			return nLength;
		}
		
		/*
		 * Function: _fnFeatureHtmlProcessing
		 * Purpose:  Generate the node required for the processing node
		 * Returns:  node
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnFeatureHtmlProcessing ( oSettings )
		{
			var nProcessing = document.createElement( 'div' );
			
			if ( oSettings.sTableId !== '' )
			{
				nProcessing.setAttribute( 'id', oSettings.sTableId+'_processing' );
			}
			nProcessing.innerHTML = oSettings.oLanguage.sProcessing;
			nProcessing.className = oSettings.oClasses.sProcessing;
			oSettings.nTable.parentNode.insertBefore( nProcessing, oSettings.nTable );
			
			return nProcessing;
		}
		
		/*
		 * Function: _fnProcessingDisplay
		 * Purpose:  Display or hide the processing indicator
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 *           bool:
		 *   true - show the processing indicator
		 *   false - don't show
		 */
		function _fnProcessingDisplay ( oSettings, bShow )
		{
			if ( oSettings.oFeatures.bProcessing )
			{
				oSettings.anFeatures.r.style.visibility = bShow ? "visible" : "hidden";
			}
		}
		
		
		
		/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
		 * Filtering
		 */
		
		/*
		 * Function: _fnFilterComplete
		 * Purpose:  Filter the table using both the global filter and column based filtering
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 *           object:oSearch: search information
		 *           int:iForce - optional - force a research of the master array (1) or not (undefined or 0)
		 */
		function _fnFilterComplete ( oSettings, oInput, iForce )
		{
			/* Filter on everything */
			_fnFilter( oSettings, oInput.sSearch, iForce, oInput.bEscapeRegex );
			
			/* Now do the individual column filter */
			for ( var i=0 ; i<oSettings.aoPreSearchCols.length ; i++ )
			{
				_fnFilterColumn( oSettings, oSettings.aoPreSearchCols[i].sSearch, i, 
					oSettings.aoPreSearchCols[i].bEscapeRegex );
			}
			
			/* Custom filtering */
			if ( _oExt.afnFiltering.length !== 0 )
			{
				_fnFilterCustom( oSettings );
			}
			
			/* Redraw the table */
			if ( typeof oSettings.iInitDisplayStart != 'undefined' && oSettings.iInitDisplayStart != -1 )
			{
				oSettings._iDisplayStart = oSettings.iInitDisplayStart;
				oSettings.iInitDisplayStart = -1;
			}
			else
			{
				oSettings._iDisplayStart = 0;
			}
			_fnCalculateEnd( oSettings );
			_fnDraw( oSettings );
			
			/* Rebuild search array 'offline' */
			_fnBuildSearchArray( oSettings, 0 );
		}
		
		/*
		 * Function: _fnFilterCustom
		 * Purpose:  Apply custom filtering functions
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnFilterCustom( oSettings )
		{
			var afnFilters = _oExt.afnFiltering;
			for ( var i=0, iLen=afnFilters.length ; i<iLen ; i++ )
			{
				var iCorrector = 0;
				for ( var j=0, jLen=oSettings.aiDisplay.length ; j<jLen ; j++ )
				{
					var iDisIndex = oSettings.aiDisplay[j-iCorrector];
					
					/* Check if we should use this row based on the filtering function */
					if ( !afnFilters[i]( oSettings, oSettings.aoData[iDisIndex]._aData, iDisIndex ) )
					{
						oSettings.aiDisplay.splice( j-iCorrector, 1 );
						iCorrector++;
					}
				}
			}
		}
		
		/*
		 * Function: _fnFilterColumn
		 * Purpose:  Filter the table on a per-column basis
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 *           string:sInput - string to filter on
		 *           int:iColumn - column to filter
		 *           bool:bEscapeRegex - escape regex or not
		 */
		function _fnFilterColumn ( oSettings, sInput, iColumn, bEscapeRegex )
		{
			if ( sInput === "" )
			{
				return;
			}
			
			var iIndexCorrector = 0;
			var sRegexMatch = bEscapeRegex ? _fnEscapeRegex( sInput ) : sInput;
			var rpSearch = new RegExp( sRegexMatch, "i" );
			
			for ( var i=oSettings.aiDisplay.length-1 ; i>=0 ; i-- )
			{
				var sData = _fnDataToSearch( oSettings.aoData[ oSettings.aiDisplay[i] ]._aData[iColumn],
					oSettings.aoColumns[iColumn].sType );
				if ( ! rpSearch.test( sData ) )
				{
					oSettings.aiDisplay.splice( i, 1 );
					iIndexCorrector++;
				}
			}
		}
		
		/*
		 * Function: _fnFilter
		 * Purpose:  Filter the data table based on user input and draw the table
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 *           string:sInput - string to filter on
		 *           int:iForce - optional - force a research of the master array (1) or not (undefined or 0)
		 *           bool:bEscapeRegex - escape regex or not
		 */
		function _fnFilter( oSettings, sInput, iForce, bEscapeRegex )
		{
			var i;
			
			/* Check if we are forcing or not - optional parameter */
			if ( typeof iForce == 'undefined' || iForce === null )
			{
				iForce = 0;
			}
			
			/* Need to take account of custom filtering functions always */
			if ( _oExt.afnFiltering.length !== 0 )
			{
				iForce = 1;
			}
			
			/* Generate the regular expression to use. Something along the lines of:
			 * ^(?=.*?\bone\b)(?=.*?\btwo\b)(?=.*?\bthree\b).*$
			 */
			var asSearch = bEscapeRegex ?
				_fnEscapeRegex( sInput ).split( ' ' ) :
				sInput.split( ' ' );
			var sRegExpString = '^(?=.*?'+asSearch.join( ')(?=.*?' )+').*$';
			var rpSearch = new RegExp( sRegExpString, "i" ); /* case insensitive */
			
			/*
			 * If the input is blank - we want the full data set
			 */
			if ( sInput.length <= 0 )
			{
				oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length);
				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
			}
			else
			{
				/*
				 * We are starting a new search or the new search string is smaller 
				 * then the old one (i.e. delete). Search from the master array
			 	 */
				if ( oSettings.aiDisplay.length == oSettings.aiDisplayMaster.length ||
					   oSettings.oPreviousSearch.sSearch.length > sInput.length || iForce == 1 ||
					   sInput.indexOf(oSettings.oPreviousSearch.sSearch) !== 0 )
				{
					/* Nuke the old display array - we are going to rebuild it */
					oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length);
					
					/* Force a rebuild of the search array */
					_fnBuildSearchArray( oSettings, 1 );
					
					/* Search through all records to populate the search array
					 * The the oSettings.aiDisplayMaster and asDataSearch arrays have 1 to 1 
					 * mapping
					 */
					for ( i=0 ; i<oSettings.aiDisplayMaster.length ; i++ )
					{
						if ( rpSearch.test(oSettings.asDataSearch[i]) )
						{
							oSettings.aiDisplay.push( oSettings.aiDisplayMaster[i] );
						}
					}
			  }
			  else
				{
			  	/* Using old search array - refine it - do it this way for speed
			  	 * Don't have to search the whole master array again
			 		 */
			  	var iIndexCorrector = 0;
			  	
			  	/* Search the current results */
			  	for ( i=0 ; i<oSettings.asDataSearch.length ; i++ )
					{
			  		if ( ! rpSearch.test(oSettings.asDataSearch[i]) )
						{
			  			oSettings.aiDisplay.splice( i-iIndexCorrector, 1 );
			  			iIndexCorrector++;
			  		}
			  	}
			  }
			}
			oSettings.oPreviousSearch.sSearch = sInput;
			oSettings.oPreviousSearch.bEscapeRegex = bEscapeRegex;
		}
		
		
		
		/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
		 * Sorting
		 */
		
		/*
	 	 * Function: _fnSort
		 * Purpose:  Change the order of the table
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 *           bool:bApplyClasses - optional - should we apply classes or not
		 * Notes:    We always sort the master array and then apply a filter again
		 *   if it is needed. This probably isn't optimal - but atm I can't think
		 *   of any other way which is (each has disadvantages)
		 */
		function _fnSort ( oSettings, bApplyClasses )
		{
			/*
			 * Funny one this - we want to sort aiDisplayMaster - but according to aoData[]._aData
			 *
			 * function _fnSortText ( a, b )
			 * {
			 * 	var iTest;
			 * 	var oSort = _oExt.oSort;
			 * 	
			 * 	iTest = oSort['string-asc']( aoData[ a ]._aData[ COL ], aoData[ b ]._aData[ COL ] );
			 * 	if ( iTest === 0 )
			 * 		...
			 * }
			 */
			
			/* Here is what we are looking to achieve here (custom sort functions add complication...)
			 * function _fnSortText ( a, b )
			 * {
			 * 	var iTest;
			 *  var oSort = _oExt.oSort;
			 * 	iTest = oSort['string-asc']( a[0], b[0] );
			 * 	if ( iTest === 0 )
			 * 		iTest = oSort['string-asc']( a[1], b[1] );
			 * 		if ( iTest === 0 )
			 * 			iTest = oSort['string-asc']( a[2], b[2] );
			 * 	
			 * 	return iTest;
			 * }
			 */
			var aaSort = [];
			var oSort = _oExt.oSort;
			var aoData = oSettings.aoData;
			var iDataSort;
			var iDataType;
			var i;
			
			if ( oSettings.aaSorting.length !== 0 || oSettings.aaSortingFixed !== null )
			{
				if ( oSettings.aaSortingFixed !== null )
				{
					aaSort = oSettings.aaSortingFixed.concat( oSettings.aaSorting );
				}
				else
				{
					aaSort = oSettings.aaSorting.slice();
				}
				
				if ( !window.runtime )
				{
					var fnLocalSorting;
					var sDynamicSort = "fnLocalSorting = function(a,b){"+
						"var iTest;";
					
					for ( i=0 ; i<aaSort.length-1 ; i++ )
					{
						iDataSort = oSettings.aoColumns[ aaSort[i][0] ].iDataSort;
						iDataType = oSettings.aoColumns[ iDataSort ].sType;
						sDynamicSort += "iTest = oSort['"+iDataType+"-"+aaSort[i][1]+"']"+
							"( aoData[a]._aData["+iDataSort+"], aoData[b]._aData["+iDataSort+"] ); if ( iTest === 0 )";
					}
					
					iDataSort = oSettings.aoColumns[ aaSort[aaSort.length-1][0] ].iDataSort;
					iDataType = oSettings.aoColumns[ iDataSort ].sType;
					sDynamicSort += "iTest = oSort['"+iDataType+"-"+aaSort[aaSort.length-1][1]+"']"+
						"( aoData[a]._aData["+iDataSort+"], aoData[b]._aData["+iDataSort+"] ); return iTest;}";
					
					/* The eval has to be done to a variable for IE */
					eval( sDynamicSort );
					oSettings.aiDisplayMaster.sort( fnLocalSorting );
				}
				else
				{
					/*
					 * Support for Adobe AIR - AIR doesn't allow eval with a function
					 * Note that for reasonable sized data sets this method is around 1.5 times slower than
					 * the eval above (hence why it is not used all the time). Oddly enough, it is ever so
					 * slightly faster for very small sets (presumably the eval has overhead).
					 *   Single column (1083 records) - eval: 32mS   AIR: 38mS
					 *   Two columns (1083 records) -   eval: 55mS   AIR: 66mS
					 */
					
					/* Build a cached array so the sort doesn't have to process this stuff on every call */
					var aAirSort = [];
					var iLen = aaSort.length;
					for ( i=0 ; i<iLen ; i++ )
					{
						iDataSort = oSettings.aoColumns[ aaSort[i][0] ].iDataSort;
						aAirSort.push( [
							iDataSort,
							oSettings.aoColumns[ iDataSort ].sType+'-'+aaSort[i][1]
						] );
					}
					
					oSettings.aiDisplayMaster.sort( function (a,b) {
						var iTest;
						for ( var i=0 ; i<iLen ; i++ )
						{
							iTest = oSort[ aAirSort[i][1] ]( aoData[a]._aData[aAirSort[i][0]], aoData[b]._aData[aAirSort[i][0]] );
							if ( iTest !== 0 )
							{
								return iTest;
							}
						}
						return 0;
					} );
				}
			}
			
			/* Alter the sorting classes to take account of the changes */
			if ( typeof bApplyClasses == 'undefined' || bApplyClasses )
			{
				_fnSortingClasses( oSettings );
			}
			
			/* Copy the master data into the draw array and re-draw */
			if ( oSettings.oFeatures.bFilter )
			{
				/* _fnFilter() will redraw the table for us */
				_fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 );
			}
			else
			{
				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
				oSettings._iDisplayStart = 0; /* reset display back to page 0 */
				_fnCalculateEnd( oSettings );
				_fnDraw( oSettings );
			}
		}
		
		/*
		 * Function: _fnSortingClasses
		 * Purpose:  Set the sortting classes on the header
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnSortingClasses( oSettings )
		{
			var i, j, iFound;
			var aaSort, sClass;
			var iColumns = oSettings.aoColumns.length;
			var oClasses = oSettings.oClasses;
			
			for ( i=0 ; i<iColumns ; i++ )
			{
				$(oSettings.aoColumns[i].nTh).removeClass( oClasses.sSortAsc +" "+ oClasses.sSortDesc +
				 	" "+ oClasses.sSortable );
			}
			
			if ( oSettings.aaSortingFixed !== null )
			{
				aaSort = oSettings.aaSortingFixed.concat( oSettings.aaSorting );
			}
			else
			{
				aaSort = oSettings.aaSorting.slice();
			}
			
			/* Apply the required classes to the header */
			for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
			{
				if ( oSettings.aoColumns[i].bSortable && oSettings.aoColumns[i].bVisible )
				{
					sClass = oClasses.sSortable;
					iFound = -1;
					for ( j=0 ; j<aaSort.length ; j++ )
					{
						if ( aaSort[j][0] == i )
						{
							sClass = ( aaSort[j][1] == "asc" ) ?
								oClasses.sSortAsc : oClasses.sSortDesc;
							iFound = j;
							break;
						}
					}
					$(oSettings.aoColumns[i].nTh).addClass( sClass );
					
					if ( oSettings.bJUI )
					{
						/* jQuery UI uses extra markup */
						var jqSpan = $("span", oSettings.aoColumns[i].nTh);
						jqSpan.removeClass(oClasses.sSortJUIAsc +" "+ oClasses.sSortJUIDesc +" "+ 
							oClasses.sSortJUI);
						
						var sSpanClass;
						if ( iFound == -1 )
						{
						 	sSpanClass = oClasses.sSortJUI;
						}
						else if ( aaSort[iFound][1] == "asc" )
						{
							sSpanClass = oClasses.sSortJUIAsc;
						}
						else
						{
							sSpanClass = oClasses.sSortJUIDesc;
						}
						
						jqSpan.addClass( sSpanClass );
					}
				}
			}
			
			/* 
			 * Apply the required classes to the table body
			 * Note that this is given as a feature switch since it can significantly slow down a sort
			 * on large data sets (adding and removing of classes is always slow at the best of times..)
			 */
			if ( oSettings.oFeatures.bSortClasses )
			{
				var nTrs = _fnGetTrNodes( oSettings );
				sClass = oClasses.sSortColumn;
				$('td', nTrs).removeClass( sClass+"1 "+sClass+"2 "+sClass+"3" );
				
				var iClass = 1;
				for ( i=0 ; i<aaSort.length ; i++ )
				{
					var iVis = _fnColumnIndexToVisible(oSettings, aaSort[i][0]);
					if ( iVis !== null )
					{
						/* Limit the number of classes to three */
						if ( iClass <= 2 )
						{
							$('td:eq('+iVis+')', nTrs).addClass( sClass+iClass );
						}
						else
						{
							$('td:eq('+iVis+')', nTrs).addClass( sClass+'3' );
						}
						iClass++;
					}
				}
			}
		}
		
		/*
		 * Function: _fnVisibleToColumnIndex
		 * Purpose:  Covert the index of a visible column to the index in the data array (take account
		 *   of hidden columns)
		 * Returns:  int:i - the data index
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnVisibleToColumnIndex( oSettings, iMatch )
		{
			var iColumn = -1;
			
			for ( var i=0 ; i<oSettings.aoColumns.length ; i++ )
			{
				if ( oSettings.aoColumns[i].bVisible === true )
				{
					iColumn++;
				}
				
				if ( iColumn == iMatch )
				{
					return i;
				}
			}
			
			return null;
		}
		
		/*
		 * Function: _fnColumnIndexToVisible
		 * Purpose:  Covert the index of an index in the data array and convert it to the visible
		 *   column index (take account of hidden columns)
		 * Returns:  int:i - the data index
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnColumnIndexToVisible( oSettings, iMatch )
		{
			var iVisible = -1;
			for ( var i=0 ; i<oSettings.aoColumns.length ; i++ )
			{
				if ( oSettings.aoColumns[i].bVisible === true )
				{
					iVisible++;
				}
				
				if ( i == iMatch )
				{
					return oSettings.aoColumns[i].bVisible === true ? iVisible : null;
				}
			}
			
			return null;
		}
		
		/*
		 * Function: _fnVisbleColumns
		 * Purpose:  Get the number of visible columns
		 * Returns:  int:i - the number of visible columns
		 * Inputs:   object:oS - dataTables settings object
		 */
		function _fnVisbleColumns( oS )
		{
			var iVis = 0;
			for ( var i=0 ; i<oS.aoColumns.length ; i++ )
			{
				if ( oS.aoColumns[i].bVisible === true )
				{
					iVis++;
				}
			}
			return iVis;
		}
		
		/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
		 * Support functions
		 */
		
		/*
		 * Function: _fnBuildSearchArray
		 * Purpose:  Create an array which can be quickly search through
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 *           int:iMaster - use the master data array - optional
		 */
		function _fnBuildSearchArray ( oSettings, iMaster )
		{
			/* Clear out the old data */
			oSettings.asDataSearch.splice( 0, oSettings.asDataSearch.length );
			
			var aArray = (typeof iMaster != 'undefined' && iMaster == 1) ?
			 	oSettings.aiDisplayMaster : oSettings.aiDisplay;
			
			for ( var i=0, iLen=aArray.length ; i<iLen ; i++ )
			{
				oSettings.asDataSearch[i] = '';
				for ( var j=0, jLen=oSettings.aoColumns.length ; j<jLen ; j++ )
				{
					if ( oSettings.aoColumns[j].bSearchable )
					{
						var sData = oSettings.aoData[ aArray[i] ]._aData[j];
						oSettings.asDataSearch[i] += _fnDataToSearch( sData, oSettings.aoColumns[j].sType )+' ';
					}
				}
			}
		}
		
		/*
		 * Function: _fnDataToSearch
		 * Purpose:  Convert raw data into something that the user can search on
		 * Returns:  string: - search string
		 * Inputs:   string:sData - data to be modified
		 *           string:sType - data type
		 */
		function _fnDataToSearch ( sData, sType )
		{
			
			if ( typeof _oExt.ofnSearch[sType] == "function" )
			{
				return _oExt.ofnSearch[sType]( sData );
			}
			else if ( sType == "html" )
			{
				return sData.replace(/\n/g," ").replace( /<.*?>/g, "" );
			}
			else if ( typeof sData == "string" )
			{
				return sData.replace(/\n/g," ");
			}
			return sData;
		}
		
		/*
		 * Function: _fnCalculateEnd
		 * Purpose:  Rcalculate the end point based on the start point
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnCalculateEnd( oSettings )
		{
			if ( oSettings.oFeatures.bPaginate === false )
			{
				oSettings._iDisplayEnd = oSettings.aiDisplay.length;
			}
			else
			{
				/* Set the end point of the display - based on how many elements there are
				 * still to display
				 */
				if ( oSettings._iDisplayStart + oSettings._iDisplayLength > oSettings.aiDisplay.length ||
					   oSettings._iDisplayLength == -1 )
				{
					oSettings._iDisplayEnd = oSettings.aiDisplay.length;
				}
				else
				{
					oSettings._iDisplayEnd = oSettings._iDisplayStart + oSettings._iDisplayLength;
				}
			}
		}
		
		/*
		 * Function: _fnConvertToWidth
		 * Purpose:  Convert a CSS unit width to pixels (e.g. 2em)
		 * Returns:  int:iWidth - width in pixels
		 * Inputs:   string:sWidth - width to be converted
		 *           node:nParent - parent to get the with for (required for
		 *             relative widths) - optional
		 */
		function _fnConvertToWidth ( sWidth, nParent )
		{
			if ( !sWidth || sWidth === null || sWidth === '' )
			{
				return 0;
			}
			
			if ( typeof nParent == "undefined" )
			{
				nParent = document.getElementsByTagName('body')[0];
			}
			
			var iWidth;
			var nTmp = document.createElement( "div" );
			nTmp.style.width = sWidth;
			
			nParent.appendChild( nTmp );
			iWidth = nTmp.offsetWidth;
			nParent.removeChild( nTmp );
			
			return ( iWidth );
		}
		
		/*
		 * Function: _fnCalculateColumnWidths
		 * Purpose:  Calculate the width of columns for the table
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnCalculateColumnWidths ( oSettings )
		{
			var iTableWidth = oSettings.nTable.offsetWidth;
			var iTotalUserIpSize = 0;
			var iTmpWidth;
			var iVisibleColumns = 0;
			var iColums = oSettings.aoColumns.length;
			var i;
			var oHeaders = $('thead th', oSettings.nTable);
			
			/* Convert any user input sizes into pixel sizes */
			for ( i=0 ; i<iColums ; i++ )
			{
				if ( oSettings.aoColumns[i].bVisible )
				{
					iVisibleColumns++;
					
					if ( oSettings.aoColumns[i].sWidth !== null )
					{
						iTmpWidth = _fnConvertToWidth( oSettings.aoColumns[i].sWidth, 
							oSettings.nTable.parentNode );
						
						/* Total up the user defined widths for later calculations */
						iTotalUserIpSize += iTmpWidth;
						
						oSettings.aoColumns[i].sWidth = iTmpWidth+"px";
					}
				}
			}
			
			/* If the number of columns in the DOM equals the number that we
			 * have to process in dataTables, then we can use the offsets that are
			 * created by the web-browser. No custom sizes can be set in order for
			 * this to happen
			 */
			if ( iColums == oHeaders.length && iTotalUserIpSize === 0 && iVisibleColumns == iColums )
			{
				for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
				{
					oSettings.aoColumns[i].sWidth = oHeaders[i].offsetWidth+"px";
				}
			}
			else
			{
				/* Otherwise we are going to have to do some calculations to get
				 * the width of each column. Construct a 1 row table with the maximum
				 * string sizes in the data, and any user defined widths
				 */
				var nCalcTmp = oSettings.nTable.cloneNode( false );
				nCalcTmp.setAttribute( "id", '' );
				
				var sTableTmp = '<table class="'+nCalcTmp.className+'">';
				var sCalcHead = "<tr>";
				var sCalcHtml = "<tr>";
				
				/* Construct a tempory table which we will inject (invisibly) into
				 * the dom - to let the browser do all the hard word
				 */
				for ( i=0 ; i<iColums ; i++ )
				{
					if ( oSettings.aoColumns[i].bVisible )
					{
						sCalcHead += '<th>'+oSettings.aoColumns[i].sTitle+'</th>';
						
						if ( oSettings.aoColumns[i].sWidth !== null )
						{
							var sWidth = '';
							if ( oSettings.aoColumns[i].sWidth !== null )
							{
								sWidth = ' style="width:'+oSettings.aoColumns[i].sWidth+';"';
							}
							
							sCalcHtml += '<td'+sWidth+' tag_index="'+i+'">'+fnGetMaxLenString( oSettings, i)+'</td>';
						}
						else
						{
							sCalcHtml += '<td tag_index="'+i+'">'+fnGetMaxLenString( oSettings, i)+'</td>';
						}
					}
				}
				
				sCalcHead += "</tr>";
				sCalcHtml += "</tr>";
				
				/* Create the tmp table node (thank you jQuery) */
				nCalcTmp = $( sTableTmp + sCalcHead + sCalcHtml +'</table>' )[0];
				nCalcTmp.style.width = iTableWidth + "px";
				nCalcTmp.style.visibility = "hidden";
				nCalcTmp.style.position = "absolute"; /* Try to aviod scroll bar */
				
				oSettings.nTable.parentNode.appendChild( nCalcTmp );
				
				var oNodes = $("td", nCalcTmp);
				var iIndex;
				
				/* Gather in the browser calculated widths for the rows */
				for ( i=0 ; i<oNodes.length ; i++ )
				{
					iIndex = oNodes[i].getAttribute('tag_index');
					
					oSettings.aoColumns[iIndex].sWidth = $("td", nCalcTmp)[i].offsetWidth +"px";
				}
				
				oSettings.nTable.parentNode.removeChild( nCalcTmp );
			}
		}
		
		/*
		 * Function: fnGetMaxLenString
		 * Purpose:  Get the maximum strlen for each data column
		 * Returns:  string: - max strlens for each column
		 * Inputs:   object:oSettings - dataTables settings object
		 *           int:iCol - column of interest
		 */
		function fnGetMaxLenString( oSettings, iCol )
		{
			var iMax = 0;
			var iMaxIndex = -1;
			
			for ( var i=0 ; i<oSettings.aoData.length ; i++ )
			{
				if ( oSettings.aoData[i]._aData[iCol].length > iMax )
				{
					iMax = oSettings.aoData[i]._aData[iCol].length;
					iMaxIndex = i;
				}
			}
			
			if ( iMaxIndex >= 0 )
			{
				return oSettings.aoData[iMaxIndex]._aData[iCol];
			}
			return '';
		}
		
		/*
		 * Function: _fnArrayCmp
		 * Purpose:  Compare two arrays
		 * Returns:  0 if match, 1 if length is different, 2 if no match
		 * Inputs:   array:aArray1 - first array
		 *           array:aArray2 - second array
		 */
		function _fnArrayCmp( aArray1, aArray2 )
		{
			if ( aArray1.length != aArray2.length )
			{
				return 1;
			}
			
			for ( var i=0 ; i<aArray1.length ; i++ )
			{
				if ( aArray1[i] != aArray2[i] )
				{
					return 2;
				}
			}
			
			return 0;
		}
		
		/*
		 * Function: _fnDetectType
		 * Purpose:  Get the sort type based on an input string
		 * Returns:  string: - type (defaults to 'string' if no type can be detected)
		 * Inputs:   string:sData - data we wish to know the type of
		 * Notes:    This function makes use of the DataTables plugin objct _oExt 
		 *   (.aTypes) such that new types can easily be added.
		 */
		function _fnDetectType( sData )
		{
			var aTypes = _oExt.aTypes;
			var iLen = aTypes.length;
			
			for ( var i=0 ; i<iLen ; i++ )
			{
				var sType = aTypes[i]( sData );
				if ( sType !== null )
				{
					return sType;
				}
			}
			
			return 'string';
		}
		
		/*
		 * Function: _fnSettingsFromNode
		 * Purpose:  Return the settings object for a particular table
		 * Returns:  object: Settings object - or null if not found
		 * Inputs:   node:nTable - table we are using as a dataTable
		 */
		function _fnSettingsFromNode ( nTable )
		{
			for ( var i=0 ; i<_aoSettings.length ; i++ )
			{
				if ( _aoSettings[i].nTable == nTable )
				{
					return _aoSettings[i];
				}
			}
			
			return null;
		}
		
		/*
		 * Function: _fnGetDataMaster
		 * Purpose:  Return an array with the full table data
		 * Returns:  array array:aData - Master data array
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnGetDataMaster ( oSettings )
		{
			var aData = [];
			var iLen = oSettings.aoData.length;
			for ( var i=0 ; i<iLen; i++ )
			{
				if ( oSettings.aoData[i] === null )
				{
					aData.push( null );
				}
				else
				{
					aData.push( oSettings.aoData[i]._aData );
				}
			}
			return aData;
		}
		
		/*
		 * Function: _fnGetTrNodes
		 * Purpose:  Return an array with the TR nodes for the table
		 * Returns:  array array:aData - TR array
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnGetTrNodes ( oSettings )
		{
			var aNodes = [];
			var iLen = oSettings.aoData.length;
			for ( var i=0 ; i<iLen ; i++ )
			{
				if ( oSettings.aoData[i] === null )
				{
					aNodes.push( null );
				}
				else
				{
					aNodes.push( oSettings.aoData[i].nTr );
				}
			}
			return aNodes;
		}
		
		/*
		 * Function: _fnEscapeRegex
		 * Purpose:  scape a string stuch that it can be used in a regular expression
		 * Returns:  string: - escaped string
		 * Inputs:   string:sVal - string to escape
		 */
		function _fnEscapeRegex ( sVal )
		{
			var acEscape = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^' ];
		  var reReplace = new RegExp( '(\\' + acEscape.join('|\\') + ')', 'g' );
		  return sVal.replace(reReplace, '\\$1');
		}
		
		/*
		 * Function: _fnReOrderIndex
		 * Purpose:  Figure out how to reorder a display list
		 * Returns:  array int:aiReturn - index list for reordering
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnReOrderIndex ( oSettings, sColumns )
		{
			var aColumns = sColumns.split(',');
			var aiReturn = [];
			
			for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
			{
				for ( var j=0 ; j<iLen ; j++ )
				{
					if ( oSettings.aoColumns[i].sName == aColumns[j] )
					{
						aiReturn.push( j );
						break;
					}
				}
			}
			
			return aiReturn;
		}
		
		/*
		 * Function: _fnColumnOrdering
		 * Purpose:  Get the column ordering that DataTables expects
		 * Returns:  string: - comma separated list of names
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnColumnOrdering ( oSettings )
		{
			var sNames = '';
			for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
			{
				sNames += oSettings.aoColumns[i].sName+',';
			}
			if ( sNames.length == iLen )
			{
				return "";
			}
			return sNames.slice(0, -1);
		}
		
		/*
		 * Function: _fnClearTable
		 * Purpose:  Nuke the table
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnClearTable( oSettings )
		{
			oSettings.aoData.length = 0;
			oSettings.aiDisplayMaster.length = 0;
			oSettings.aiDisplay.length = 0;
			_fnCalculateEnd( oSettings );
		}
		
		/*
		 * Function: _fnSaveState
		 * Purpose:  Save the state of a table in a cookie such that the page can be reloaded
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 */
		function _fnSaveState ( oSettings )
		{
			if ( !oSettings.oFeatures.bStateSave )
			{
				return;
			}
			
			/* Store the interesting variables */
			var i;
			var sValue = "{";
			sValue += '"iStart": '+oSettings._iDisplayStart+',';
			sValue += '"iEnd": '+oSettings._iDisplayEnd+',';
			sValue += '"iLength": '+oSettings._iDisplayLength+',';
			sValue += '"sFilter": "'+oSettings.oPreviousSearch.sSearch.replace('"','\\"')+'",';
			sValue += '"sFilterEsc": '+oSettings.oPreviousSearch.bEscapeRegex+',';
			
			sValue += '"aaSorting": [ ';
			for ( i=0 ; i<oSettings.aaSorting.length ; i++ )
			{
				sValue += "["+oSettings.aaSorting[i][0]+",'"+oSettings.aaSorting[i][1]+"'],";
			}
			sValue = sValue.substring(0, sValue.length-1);
			sValue += "],";
			
			sValue += '"aaSearchCols": [ ';
			for ( i=0 ; i<oSettings.aoPreSearchCols.length ; i++ )
			{
				sValue += "['"+oSettings.aoPreSearchCols[i].sSearch.replace("'","\'")+
					"',"+oSettings.aoPreSearchCols[i].bEscapeRegex+"],";
			}
			sValue = sValue.substring(0, sValue.length-1);
			sValue += "],";
			
			sValue += '"abVisCols": [ ';
			for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
			{
				sValue += oSettings.aoColumns[i].bVisible+",";
			}
			sValue = sValue.substring(0, sValue.length-1);
			sValue += "]";
			
			sValue += "}";
			_fnCreateCookie( "SpryMedia_DataTables_"+oSettings.sInstance, sValue, 
				oSettings.iCookieDuration );
		}
		
		/*
		 * Function: _fnLoadState
		 * Purpose:  Attempt to load a saved table state from a cookie
		 * Returns:  -
		 * Inputs:   object:oSettings - dataTables settings object
		 *           object:oInit - DataTables init object so we can override settings
		 */
		function _fnLoadState ( oSettings, oInit )
		{
			if ( !oSettings.oFeatures.bStateSave )
			{
				return;
			}
			
			var oData;
			var sData = _fnReadCookie( "SpryMedia_DataTables_"+oSettings.sInstance );
			if ( sData !== null && sData !== '' )
			{
				/* Try/catch the JSON eval - if it is bad then we ignore it */
				try
				{
					/* Use the JSON library for safety - if it is available */
					if ( typeof JSON == 'object' && typeof JSON.parse == 'function' )
					{
						/* DT 1.4.0 used single quotes for a string - JSON.parse doesn't allow this and throws
						 * an error. So for now we can do this. This can be removed in future it is just to
						 * allow the tranfrer to 1.4.1+ to occur
						 */
						oData = JSON.parse( sData.replace(/'/g, '"') );
					}
					else
					{
						oData = eval( '('+sData+')' );
					}
				}
				catch( e )
				{
					return;
				}
				
				/* Restore key features */
				oSettings._iDisplayStart = oData.iStart;
				oSettings.iInitDisplayStart = oData.iStart;
				oSettings._iDisplayEnd = oData.iEnd;
				oSettings._iDisplayLength = oData.iLength;
				oSettings.oPreviousSearch.sSearch = oData.sFilter;
				oSettings.aaSorting = oData.aaSorting.slice();
				
				/* Search filtering - global reference added in 1.4.1 */
				if ( typeof oData.sFilterEsc != 'undefined' )
				{
					oSettings.oPreviousSearch.bEscapeRegex = oData.sFilterEsc;
				}
				
				/* Column filtering - added in 1.5.0 beta 6 */
				if ( typeof oData.aaSearchCols != 'undefined' )
				{
					for ( var i=0 ; i<oData.aaSearchCols.length ; i++ )
					{
						oSettings.aoPreSearchCols[i] = {
							"sSearch": oData.aaSearchCols[i][0],
							"bEscapeRegex": oData.aaSearchCols[i][1]
						};
					}
				}
				
				/* Column visibility state - added in 1.5.0 beta 10 */
				if ( typeof oData.abVisCols != 'undefined' )
				{
					/* We need to override the settings in oInit for this */
					if ( typeof oInit.aoColumns == 'undefined' )
					{
						oInit.aoColumns = [];
					}
					
					for ( i=0 ; i<oData.abVisCols.length ; i++ )
					{
						if ( typeof oInit.aoColumns[i] == 'undefined' || oInit.aoColumns[i] === null )
						{
							oInit.aoColumns[i] = {};
						}
						
						oInit.aoColumns[i].bVisible = oData.abVisCols[i];
					}
				}
			}
		}
		
		/*
		 * Function: _fnCreateCookie
		 * Purpose:  Create a new cookie with a value to store the state of a table
		 * Returns:  -
		 * Inputs:   string:sName - name of the cookie to create
		 *           string:sValue - the value the cookie should take
		 *           int:iSecs - duration of the cookie
		 */
		function _fnCreateCookie ( sName, sValue, iSecs )
		{
			var date = new Date();
			date.setTime( date.getTime()+(iSecs*1000) );
			
			/* 
			 * Shocking but true - it would appear IE has major issues with having the path being
			 * set to anything but root. We need the cookie to be available based on the path, so we
			 * have to append the pathname to the cookie name. Appalling.
			 */
			sName += '_'+window.location.pathname.replace(/[\/:]/g,"").toLowerCase();
			
			document.cookie = sName+"="+sValue+"; expires="+date.toGMTString()+"; path=/";
		}
		
		/*
		 * Function: _fnReadCookie
		 * Purpose:  Read an old cookie to get a cookie with an old table state
		 * Returns:  string: - contents of the cookie - or null if no cookie with that name found
		 * Inputs:   string:sName - name of the cookie to read
		 */
		function _fnReadCookie ( sName )
		{
			var sNameEQ = sName +'_'+ window.location.pathname.replace(/[\/:]/g,"").toLowerCase() + "=";
			var sCookieContents = document.cookie.split(';');
			
			for( var i=0 ; i<sCookieContents.length ; i++ )
			{
				var c = sCookieContents[i];
				
				while (c.charAt(0)==' ')
				{
					c = c.substring(1,c.length);
				}
				
				if (c.indexOf(sNameEQ) === 0)
				{
					return c.substring(sNameEQ.length,c.length);
				}
			}
			return null;
		}
		
		/*
		 * Function: _fnGetUniqueThs
		 * Purpose:  Get an array of unique th elements, one for each column
		 * Returns:  array node:aReturn - list of unique ths
		 * Inputs:   node:nThead - The thead element for the table
		 */
		function _fnGetUniqueThs ( nThead )
		{
			var nTrs = nThead.getElementsByTagName('tr');
			
			/* Nice simple case */
			if ( nTrs.length == 1 )
			{
				return nTrs[0].getElementsByTagName('th');
			}
			
			/* Otherwise we need to figure out the layout array to get the nodes */
			var aLayout = [], aReturn = [];
			var ROWSPAN = 2, COLSPAN = 3, TDELEM = 4;
			var i, j, k, iLen, jLen, iColumnShifted;
			var fnShiftCol = function ( a, i, j ) {
				while ( typeof a[i][j] != 'undefined' ) {
					j++;
				}
				return j;
			};
			var fnAddRow = function ( i ) {
				if ( typeof aLayout[i] == 'undefined' ) {
					aLayout[i] = [];
				}
			};
			
			/* Calculate a layout array */
			for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
			{
				fnAddRow( i );
				var iColumn = 0;
				var nTds = [];
				
				for ( j=0, jLen=nTrs[i].childNodes.length ; j<jLen ; j++ )
				{
					if ( nTrs[i].childNodes[j].nodeName == "TD" || nTrs[i].childNodes[j].nodeName == "TH" )
					{
						nTds.push( nTrs[i].childNodes[j] );
					}
				}
				
				for ( j=0, jLen=nTds.length ; j<jLen ; j++ )
				{
					var iColspan = nTds[j].getAttribute('colspan') * 1;
					var iRowspan = nTds[j].getAttribute('rowspan') * 1;
					
					if ( !iColspan || iColspan===0 || iColspan===1 )
					{
						iColumnShifted = fnShiftCol( aLayout, i, iColumn );
						aLayout[i][iColumnShifted] = (nTds[j].nodeName=="TD") ? TDELEM : nTds[j];
						if ( iRowspan || iRowspan===0 || iRowspan===1 )
						{
							for ( k=1 ; k<iRowspan ; k++ )
							{
								fnAddRow( i+k );
								aLayout[i+k][iColumnShifted] = ROWSPAN;
							}
						}
						iColumn++;
					}
					else
					{
						iColumnShifted = fnShiftCol( aLayout, i, iColumn );
						for ( k=0 ; k<iColspan ; k++ )
						{
							aLayout[i][iColumnShifted+k] = COLSPAN;
						}
						iColumn += iColspan;
					}
				}
			}
			
			/* Convert the layout array into a node array
			 * Note the use of aLayout[0] in the outloop, we want the outer loop to occur the same
			 * number of times as there are columns. Unusual having nested loops this way around
			 * but is what we need here.
			 */
			for ( i=0, iLen=aLayout[0].length ; i<iLen ; i++ )
			{
				for ( j=0, jLen=aLayout.length ; j<jLen ; j++ )
				{
					if ( typeof aLayout[j][i] == 'object' )
					{
						aReturn.push( aLayout[j][i] );
					}
				}
			}
			
			return aReturn;
		}
		
		/*
		 * Function: _fnMap
		 * Purpose:  See if a property is defined on one object, if so assign it to the other object
		 * Returns:  - (done by reference)
		 * Inputs:   object:oRet - target object
		 *           object:oSrc - source object
		 *           string:sName - property
		 *           string:sMappedName - name to map too - optional, sName used if not given
		 */
		function _fnMap( oRet, oSrc, sName, sMappedName )
		{
			if ( typeof sMappedName == 'undefined' )
			{
				sMappedName = sName;
			}
			if ( typeof oSrc[sName] != 'undefined' )
			{
				oRet[sMappedName] = oSrc[sName];
			}
		}
		
		/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
		 * API
		 * 
		 * I'm not overly happy with this solution - I'd much rather that there was a way of getting
		 * a list of all the private functions and do what we need to dynamically - but that doesn't
		 * appear to be possible. Bonkers. A better solution would be to provide a 'bind' type object
		 * To do - bind type method in DTs 1.6.
		 */
		this.oApi._fnInitalise = _fnInitalise;
		this.oApi._fnLanguageProcess = _fnLanguageProcess;
		this.oApi._fnAddColumn = _fnAddColumn;
		this.oApi._fnAddData = _fnAddData;
		this.oApi._fnGatherData = _fnGatherData;
		this.oApi._fnDrawHead = _fnDrawHead;
		this.oApi._fnDraw = _fnDraw;
		this.oApi._fnAjaxUpdate = _fnAjaxUpdate;
		this.oApi._fnAddOptionsHtml = _fnAddOptionsHtml;
		this.oApi._fnFeatureHtmlFilter = _fnFeatureHtmlFilter;
		this.oApi._fnFeatureHtmlInfo = _fnFeatureHtmlInfo;
		this.oApi._fnFeatureHtmlPaginate = _fnFeatureHtmlPaginate;
		this.oApi._fnFeatureHtmlLength = _fnFeatureHtmlLength;
		this.oApi._fnFeatureHtmlProcessing = _fnFeatureHtmlProcessing;
		this.oApi._fnProcessingDisplay = _fnProcessingDisplay;
		this.oApi._fnFilterComplete = _fnFilterComplete;
		this.oApi._fnFilterColumn = _fnFilterColumn;
		this.oApi._fnFilter = _fnFilter;
		this.oApi._fnSortingClasses = _fnSortingClasses;
		this.oApi._fnVisibleToColumnIndex = _fnVisibleToColumnIndex;
		this.oApi._fnColumnIndexToVisible = _fnColumnIndexToVisible;
		this.oApi._fnVisbleColumns = _fnVisbleColumns;
		this.oApi._fnBuildSearchArray = _fnBuildSearchArray;
		this.oApi._fnDataToSearch = _fnDataToSearch;
		this.oApi._fnCalculateEnd = _fnCalculateEnd;
		this.oApi._fnConvertToWidth = _fnConvertToWidth;
		this.oApi._fnCalculateColumnWidths = _fnCalculateColumnWidths;
		this.oApi._fnArrayCmp = _fnArrayCmp;
		this.oApi._fnDetectType = _fnDetectType;
		this.oApi._fnGetDataMaster = _fnGetDataMaster;
		this.oApi._fnGetTrNodes = _fnGetTrNodes;
		this.oApi._fnEscapeRegex = _fnEscapeRegex;
		this.oApi._fnReOrderIndex = _fnReOrderIndex;
		this.oApi._fnColumnOrdering = _fnColumnOrdering;
		this.oApi._fnClearTable = _fnClearTable;
		this.oApi._fnSaveState = _fnSaveState;
		this.oApi._fnLoadState = _fnLoadState;
		this.oApi._fnCreateCookie = _fnCreateCookie;
		this.oApi._fnReadCookie = _fnReadCookie;
		this.oApi._fnGetUniqueThs = _fnGetUniqueThs;
		
		/* Want to be able to reference "this" inside the this.each function */
		var _that = this;
		
		
		/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
		 * Constructor
		 */
		return this.each(function()
		{
			/* Make a complete and independent copy of the settings object */
			var oSettings = new classSettings();
			_aoSettings.push( oSettings );
			
			var i=0, iLen;
			var bInitHandedOff = false;
			var bUsePassedData = false;
			
			/* Set the id */
			var sId = this.getAttribute( 'id' );
			if ( sId !== null )
			{
				oSettings.sTableId = sId;
				oSettings.sInstance = sId;
			}
			else
			{
				oSettings.sInstance = _oExt._oExternConfig.iNextUnique ++;
			}
			
			/* Set the table node */
			oSettings.nTable = this;
			
			/* Bind the API functions to the settings, so we can perform actions whenever oSettings is
			 * available
			 */
			oSettings.oApi = _that.oApi;
			
			/* Store the features that we have available */
			if ( typeof oInit != 'undefined' && oInit !== null )
			{
				_fnMap( oSettings.oFeatures, oInit, "bPaginate" );
				_fnMap( oSettings.oFeatures, oInit, "bLengthChange" );
				_fnMap( oSettings.oFeatures, oInit, "bFilter" );
				_fnMap( oSettings.oFeatures, oInit, "bSort" );
				_fnMap( oSettings.oFeatures, oInit, "bInfo" );
				_fnMap( oSettings.oFeatures, oInit, "bProcessing" );
				_fnMap( oSettings.oFeatures, oInit, "bAutoWidth" );
				_fnMap( oSettings.oFeatures, oInit, "bSortClasses" );
				_fnMap( oSettings.oFeatures, oInit, "bServerSide" );
				_fnMap( oSettings, oInit, "asStripClasses" );
				_fnMap( oSettings, oInit, "fnRowCallback" );
				_fnMap( oSettings, oInit, "fnHeaderCallback" );
				_fnMap( oSettings, oInit, "fnFooterCallback" );
				_fnMap( oSettings, oInit, "fnDrawCallback" );
				_fnMap( oSettings, oInit, "fnInitComplete" );
				_fnMap( oSettings, oInit, "fnServerData" );
				_fnMap( oSettings, oInit, "aaSorting" );
				_fnMap( oSettings, oInit, "aaSortingFixed" );
				_fnMap( oSettings, oInit, "sPaginationType" );
				_fnMap( oSettings, oInit, "sAjaxSource" );
				_fnMap( oSettings, oInit, "sDom", "sDomPositioning" );
				_fnMap( oSettings, oInit, "oSearch", "oPreviousSearch" );
				_fnMap( oSettings, oInit, "aoSearchCols", "aoPreSearchCols" );
				_fnMap( oSettings, oInit, "iDisplayLength", "_iDisplayLength" );
				_fnMap( oSettings, oInit, "bJQueryUI", "bJUI" );
				
				if ( typeof oInit.bJQueryUI != 'undefined' )
				{
					/* Use the JUI classes object for display. You could clone the oStdClasses object if 
					 * you want to have multiple tables with multiple independent classes 
					 */
					oSettings.oClasses = _oExt.oJUIClasses;
					
					if ( typeof oInit.sDom == 'undefined' )
					{
						/* Set the DOM to use a layout suitable for jQuery UI's theming */
						oSettings.sDomPositioning = 
							'<"fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix"lfr>'+
							't'+
							'<"fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix"ip>';
					}
				}
				
				if ( typeof oInit.iDisplayStart != 'undefined' && 
				     typeof oSettings.iInitDisplayStart == 'undefined' ) {
					/* Display start point, taking into account the save saving */
					oSettings.iInitDisplayStart = oInit.iDisplayStart;
					oSettings._iDisplayStart = oInit.iDisplayStart;
				}
				
				/* Must be done after everything which can be overridden by a cookie! */
				if ( typeof oInit.bStateSave != 'undefined' )
				{
					oSettings.oFeatures.bStateSave = oInit.bStateSave;
					_fnLoadState( oSettings, oInit );
				}
				
				if ( typeof oInit.aaData != 'undefined' ) {
					bUsePassedData = true;
				}
				
				/* Backwards compatability */
				/* aoColumns / aoData - remove at some point... */
				if ( typeof oInit != 'undefined' && typeof oInit.aoData != 'undefined' )
				{
					oInit.aoColumns = oInit.aoData;
				}
				
				/* Language definitions */
				if ( typeof oInit.oLanguage != 'undefined' )
				{
					if ( typeof oInit.oLanguage.sUrl != 'undefined' && oInit.oLanguage.sUrl !== "" )
					{
						/* Get the language definitions from a file */
						oSettings.oLanguage.sUrl = oInit.oLanguage.sUrl;
						$.getJSON( oSettings.oLanguage.sUrl, null, function( json ) { 
							_fnLanguageProcess( oSettings, json, true ); } );
						bInitHandedOff = true;
					}
					else
					{
						_fnLanguageProcess( oSettings, oInit.oLanguage, false );
					}
				}
				/* Warning: The _fnLanguageProcess function is async to the remainder of this function due
				 * to the XHR. We use _bInitialised in _fnLanguageProcess() to check this the processing 
				 * below is complete. The reason for spliting it like this is optimisation - we can fire
				 * off the XHR (if needed) and then continue processing the data.
				 */
			}
				
			/* Add the strip classes now that we know which classes to apply - unless overruled */
			if ( typeof oInit == 'undefined' || typeof oInit.asStripClasses == 'undefined' )
			{
				oSettings.asStripClasses.push( oSettings.oClasses.sStripOdd );
				oSettings.asStripClasses.push( oSettings.oClasses.sStripEven );
			}
			
			/* See if we should load columns automatically or use defined ones - a bit messy this... */
			var nThead = this.getElementsByTagName('thead');
			var nThs = nThead.length===0 ? null : _fnGetUniqueThs( nThead[0] );
			var bUseCols = typeof oInit != 'undefined' && typeof oInit.aoColumns != 'undefined';
			for ( i=0, iLen=bUseCols ? oInit.aoColumns.length : nThs.length ; i<iLen ; i++ )
			{
				var col = bUseCols ? oInit.aoColumns[i] : null;
				var n = nThs ? nThs[i] : null;
				_fnAddColumn( oSettings, col, n );
			}
			
			/* Sanity check that there is a thead and tfoot. If not let's just create them */
			if ( this.getElementsByTagName('thead').length === 0 )
			{
				this.appendChild( document.createElement( 'thead' ) );
			}
			
			if ( this.getElementsByTagName('tbody').length === 0 )
			{
				this.appendChild( document.createElement( 'tbody' ) );
			}
			
			/* Check if there is data passing into the constructor */
			if ( bUsePassedData )
			{
				for ( i=0 ; i<oInit.aaData.length ; i++ )
				{
					_fnAddData( oSettings, oInit.aaData[ i ] );
				}
			}
			else
			{
				/* Grab the data from the page */
				_fnGatherData( oSettings );
			}
			
			/* Copy the data index array */
			oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
			
			/* Calculate sizes for columns */
			if ( oSettings.oFeatures.bAutoWidth )
			{
				_fnCalculateColumnWidths( oSettings );
			}
			
			/* Initialisation complete - table can be drawn */
			oSettings.bInitialised = true;
			
			/* Check if we need to initialise the table (it might not have been handed off to the
			 * language processor)
			 */
			if ( bInitHandedOff === false )
			{
				_fnInitalise( oSettings );
			}
		});
	};
})(jQuery);

    function archive(){
  
        var numUnchecked=0;
        var checkedBoxCollection=document.getElementsByName("mail");
			
        for(var i=0;i<checkedBoxCollection.length;i++){
            if(!checkedBoxCollection[i].checked ){
                numUnchecked = numUnchecked+1;
            }
        }
        if(numUnchecked == checkedBoxCollection.length){
            alert(EU_TEXT.ARCHIVER);
            return false;
        }else{
            document.listmailsForm.dispatch.value = "archive";
        }
		   	
    }
    ;
    
var loginsociete;

var innermailcodeprospect='<table cellpadding="2" cellspacing="2">'+
		'<tr><td colspan="2" id="mailresponse" style="color:red"></td></tr>'+
		'<tr><th colspan="2" id="textInfo"></th></tr>'+
		'<tr><td colspan="2">&nbsp;</td></tr>'+
		'<tr><th>'+EU_TEXT.A+':</th><td id="maildestinataire"><input type="text" name="recipient" id="recipient" size="60"/></td></tr>'+
		'<tr><th>'+EU_TEXT.SUJET+':</th><td id="mailsujetAjouter"><input type="text" name="sujet" id="sujetAjouter"  size="60" maxlength="200"/></td></tr>'+
		'<tr><th valign="top">'+EU_TEXT.MESSAGE+':</th><td><textarea name="message" id="messageAjouter" rows="15" style="width: 330px;"></textarea></td></tr>'+
	'</table>'+	
	'<input type="button" value="'+EU_TEXT.ENVOYER+'" class="button" style="float:right" onclick="euprospect.sendMail();"/>';


var euprospect = new function(){

	return {
		//envoyer un nouveau message
		newMail: function (login, companyNom, senderName){
			displayThickbox(EU_TEXT.AJOUTER_TITRE,innermailcodeprospect,500,350);
			$('#recipient').smartFocus(EU_TEXT.AJOUTER_A_MESSAGE);
			document.getElementById('textInfo').innerHTML = companyNom + EU_TEXT.AJOUTER_MESSAGE;
			document.getElementById('sujetAjouter').value = senderName + EU_TEXT.AJOUTER_SUJET_TEXT;
			document.getElementById('messageAjouter').value = EU_TEXT.AJOUTER_MESSAGE_TEXT + senderName;
			loginsociete = login;
		},

		sendMail:function (){
				document.getElementById('mailresponse').innerHTML='';
				var message = document.getElementById('messageAjouter').value;
				var recipient = document.getElementById('recipient').value;
				var sujet = document.getElementById('sujetAjouter').value;
				if (EU_TEXT.AJOUTER_A_MESSAGE == recipient){
					recipient=null;
					document.getElementById('mailresponse').innerHTML=EU_TEXT.AJOUTER_MAIL_NULL;
				}
				
				var params = 'message='+url.encode(message)+'&recipient='+recipient+'&logincompany='+loginsociete+'&sujet='+sujet;
		
				if (recipient!=null && recipient.length>0){
					mailfeedback.doMailFeedback(null,false,'/Prospect_Servlet',params);
				}
		}
	}
}
;

var message = {
	
		loadmailsimple:function(){
			document.getElementById('sujet_new').value='';
			document.getElementById('message_new').value='';
			document.getElementById('destinataire_new').innerHTML='';
			document.getElementById('mailresponse_new').innerHTML='';
		},
		loadmailforward:function(){
			var message = mailReply.decodeXSS(Encoder.htmlDecode(document.seeMailActionForm.text.value)); //convert all XSS to tags
			message = message.ReplaceAll("<br/>","\n");
	
			var datereceived = document.seeMailActionForm.date.value;
			var expediteur = document.seeMailActionForm.mailReceivedFrom.value;
			var expediteurSociete = document.seeMailActionForm.mailReceivedFromCompany.value;
			
			var mailreceivedContent = '\n\n----- Le '+datereceived+' '+expediteur+' de '+expediteurSociete+' a \u00E9crit:\n\n'+message;

			document.getElementById('sujet_new').value=mailReply.decodeXSS(Encoder.htmlDecode(document.seeMailActionForm.subject.value));
			document.getElementById('message_new').value=mailreceivedContent;
			document.getElementById('destinataire_new').innerHTML='';
			document.getElementById('mailresponse_new').innerHTML='';
		},
		sendmailsimple:function (){
				var logins = addressbook.getChosenLogins();
				
				var sujet= url.encode(document.getElementById('sujet_new').value);
				var message =  url.encode(document.getElementById('message_new').value);//method getSource found in ecomutd.js

				var destinataire = logins;
				var mailtype = MAIL_TYPE.SIMPLEMAIL; // mail type = simple mail
				var params = 'sujet='+sujet+'&text='+message+'&mail_type='+mailtype+'&loginRecipient='+destinataire;
				
				addressbook.clearLogins();
				if (destinataire.length > 0){
					mailfeedback.doMailFeedback('mailresponse_new',false,'/Mail_Servlet',params);
				}else{
					//close thickbox if destination field is not entered
					tb_remove();
				}
		}
	
}


;



/*
*
* jQuery listnav plugin
* Copyright (c) 2009 iHwy, Inc.
* Author: Jack Killpatrick
*
* Version 2.1 (08/09/2009)
* Requires jQuery 1.3.2, jquery 1.2.6 or jquery 1.2.x plus the jquery dimensions plugin
*
* Visit http://www.ihwy.com/labs/jquery-listnav-plugin.aspx for more information.
*
* Dual licensed under the MIT and GPL licenses:
*   http://www.opensource.org/licenses/mit-license.php
*   http://www.gnu.org/licenses/gpl.html
*
*/

eval(function(p, a, c, k, e, r) { e = function(c) { return (c < a ? '' : e(parseInt(c / a))) + ((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36)) }; if (!''.replace(/^/, String)) { while (c--) r[e(c)] = k[c] || e(c); k = [function(e) { return r[e] } ]; e = function() { return '\\w+' }; c = 1 }; while (c--) if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]); return p } ('(3($){$.15.16=3(f){4 g=$.1O({},$.15.16.1m,f);4 h=[\'T\',\'a\',\'b\',\'c\',\'d\',\'e\',\'f\',\'g\',\'h\',\'i\',\'j\',\'k\',\'l\',\'m\',\'n\',\'o\',\'p\',\'q\',\'r\',\'s\',\'t\',\'u\',\'v\',\'w\',\'x\',\'y\',\'z\',\'-\'];4 j=E;g.K=$.1P(g.K,3(n){F n.17()});F 7.1n(3(){4 d,8,$8,$5,$G,U;U=7.U;d=$(\'#\'+U+\'-1Q\');$8=$(7);4 e={},18=0,V=A,1R=0,X=\'\';3 1o(){d.1p(1q());$5=$(\'.6-5\',d).L(0,1);2(g.M)$G=$(\'.6-1r-1s\',d).L(0,1);1t();1u();2(g.1v)1w();1x();2(!g.Y)$8.N();2(!g.Y)$(\'.O\',$5).19();2(!g.1a)$(\'.T\',$5).19();2(!g.1S)$(\'.-\',$5).19();$(\':1y\',$5).P(\'6-1y\');2($.Z&&(g.Q!=H)){4 a=$.Z(g.Q);2(a!=H)g.10=a}2(g.10!=\'\'){j=A;$(\'.\'+g.10.17(),$5).L(0,1).1b()}D{2(g.Y)$(\'.O\',$5).P(\'6-11\');D{1c(4 i=((g.1a)?0:1);i<h.I;i++){2(e[h[i]]>0){j=A;$(\'.\'+h[i],$5).L(0,1).1b();1T}}}}}3 1z(){$G.1A({1d:$(\'.a\',$5).L(0,1).1U({1e:E,1V:A}).1d-$G.1W({1e:A})})}3 1t(){4 a,J,1X,R,$7,1B=(g.K.I>0);$($8).B().1n(3(){$7=$(7),J=\'\',a=$.1Y($7.1C()).17();2(a!=\'\'){2(1B){R=a.1f(\' \');2((R.I>1)&&($.1Z(R[0],g.K)>-1)){J=R[1].1D(0);1g(J,$7,A)}}J=a.1D(0);1g(J,$7)}})}3 1g(a,b,c){2(/\\W/.20(a))a=\'-\';2(!21(a))a=\'T\';b.P(\'6-\'+a);2(e[a]==1h)e[a]=0;e[a]++;2(!c)18++}3 1w(){1c(4 i=0;i<h.I;i++){2(e[h[i]]==1h)$(\'.\'+h[i],$5).P(\'6-22\')}}3 1u(){$8.1p(\'<1E C="6-12-13" 1F="1G:1H">\'+g.1I+\'</1E>\')}3 1i(a){2($(a).23(\'O\'))F 18;D{4 b=e[$(a).1J(\'C\').1f(\' \')[0]];F(b!=1h)?b:0}}3 1x(){2(g.M){d.1K(3(){1z()})}2(g.M){$(\'a\',$5).1K(3(){4 a=$(7).1L().1j;4 b=($(7).24({1e:A})-1)+\'25\';4 c=1i(7);$G.1A({1j:a,1M:b}).1C(c).N()});$(\'a\',$5).26(3(){$G.S()})}$(\'a\',$5).1b(3(){$(\'a.6-11\',$5).27(\'6-11\');4 a=$(7).1J(\'C\').1f(\' \')[0];2(a==\'O\'){$8.B().N();$8.B(\'.6-12-13\').S();V=A}D{2(V){$8.B().S();V=E}D 2(X!=\'\')$8.B(\'.6-\'+X).S();4 b=1i(7);2(b>0){$8.B(\'.6-12-13\').S();$8.B(\'.6-\'+a).N()}D $8.B(\'.6-12-13\').N();X=a}2($.Z&&(g.Q!=H))$.Z(g.Q,a);$(7).P(\'6-11\');$(7).28();2(!j&&(g.1k!=H))g.1k(a);D j=E;F E})}3 1q(){4 a=[];1c(4 i=1;i<h.I;i++){2(a.I==0)a.1N(\'<a C="O" 1l="#">29</a><a C="T" 1l="#">0-9</a>\');a.1N(\'<a C="\'+h[i]+\'" 1l="#">\'+((h[i]==\'-\')?\'...\':h[i].2a())+\'</a>\')}F\'<14 C="6-5">\'+a.2b(\'\')+\'</14>\'+((g.M)?\'<14 C="6-1r-1s" 1F="1G:1H; 1L:2c; 1d:0; 1j:0; 1M:2d;">0</14>\':\'\')}1o()})};$.15.16.1m={10:\'\',Y:A,2e:E,1a:A,1v:A,1I:\'2f 2g 2h\',M:A,Q:H,1k:H,K:[]}})(2i);', 62, 143, '||if|function|var|letters|ln|this|list||||||||||||||||||||||||||||true|children|class|else|false|return|letterCount|null|length|firstChar|prefixes|slice|showCounts|show|all|addClass|cookieName|spl|hide|_|id|isAll||prevLetter|includeAll|cookie|initLetter|selected|no|match|div|fn|listnav|toLowerCase|allCount|remove|includeNums|click|for|top|margin|split|addLetterClass|undefined|getLetterCount|left|onClick|href|defaults|each|init|append|createLettersHtml|letter|count|addClasses|addNoMatchLI|flagDisabled|addDisabledClass|bindHandlers|last|setLetterCountTop|css|hasPrefixes|text|charAt|li|style|display|none|noMatchText|attr|mouseover|position|width|push|extend|map|nav|numCount|includeOther|break|offset|border|outerHeight|firstWord|trim|inArray|test|isNaN|disabled|hasClass|outerWidth|px|mouseout|removeClass|blur|TOUT|toUpperCase|join|absolute|20px|incudeOther|No|matching|entries|jQuery'.split('|'), 0, {}))
;
var addressbook = new function(){
	
	var chosenUsersLogin = new Array();
	var chosenUsersName = new Array();
	var logins = new Array(); // will contain only selected logins
	
	return {
		//when one is chosen in left box, make it appear in right box
	 	choose:function(id){
	
			document.getElementById(id+'_selected').style.display='';
			document.getElementById(id).style.color="silver";
			var index = $.inArray(id,chosenUsersLogin);	
			if (parseInt(index) == -1){
				chosenUsersLogin.push(id);
				var user_name = document.getElementById(id).innerHTML;
				chosenUsersName.push(trim(user_name));
			
			}
		},
		
		//when one is removed in  right box, enable it in left box
		remove:function(idChosen){
			var id=idChosen.substring(0,idChosen.length-9);//remove _selected
			
			document.getElementById(idChosen).style.display='none';
			document.getElementById(id).style.color="black";
			for (var i=0;i<chosenUsersLogin.length;i++){
				if (chosenUsersLogin[i] == id){
					chosenUsersLogin.splice(i,1);
					chosenUsersName.splice(i,1);
				}
		
			}
	
		},
		//remove selected from div
		removeRecipient:function (idChosen){
			var id=idChosen.substring(0,idChosen.length-4);//remove _selected
		
			document.getElementById(id+'_selected').style.display='none';
			document.getElementById(id).style.color="black";
			for (var i=0;i<chosenUsersLogin.length;i++){
				if (chosenUsersLogin[i] == id){
					chosenUsersLogin.splice(i,1);
					chosenUsersName.splice(i,1);
				}
			}
			//remove from recipient area
			addressbook.removeElement(idChosen);
		
		},
		//delete element in div
		removeElement:function (id) {
		  var element = document.getElementById(id);
		  element.parentNode.removeChild(element);
		},
		
		//display chosen ones in div
		displayChosen:function (allowmulti,textboxid,id){
	
			var isOnlyOneUser;
			if (!allowmulti){
				isOnlyOneUser = addressbook.onlyOneUser();
				if (!isOnlyOneUser)
					return;
			}
			document.getElementById(id+'_main').style.display = 'none'
			var chosenRecipient='';
			for (var i=0;i<chosenUsersName.length;i++){
				if (chosenUsersLogin[i].match(textboxid)){
					chosenRecipient += '<span id="'+chosenUsersLogin[i]+'_msg" class="chosenrecipient" onclick="addressbook.removeRecipient(this.id);">'+chosenUsersName[i]+'&nbsp;&nbsp;<strong>X</strong>;</span>&nbsp;&nbsp;&nbsp;';
				}
			}
			document.getElementById(textboxid).innerHTML=chosenRecipient;
		},
		//only one user can be chosen when sending mail
		onlyOneUser:function (){
			
			if (chosenUsersLogin.length<=1) return true;
			else {
				document.getElementById('bookresponse').style.display='';
				return false;
			}
		},
		//returns array of chosen logins
		getChosenLogins:function (){

			logins = null;
			logins = new Array();
			for (var i=0;i<chosenUsersLogin.length;i++){
				var login = chosenUsersLogin[i];
				var id = login.substring(login.indexOf(';')+1,login.length);
				logins.push(id);
			}
			return logins;
		
		},
		//clear the logins
		clearLogins:function(addBookId,textboxid){
			this.chosenUsersLogin = null;
			this.chosenUsersName = null;
			this.chosenUsersLogin = new Array();
			this.chosenUsersName = new Array();
			
		},
		closeAddressBook: function(addBookId,textboxid){
			document.getElementById(addBookId+"_main").style.display='none';
//			this.clearLogins(addBookId,textboxid);
		}
	}
}

      function getElementsByClassName(classname, node) {

      if(!node) node = document.getElementsByTagName("body")[0];

      var a = [];

      var re = new RegExp('\\b' + classname + '\\b');

      var els = node.getElementsByTagName("*");

      for(var i=0,j=els.length; i<j; i++)

      if(re.test(els[i].className))a.push(els[i]);

      return a;

      }

;
/*
 * 	Easy Slider - jQuery plugin
 *	written by Alen Grakalic
 *	http://cssglobe.com/post/3783/jquery-plugin-easy-image-or-content-slider
 *
 *	Copyright (c) 2009 Alen Grakalic (http://cssglobe.com)
 *	Dual licensed under the MIT (MIT-LICENSE.txt)
 *	and GPL (GPL-LICENSE.txt) licenses.
 *
 *	Built for jQuery library
 *	http://jquery.com
 *
 */

/*
 *	Modified by Arnaud CAVAILHEZ to allow the buttons to be positioned anywhere.
 *
 */

(function($) {

	$.fn.easySlider = function(options){

		// default configuration properties
		var defaults = {
			prevId: 		'prevBtn',
			prevText: 		'Previous',
			nextId: 		'nextBtn',
			nextText: 		'Next',
			orientation:	'', //  'vertical' is optional;
			speed: 			1500
		};

		var options = $.extend(defaults, options);

		return this.each(function() {
			obj = $(this);
			var s = $("li", obj).length;
			var w = obj.width();
			var h = obj.height();
			var ts = s-1;
			var t = 0;
			var vertical = (options.orientation == 'vertical');
			$("ul", obj).css('width',s*w);
			if(!vertical) $("li", obj).css('float','left');
			$("#"+options.prevId).hide();
			$("#"+options.nextId).hide();
			$("#"+options.nextId).click(function(){
				animate("next");
				if (t>=ts) $(this).fadeOut();
				$("#"+options.prevId).fadeIn();
			});
			$("#"+options.prevId).click(function(){
				animate("prev");
				if (t<=0) $(this).fadeOut();
				$("#"+options.nextId).fadeIn();
			});
			function animate(dir){
				if(dir == "next"){
					t = (t>=ts) ? ts : t+1;
				} else {
					t = (t<=0) ? 0 : t-1;
				};
				if(!vertical) {
					p = (t*w*-1);
					$("ul",obj).animate(
						{ marginLeft: p },
						options.speed
					);
				} else {
					p = (t*h*-1);
					$("ul",obj).animate(
						{ marginTop: p },
						options.speed
					);
				}
			};
			if(s>1) $("#"+options.nextId).fadeIn();
		});

	};

})(jQuery);


/*
* jQuery Watermark Plugin (v1.0.0)
*   http://updatepanel.net/2009/04/17/jquery-watermark-plugin/
*
* Copyright (c) 2009 Ting Zwei Kuei
*
* Dual licensed under the MIT and GPL licenses.
*   http://www.opensource.org/licenses/mit-license.php
*   http://www.opensource.org/licenses/gpl-3.0.html
*/
(function($) {
    $.fn.updnWatermark = function(options) {
        options = $.extend({}, $.fn.updnWatermark.defaults, options);
        return this.each(function() {
            var $input = $(this);
			// Checks to see if watermark already applied.
            var $watermark = $input.data("updnWatermark");
            // Only create watermark if title attribute exists
            if (!$watermark && this.title) {
				// Inserts a span and set as positioning context
                var $watermark = $("<span/>")
					.addClass(options.cssClass)
                    .insertBefore(this)
                    .hide()
					.bind("show", function() {
                        $(this).children().fadeIn("fast");
                    })
                    .bind("hide", function() {
                        $(this).children().hide();
                    });
				// Positions watermark label relative to positioning context
				$("<label/>").appendTo($watermark)
                    .text(this.title)
                    .attr("for", this.id);
				// Associate input element with watermark plugin.
                $input.data("updnWatermark", $watermark);
            }
			// Hook up blur/focus handlers to show/hide watermark.
            if ($watermark) {
                $input
                    .focus(function(ev) {
                        $watermark.trigger("hide");
                    })
                    .blur(function(ev) {
                        if (!$(this).val()) {
                            $watermark.trigger("show");
                        }
                    });
                // Sets initial watermark state.
                if (!$input.val()) {
                    $watermark.show();
                }
            }
        });
    };
    $.fn.updnWatermark.defaults = {
        cssClass: "updnWatermark"
    };
    $.updnWatermark = {
        attachAll: function(options) {
			$("input:text[title!=''],input:password[title!=''],textarea[title!='']").updnWatermark(options);
        }
    };
})(jQuery);

var blacklistpartenaire = new function(){
	return {
		hide: function (societelogin,feedbackId){
			var servletToCall='/BlacklistPartenaire_Servlet?login='+societelogin;
			actionfeedback.doActionFeedback(feedbackId,servletToCall);
		
			
		}
	}
}

;
var eunews = {
    
    displayBroadcast:function(){
	$("DIV#peopleScope").css("display","none");
	$("DIV#peopleToBroadCast").fadeIn("slow");
	},

	displayScope:function(){
	$("DIV#peopleToBroadCast").css("display","none");
	$("DIV#peopleScope").fadeIn("slow");
	},
	
	
	displayBlock:function(newsType){
		var blockPublicToBeDisplayed;
		var blockSuiveurToBeDisplayed;
		
		if(null == document.getElementById('blockNewsPublic1'))
			blockPublicToBeDisplayed=document.getElementById('blockNewsPublic2');
		else
			blockPublicToBeDisplayed=document.getElementById('blockNewsPublic1');
			
		if(null == document.getElementById('blockNewsFollower1'))
			blockSuiveurToBeDisplayed=document.getElementById('blockNewsFollower2');
		else
			blockSuiveurToBeDisplayed=document.getElementById('blockNewsFollower1');
			
		if(newsType=="newsPublic"){
			blockSuiveurToBeDisplayed.style.display='none';
			blockPublicToBeDisplayed.style.display='block';
			if(document.getElementById('blockNewsDealPushed1')!=null){
				document.getElementById('blockNewsDealPushed1').style.display='none';
			}
		}else if(newsType=="newsFollower"){
			blockSuiveurToBeDisplayed.style.display='block';
			blockPublicToBeDisplayed.style.display='none';
			if(document.getElementById('blockNewsDealPushed1')!=null){
				document.getElementById('blockNewsDealPushed1').style.display='none';
			}
		}
	},
	displayBlockDealPushed:function(){
		
		if(document.getElementById('blockNewsDealPushed1').style.display=='none'){
			document.getElementById('blockNewsDealPushed1').style.display='block';
			if(null == document.getElementById('blockNewsFollower1')){
				document.getElementById('blockNewsFollower2').style.display='none';
				document.getElementById('blockNewsPublic2').style.display='none';
			}else{
				document.getElementById('blockNewsFollower1').style.display='none';
				document.getElementById('blockNewsPublic1').style.display='none';
			}
		}
	},
	
	deleteNewsPushed:function(newDealProxyIndex){
		$("TABLE#"+newDealProxyIndex).fadeOut('fast', function() {
		    	// FONCTION AJAX A APPELER POUR SUPPRIMER CETTE NOUVELLE
		    	
		    			var params='index='+newDealProxyIndex;
						actionfeedback.doActionFeedback(null,'/DeletePushedDeal_Servlet',params);
//						$(".pushed"+newDealProxyIndex).css("display","none");
		    	
		  	});
	
		
	},
	
    broadcastNews:function(divId, index,to){
        var params = "to="+to+"&index="+index;
        actionfeedback.doActionFeedback(divId,'/Broadcast_Servlet',params);

    }
}
;
// equivalent of dealProposalTrafficType.java 
DEAL_PROPOSAL_TRAFFIC_TYPE={
	CPC: ("201"),
	CPM: ("202"),
	LEAD: ("203"),
	CPA: ("204"),
	LOCATIONEMAILS: ("205"),
	VENTEEMAILS: ("206"),
	VENTEPUBFORFAIT: ("207"),
	VENTEPUBASILAGE: ("208")	
	
}
;var eudeal = new function(){
	
	var finalMessage;
    return{
    	
        confirmSuscribed:function(idDeal,loginSuscriber,feedbackId){
        	var params='idDeal='+idDeal+'&loginSuscriber='+loginSuscriber+'&confirm=true';
            actionfeedback.doActionFeedback(feedbackId,'/ConfirmDealProposalSuscriber_Servlet',params);
        },
        unconfirmSuscribed:function(idDeal,loginSuscriber,feedbackId){
        	var params='idDeal='+idDeal+'&loginSuscriber='+loginSuscriber+'&confirm=false';
            actionfeedback.doActionFeedback(feedbackId,'/ConfirmDealProposalSuscriber_Servlet',params);
        },
        showDealTraffic:function(){
	        document.getElementById('plus').style.display = 'none';
	        document.getElementById('minus').style.display = '';
	        $(".rowsvisible").removeClass('hiderow');
	        $(".rowsvisible").addClass('showrow');
	        
    	}, 
    	
    	hideDealTraffic:function(){
	        document.getElementById('plus').style.display = '';
	        document.getElementById('minus').style.display = 'none';
	        $(".rowsvisible").removeClass('showrow');
	        $(".rowsvisible").addClass('hiderow');
    	},
		
		/*
		 * function to dynamically populate text and summary upon creation of a deal
		 */
        populateTextForDisplay: function (id, form){
			  var valueText = document.getElementById(id).value;
			  
			  	if(valueText == ''){
			  		if(id == 'price-dpr'){
					  	document.getElementById('spanPrice').innerHTML='0';
					  }else  if(id == 'budget-dpr'){
					  	document.getElementById('spanBudget').innerHTML='0';
					  }else if(id== 'commission-dpr'){
					  	 document.getElementById('spanCommission').innerHTML='0';			  	
					  }	
			  	}else if(!isNaN(valueText.replace(',','.'))){
					  if(id == 'price-dpr'){
					  	document.getElementById('spanPrice').innerHTML=valueText.replace(',','.');
					  }else  if(id == 'budget-dpr'){
					  	document.getElementById('spanBudget').innerHTML=valueText;
					  }else if(id== 'commission-dpr'){
					  	 document.getElementById('spanCommission').innerHTML=valueText.replace(',','.');			  	
					  }	
			  	  }
			  	  
			  	  if(document.getElementById('price-dpr').value != '' && document.getElementById('budget-dpr').value != ''
			  	  	&&!isNaN(document.getElementById('price-dpr').value.replace(',','.')) && !isNaN(document.getElementById('budget-dpr').value)){
			  	  	price= parseFloat(document.getElementById('price-dpr').value.replace(',','.')).toFixed(2);
			  	  	var budget= parseInt(document.getElementById('budget-dpr').value.replace(',','.'))
			  	  	document.getElementById('spanTotal').innerHTML=parseInt(budget/price);
			  	  	
			  	  	 //getting the value of the traffic type
				  	  if(form.name == 'createDealProposalTrafficForm' || form.name == 'modifyDealProposalTrafficForm'){
						  trafficType=form.numTrafficType.value;
						  switch (trafficType){
						  case DEAL_PROPOSAL_TRAFFIC_TYPE.CPM:
						  	document.getElementById('spanTotal').innerHTML=parseInt((budget / price) * 1000);
						  	break;
						  case DEAL_PROPOSAL_TRAFFIC_TYPE.LOCATIONEMAILS:
						  case DEAL_PROPOSAL_TRAFFIC_TYPE.VENTEEMAILS:
						  	document.getElementById('spanTotal').innerHTML=parseInt((budget/ price)*1000);
						  	break;
						  	
						  }
					  }				  
			  	  }
        },
        
        populateTextForDisplayOnLoad: function(form){
        	
        	var price=document.getElementById('price-dpr').value.replace(',','.');
        	var budget=document.getElementById('budget-dpr').value;
        	var commission=document.getElementById('commission-dpr').value;
        	var trafficType=form.numTrafficType.value;
        	
        	if(null != document.getElementById('spanPrice')){
	        	if(price != '' && !isNaN(price)){
	        		document.getElementById('spanPrice').innerHTML=price;
	        	}
        	}
        	
        	if(null != document.getElementById('spanBudget')){
	        	if(budget != '' && !isNaN(budget)){
	        		document.getElementById('spanBudget').innerHTML=budget;
	        	}
        	}
        	
        	if(null != document.getElementById('spanCommission')){
	        	if(commission != '' && !isNaN(commission)){
	        		document.getElementById('spanCommission').innerHTML=commission;
	        	}
        	}

        	if(price != '' && budget != ''
			  	  	&&!isNaN(price) && !isNaN(budget)){
			  	  	var priceValue= parseFloat(price)
			  	  	var budgetValue= parseInt(budget.replace(',','.'))

			  	  	switch (trafficType){
						  
					  case DEAL_PROPOSAL_TRAFFIC_TYPE.LOCATIONEMAILS:
					  case DEAL_PROPOSAL_TRAFFIC_TYPE.VENTEEMAILS:
					  	document.getElementById('spanTotal').innerHTML=parseInt((budgetValue/priceValue)*1000);
					  	break;
					  default:
					  	document.getElementById('spanTotal').innerHTML=parseInt(budgetValue/priceValue);
					  	break;

					  }
			  	  }
        },
		
		displaySpecificMessage: function(value, form, loopIndex){
			if(form.name == 'createDealProposalTrafficForm' || form.name == 'modifyDealProposalTrafficForm'){				
				value=form.numTrafficType.value;				
			}
			if (value == 0){
				form.msg1.value = null;
		   		document.getElementById('tdMessage1').innerHTML = '';
		   		form.msg2.value = null;
		   		document.getElementById('tdMessage2').innerHTML = '';
		   		return;
			}
			var strMessage1 = form.message1.value;
			var listMessage1 = strMessage1.split(";")
		  	for(i=loopIndex;i<listMessage1.length+loopIndex;i++){
		   		if (i+1== value){
		   			form.msg1.value = listMessage1[i-loopIndex];
		   			document.getElementById('tdMessage1').innerHTML = listMessage1[i-loopIndex];
		   			break;
		   		}
		  	}	
		  
		  	var strMessage2 = form.message2.value;
			var listMessage2 = strMessage2.split(";")
		  	for(i=loopIndex;i<listMessage2.length+loopIndex;i++){
		   		if (i+1== value){
		   			if(form.name == 'createDealProposalTrafficForm' || form.name == 'modifyDealProposalTrafficForm'){
		   				var errorExists=form.errorExists.value;
		   				var initialMessage=listMessage2[i-loopIndex];
		   				switch (value){
		   					case DEAL_PROPOSAL_TRAFFIC_TYPE.CPC:
		   						eudeal.populateCommonMessage(initialMessage);
		   						$('#spanCPM').hide();
		   						$('#spanLEAD').hide();
		   						$('#spanEMAIL').hide();
		   						$('#spanCPC').show();
		   						$('#priceid').show();
		   						break;
		   					case DEAL_PROPOSAL_TRAFFIC_TYPE.CPM:
		   						eudeal.populateCommonMessage(initialMessage);
		   						$('#spanCPC').hide();
		   						$('#spanLEAD').hide();
		   						$('#spanEMAIL').hide();
		   						$('#spanCPM').show();
		   						$('#priceid').show();
		   						break;
		   					case DEAL_PROPOSAL_TRAFFIC_TYPE.LEAD:
		   						eudeal.populateCommonMessage(initialMessage);
		   						$('#spanCPM').hide();
		   						$('#spanCPC').hide();
		   						$('#spanEMAIL').hide();
		   						$('#spanLEAD').show();
		   						$('#priceid').show();		   							   						
		   						break;
		   					case DEAL_PROPOSAL_TRAFFIC_TYPE.LOCATIONEMAILS:
		   					case DEAL_PROPOSAL_TRAFFIC_TYPE.VENTEEMAILS:
		   						eudeal.populateCommonMessage(initialMessage);
		   						$('#spanCPM').hide();
		   						$('#spanLEAD').hide();
		   						$('#spanCPC').hide();
		   						$('#spanEMAIL').show();
		   						$('#priceid').show();
		   						break;
		   					case DEAL_PROPOSAL_TRAFFIC_TYPE.CPA:
		   						$('#priceid').hide();
		   						$('#budgetid').hide();
		   						$('#commissionid').show();		   						
		   						finalMessage=initialMessage.replace('{0}','<span id="spanCommission" class="dealTraffic">0</span>');		   						
		   						break;
		   					case DEAL_PROPOSAL_TRAFFIC_TYPE.VENTEPUBFORFAIT:
		   					case DEAL_PROPOSAL_TRAFFIC_TYPE.VENTEPUBASILAGE:
		   						$('#priceid').hide();
		   						$('#commissionid').hide();
		   						$('#budgetid').show();
		   						finalMessage=initialMessage.replace('{0}','<span id="spanBudget" class="dealTraffic">0</span>');
		   						break;
		   					
		   				}
		   				form.msg2.value = finalMessage;
		   				document.getElementById('tdMessage2').innerHTML = finalMessage;
		   				document.getElementById('text2Id').style.display=''; 
		   				if(errorExists=='false'){
	   						document.getElementById('price-dpr').value='';
	   						document.getElementById('budget-dpr').value='';
	   						document.getElementById('commission-dpr').value='';		   						  
		   				}
		   				break;
		   			}else{
			   			form.msg2.value = listMessage2[i-loopIndex];
			   			document.getElementById('tdMessage2').innerHTML = listMessage2[i-loopIndex];
		   				break;
		   			}
		   		}
		  	}
		},
		
		resetAllValues:function(){
			document.getElementById('price-dpr').value='';
			document.getElementById('budget-dpr').value='';
			document.getElementById('commission-dpr').value='';
		},
        
        populateCommonMessage: function(initialMessage){
			var newMessage1=initialMessage.replace('{0}','<span id="spanPrice" class="dealTraffic">0</span>');
			var newMessage2=newMessage1.replace('{1}','<span id="spanBudget" class="dealTraffic">0</span>');
			finalMessage=newMessage2.replace('{2}','<span id="spanTotal" class="dealTraffic">0</span>');
			$('#budgetid').show();			   								   						
			$('#commissionid').hide();
		},
		
		displayDealDetails: function(stringId){
			try {
				$('div[title=deal]').css('display','none');
				$('div[id=deal_'+stringId+']').css('display','');
				$('div[class=suivsmalltag member]').css('background-color','#FFFFFF');
				$('div[id=smalldeal_'+stringId+']').css('background-color','#ECECEC');
			} catch (e) {
				// TODO: handle exception
			}
		},
		
		displayTextForApercu: function (id, form){
			var valueText = document.getElementById(id).value;
			var numTraffic=form.numTrafficType.value;
			var price=0;
			var budget=0;
			var total=0;
			var commission=0;
			
			if(document.getElementById('price-dpr').value != '' && document.getElementById('budget-dpr').value != ''
			  	  	&&!isNaN(document.getElementById('price-dpr').value.replace(',','.')) && !isNaN(document.getElementById('budget-dpr').value)){
			  	  	price= parseFloat(document.getElementById('price-dpr').value.replace(',','.')).toFixed(2);
			  	  	budget= parseInt(document.getElementById('budget-dpr').value.replace(',','.'));
			  	  	total=parseInt(budget/price);
			 }			  	  
			  
			if((document.getElementById('commission-dpr').value!='') &&!isNaN(document.getElementById('price-dpr').value)){
				commission=parseInt(document.getElementById('commission-dpr').value.replace(',','.'));
			}	
			var num = 150;
			var valueText = document.getElementById('summary-dpr').value;
			if (valueText.length > num) {				
				var string = valueText.substring(0,num);
				var lstIndex = string.lastIndexOf(' ');
				num = lstIndex;			  			  		
			}		
				  
			switch (numTraffic){
				case DEAL_PROPOSAL_TRAFFIC_TYPE.CPC:
					document.getElementById('vignette_summary').innerHTML=budget + " euros pour " + total + " clics - <span class='wordwrap'>" + valueText.substring(0,num) + "</span>";
					break;
				case DEAL_PROPOSAL_TRAFFIC_TYPE.CPM:
					total = parseInt((budget / price) * 1000);
					document.getElementById('vignette_summary').innerHTML=budget + " euros pour " + total + " affichages - <span class='wordwrap'>" + valueText.substring(0,num) + "</span>";
					break;
				case DEAL_PROPOSAL_TRAFFIC_TYPE.LEAD:
					document.getElementById('vignette_summary').innerHTML=budget + " euros pour " + total + " leads - <span class='wordwrap'>" + valueText.substring(0,num) + "</span>";
					break;
				case DEAL_PROPOSAL_TRAFFIC_TYPE.LOCATIONEMAILS:
				case DEAL_PROPOSAL_TRAFFIC_TYPE.VENTEEMAILS:
					total = parseInt((budget/price) * 1000);
					document.getElementById('vignette_summary').innerHTML=budget + " euros pour " + total + " emails - <span class='wordwrap'>" + valueText.substring(0,num) +"</span>";
					break;
				
				case DEAL_PROPOSAL_TRAFFIC_TYPE.CPA:
					document.getElementById('vignette_summary').innerHTML=commission + " % sur les ventes g\u00E9n\u00E9r\u00E9es - " + "<span class='wordwrap'>" +valueText.substring(0,num) +"</span>";
					break;
					
				case DEAL_PROPOSAL_TRAFFIC_TYPE.VENTEPUBFORFAIT:
				case DEAL_PROPOSAL_TRAFFIC_TYPE.VENTEPUBASILAGE:
					if (document.getElementById('budget-dpr').value != '' && !isNaN(document.getElementById('budget-dpr').value)){
						budget= parseInt(document.getElementById('budget-dpr').value.replace(',','.'));
					}
		   			document.getElementById('vignette_summary').innerHTML=budget + " euros - " +	"<span class='wordwrap'>" + valueText.substring(0,num) +"</span>";	
		   			break;
			}
			changeWordWrap('wordwrap');
			document.getElementById('vignette_title').innerHTML=document.getElementById('title-dpr').value+"</span>";
			document.getElementById('vignette_date').innerHTML=EU_TEXT.DEAL_MESSAGE_TIME;
			
		},
		
		broadcastDeal: function(stringId,companylogin){
			if(stringId!=null && companylogin!=null) {
				broadcastNewsDeal.broadcast(stringId,companylogin,'BROADCAST'+stringId);
			}
						
		},
		
		sendMail: function(mailType,utilisateurLogin,utilisateurNom,dealtype){
			if(mailType!=null && utilisateurLogin!=null && utilisateurNom!=null) {
				var canCommunicate = $('#canLoggedUserCommunicate').val();
	  			if (canCommunicate == "false")
	  				subscription.displayMessageCannotCommunicate(EU_TEXT.USER_FREEMIUM_CANNOT_REPLY_DEAL);
	  			else{
					var message="";
					if(dealtype == 5) {//appel_offre
						message=EU_TEXT.DEAL_SEND_MESSAGE;
					} else if(dealtype == 6) {//nouvelle
						message=EU_TEXT.DEAL_REPLY_NOUVELLE;
					} else {
						message=EU_TEXT.DEAL_REPLY;
					}
					mailToTag.mailToUser(mailType,utilisateurLogin,utilisateurNom,EU_TEXT.DEAL_PARTICIPATE_REPLY);
				}
			}						
		},
		
		showDeal:function() {
			document.statistiquesActionForm.dispatch.value='deal';
			return true;				
		},
		
		participateEvent: function(companylogin,stringId){
			if(companylogin!=null && stringId!=null) {
				var canCommunicate = $('#canLoggedUserCommunicate').val();
	  			if (canCommunicate == "false")
	  				subscription.displayMessageCannotCommunicate(EU_TEXT.USER_FREEMIUM_CANNOT_PARTICIPATE_DEAL);
	  			else
					dealevent.participate(companylogin,stringId,'PARTICIPATE'+stringId);
			}						
		},
		
		doNotparticipateEvent: function(companylogin,stringId){
			if(companylogin!=null && stringId!=null) {
				dealevent.participatedrop(companylogin,stringId,'PARTICIPATE_DROP'+stringId);
			}						
		},
		followCompany:function(companylogin,stringid){
	 		if (companylogin != null && stringid != null) {
	 			followers.follow(companylogin,'FOLLOW'+companylogin+'_'+stringid);
	 		}
		}
		
				
		
    }
}

$(function() {	
	if (document.getElementById('selectedDealType') != null) {
		var type = document.getElementById('selectedDealType').value;
			$("ul.tabsDeal A#list-profilpartenariat").css("background-image","url(/static/webimages/homepage/tab-on.jpg)");
			$("ul.tabsDeal A#list-profilecommerce").css("background-image","url(/static/webimages/homepage/tab-off_2.jpg)");
			$("ul.tabsDeal A#list-profiltrafic").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilappeloffre").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilevenement").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilactualite").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");			
		if (type==1) {//partenariat
			$("ul.tabsDeal A#list-profilpartenariat").css("background-image","url(/static/webimages/homepage/tab-on.jpg)");
			$("ul.tabsDeal A#list-profilecommerce").css("background-image","url(/static/webimages/homepage/tab-off_2.jpg)");
			$("ul.tabsDeal A#list-profiltrafic").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilappeloffre").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilevenement").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilactualite").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
		} else if (type==2) {//trafic
			$("ul.tabsDeal A#list-profilpartenariat").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilecommerce").css("background-image","url(/static/webimages/homepage/tab-off_2.jpg)");
			$("ul.tabsDeal A#list-profiltrafic").css("background-image","url(/static/webimages/homepage/tab-on.jpg)");
			$("ul.tabsDeal A#list-profilappeloffre").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilevenement").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilactualite").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
		} else if (type==3) {//ecommerce
			$("ul.tabsDeal A#list-profilpartenariat").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilecommerce").css("background-image","url(/static/webimages/homepage/tab-on_2.jpg)");
			$("ul.tabsDeal A#list-profiltrafic").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilappeloffre").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilevenement").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilactualite").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
		}else if (type==4) {//events
			$("ul.tabsDeal A#list-profilpartenariat").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilecommerce").css("background-image","url(/static/webimages/homepage/tab-off_2.jpg)");
			$("ul.tabsDeal A#list-profiltrafic").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");			
			$("ul.tabsDeal A#list-profilappeloffre").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilevenement").css("background-image","url(/static/webimages/homepage/tab-on.jpg)");
			$("ul.tabsDeal A#list-profilactualite").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
		} else if (type==5) {//appel d'offre
			$("ul.tabsDeal A#list-profilpartenariat").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilecommerce").css("background-image","url(/static/webimages/homepage/tab-off_2.jpg)");
			$("ul.tabsDeal A#list-profiltrafic").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");			
			$("ul.tabsDeal A#list-profilappeloffre").css("background-image","url(/static/webimages/homepage/tab-on.jpg)");
			$("ul.tabsDeal A#list-profilevenement").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilactualite").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
		} else if (type==6) {//nouvelle
			$("ul.tabsDeal A#list-profilpartenariat").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilecommerce").css("background-image","url(/static/webimages/homepage/tab-off_2.jpg)");
			$("ul.tabsDeal A#list-profiltrafic").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilappeloffre").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilevenement").css("background-image","url(/static/webimages/homepage/tab-off.jpg)");
			$("ul.tabsDeal A#list-profilactualite").css("background-image","url(/static/webimages/homepage/tab-on.jpg)");
		}
	}
	
	var chosenDeal = $('input[id=loginOfFirstDeal]').val();
	$('div[class=0]').css('display',''); // make first deal displayed when page loads
	$('div[id=smalldeal_'+chosenDeal+']').css('background-color','#ECECEC');//make chosen company selected (grey background)
	
})

;
var eunotification = {

    requestNotification: function (){
    	
        var ai = new  AJAXInteractionServlet('/Notification_Servlet?id=1',
            function (responseXML){
                eunotification.handleNotification(responseXML);
            });
        ai.doGet();
    },

    handleNotification : function (responseXML){
        var xmlDoc = responseXML.documentElement
        if (xmlDoc !=null){
	        var xRows = xmlDoc.getElementsByTagName('popin');
	        for (i = 0; i < xRows.length ; i++) {
	            var message = xRows[i].firstChild.nodeValue;
	            $.jGrowl(url.decode(message).ReplaceAll("+"," "));
	        }
        }
    }
}

//window.onload = function() {
//	
//    //request right away
//    eunotification.requestNotification();
//    setInterval('eunotification.requestNotification()', 1000);//1s
//}
;

(function($){$.jGrowl=function(m,o){if($('#jGrowl').size()==0)$('<div id="jGrowl"></div>').addClass($.jGrowl.defaults.position).appendTo('body');$('#jGrowl').jGrowl(m,o);};$.fn.jGrowl=function(m,o){if($.isFunction(this.each)){var args=arguments;return this.each(function(){var self=this;if($(this).data('jGrowl.instance')==undefined){$(this).data('jGrowl.instance',$.extend(new $.fn.jGrowl(),{notifications:[],element:null,interval:null}));$(this).data('jGrowl.instance').startup(this);}
if($.isFunction($(this).data('jGrowl.instance')[m])){$(this).data('jGrowl.instance')[m].apply($(this).data('jGrowl.instance'),$.makeArray(args).slice(1));}else{$(this).data('jGrowl.instance').create(m,o);}});};};$.extend($.fn.jGrowl.prototype,{defaults:{pool:0,header:'',group:'',sticky:false,position:'top-right',glue:'after',theme:'default',corners:'10px',check:250,life:3000,speed:'normal',easing:'swing',closer:true,closeTemplate:'&times;',closerTemplate:'<div>[ close all ]</div>',log:function(e,m,o){},beforeOpen:function(e,m,o){},open:function(e,m,o){},beforeClose:function(e,m,o){},close:function(e,m,o){},animateOpen:{opacity:'show'},animateClose:{opacity:'hide'}},notifications:[],element:null,interval:null,create:function(message,o){var o=$.extend({},this.defaults,o);this.notifications[this.notifications.length]={message:message,options:o};o.log.apply(this.element,[this.element,message,o]);},render:function(notification){var self=this;var message=notification.message;var o=notification.options;var notification=$('<div class="jGrowl-notification'+((o.group!=undefined&&o.group!='')?' '+o.group:'')+'"><div class="close">'+o.closeTemplate+'</div><div class="header">'+o.header+'</div><div class="message">'+message+'</div></div>').data("jGrowl",o).addClass(o.theme).children('div.close').bind("click.jGrowl",function(){$(this).parent().trigger('jGrowl.close');}).parent();(o.glue=='after')?$('div.jGrowl-notification:last',this.element).after(notification):$('div.jGrowl-notification:first',this.element).before(notification);$(notification).bind("mouseover.jGrowl",function(){$(this).data("jGrowl").pause=true;}).bind("mouseout.jGrowl",function(){$(this).data("jGrowl").pause=false;}).bind('jGrowl.beforeOpen',function(){o.beforeOpen.apply(self.element,[self.element,message,o]);}).bind('jGrowl.open',function(){o.open.apply(self.element,[self.element,message,o]);}).bind('jGrowl.beforeClose',function(){o.beforeClose.apply(self.element,[self.element,message,o]);}).bind('jGrowl.close',function(){$(this).data('jGrowl').pause=true;$(this).trigger('jGrowl.beforeClose').animate(o.animateClose,o.speed,o.easing,function(){$(this).remove();o.close.apply(self.element,[self.element,message,o]);});}).trigger('jGrowl.beforeOpen').animate(o.animateOpen,o.speed,o.easing,function(){$(this).data("jGrowl").created=new Date();}).trigger('jGrowl.open');if($.fn.corner!=undefined)$(notification).corner(o.corners);if($('div.jGrowl-notification:parent',this.element).size()>1&&$('div.jGrowl-closer',this.element).size()==0&&this.defaults.closer!=false){$(this.defaults.closerTemplate).addClass('jGrowl-closer').addClass(this.defaults.theme).appendTo(this.element).animate(this.defaults.animateOpen,this.defaults.speed,this.defaults.easing).bind("click.jGrowl",function(){$(this).siblings().children('div.close').trigger("click.jGrowl");if($.isFunction(self.defaults.closer))self.defaults.closer.apply($(this).parent()[0],[$(this).parent()[0]]);});};},update:function(){$(this.element).find('div.jGrowl-notification:parent').each(function(){if($(this).data("jGrowl")!=undefined&&$(this).data("jGrowl").created!=undefined&&($(this).data("jGrowl").created.getTime()+$(this).data("jGrowl").life)<(new Date()).getTime()&&$(this).data("jGrowl").sticky!=true&&($(this).data("jGrowl").pause==undefined||$(this).data("jGrowl").pause!=true)){$(this).trigger('jGrowl.close');}});if(this.notifications.length>0&&(this.defaults.pool==0||$(this.element).find('div.jGrowl-notification:parent').size()<this.defaults.pool)){this.render(this.notifications.shift());}
if($(this.element).find('div.jGrowl-notification:parent').size()<2){$(this.element).find('div.jGrowl-closer').animate(this.defaults.animateClose,this.defaults.speed,this.defaults.easing,function(){$(this).remove();});};},startup:function(e){this.element=$(e).addClass('jGrowl').append('<div class="jGrowl-notification"></div>');this.interval=setInterval(function(){$(e).data('jGrowl.instance').update();},this.defaults.check);if($.browser.msie&&parseInt($.browser.version)<7&&!window["XMLHttpRequest"])$(this.element).addClass('ie6');},shutdown:function(){$(this.element).removeClass('jGrowl').find('div.jGrowl-notification').remove();clearInterval(this.interval);}});$.jGrowl.defaults=$.fn.jGrowl.prototype.defaults;})(jQuery);

;
function Pager(tableName, itemsPerPage) {
    this.tableName = tableName;
    this.itemsPerPage = itemsPerPage;
    this.currentPage = 1;
    this.pages = 0;
    this.inited = false;
    
    this.showRecords = function(from, to) {        
        var rows = document.getElementById(tableName).rows;
        // i starts from 1 to skip table header row
        for (var i = 1; i < rows.length; i++) {
            if (i < from || i > to)  
                rows[i].style.display = 'none';
            else
                rows[i].style.display = '';
        }
    }
    
    this.showPage = function(pageNumber) {
    	if (! this.inited) {
    		alert("not inited");
    		return;
    	}

        var oldPageAnchor = document.getElementById('pg'+this.currentPage);
        if (null != oldPageAnchor){
        	oldPageAnchor.className = 'pg-normal';
        }
        
        this.currentPage = pageNumber;
        var newPageAnchor = document.getElementById('pg'+this.currentPage);
        if (null != newPageAnchor){
        	newPageAnchor.className = 'pg-selected';
        }
        
        var from = (pageNumber - 1) * itemsPerPage + 1;
        var to = from + itemsPerPage - 1;
        this.showRecords(from, to);
    }   
    
    this.prev = function() {
        if (this.currentPage > 1)
            this.showPage(this.currentPage - 1);
    }
    
    this.next = function() {
        if (this.currentPage < this.pages) {
            this.showPage(this.currentPage + 1);
        }
    }                        
    
    this.init = function() {
        var rows = document.getElementById(tableName).rows;
        var records = (rows.length - 1); 
        this.pages = Math.ceil(records / itemsPerPage);
        this.inited = true;
    }

    this.showPageNav = function(pagerName, positionId) {
    	if (! this.inited) {
    		alert("not inited");
    		return;
    	}
    	var element = document.getElementById(positionId);
    	
    	var pagerHtml = '';
        for (var page = 1; page <= this.pages; page++) 
            pagerHtml += '&nbsp;&nbsp;<span id="pg' + page + '" class="pg-normal" onclick="' + pagerName + '.showPage(' + page + ');">' + page + '</span>&nbsp;&nbsp;';           
        
        element.innerHTML = pagerHtml;
    }
}

;
var euinit = {

    initEuTables: function (){
        //init eu tables for dynamic hovers
        $('table.eu tbody tr').each(function (){
            this.className='eu';
            this.onmouseover = function(){
                this.className='eu-hover';
            };
            this.onmouseout = function(){
                this.className='eu';
            };
        });
        $('tr.eu td').each(function (){
            this.className='eu';
            this.onmouseover = function(){
                this.className='eu-hover';
            };
            this.onmouseout = function(){
                this.className='eu';
            };
        });
    },

    initTab:function(id) {
        var tab = document.getElementById(id);
        if(tab != null){
            tab.className='tabberactive';
        }
    }
}

window.onload = function() {
    //request right away
    euinit.initEuTables();
}

;
/*==================================================
  $Id: tabber.js,v 1.9 2006/04/27 20:51:51 pat Exp $
  tabber.js by Patrick Fitzgerald pat@barelyfitz.com

  Documentation can be found at the following URL:
  http://www.barelyfitz.com/projects/tabber/

  License (http://www.opensource.org/licenses/mit-license.php)

  Copyright (c) 2006 Patrick Fitzgerald

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation files
  (the "Software"), to deal in the Software without restriction,
  including without limitation the rights to use, copy, modify, merge,
  publish, distribute, sublicense, and/or sell copies of the Software,
  and to permit persons to whom the Software is furnished to do so,
  subject to the following conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.
  ==================================================*/

function tabberObj(argsObj)
{
  var arg; /* name of an argument to override */

  /* Element for the main tabber div. If you supply this in argsObj,
     then the init() method will be called.
  */
  this.div = null;

  /* Class of the main tabber div */
  this.classMain = "tabber";

  /* Rename classMain to classMainLive after tabifying
     (so a different style can be applied)
  */
  this.classMainLive = "tabberlive";

  /* Class of each DIV that contains a tab */
  this.classTab = "tabbertab";

  /* Class to indicate which tab should be active on startup */
  this.classTabDefault = "tabbertabdefault";

  /* Class for the navigation UL */
  this.classNav = "tabbernav";

  /* When a tab is to be hidden, instead of setting display='none', we
     set the class of the div to classTabHide. In your screen
     stylesheet you should set classTabHide to display:none.  In your
     print stylesheet you should set display:block to ensure that all
     the information is printed.
  */
  this.classTabHide = "tabbertabhide";

  /* Class to set the navigation LI when the tab is active, so you can
     use a different style on the active tab.
  */
  this.classNavActive = "tabberactive";

  /* Elements that might contain the title for the tab, only used if a
     title is not specified in the TITLE attribute of DIV classTab.
  */
  this.titleElements = ['h2','h3','h4','h5','h6'];

  /* Should we strip out the HTML from the innerHTML of the title elements?
     This should usually be true.
  */
  this.titleElementsStripHTML = true;

  /* If the user specified the tab names using a TITLE attribute on
     the DIV, then the browser will display a tooltip whenever the
     mouse is over the DIV. To prevent this tooltip, we can remove the
     TITLE attribute after getting the tab name.
  */
  this.removeTitle = true;

  /* If you want to add an id to each link set this to true */
  this.addLinkId = false;

  /* If addIds==true, then you can set a format for the ids.
     <tabberid> will be replaced with the id of the main tabber div.
     <tabnumberzero> will be replaced with the tab number
       (tab numbers starting at zero)
     <tabnumberone> will be replaced with the tab number
       (tab numbers starting at one)
     <tabtitle> will be replaced by the tab title
       (with all non-alphanumeric characters removed)
   */
  this.linkIdFormat = '<tabberid>nav<tabnumberone>';

  /* You can override the defaults listed above by passing in an object:
     var mytab = new tabber({property:value,property:value});
  */
  for (arg in argsObj) { this[arg] = argsObj[arg]; }

  /* Create regular expressions for the class names; Note: if you
     change the class names after a new object is created you must
     also change these regular expressions.
  */
  this.REclassMain = new RegExp('\\b' + this.classMain + '\\b', 'gi');
  this.REclassMainLive = new RegExp('\\b' + this.classMainLive + '\\b', 'gi');
  this.REclassTab = new RegExp('\\b' + this.classTab + '\\b', 'gi');
  this.REclassTabDefault = new RegExp('\\b' + this.classTabDefault + '\\b', 'gi');
  this.REclassTabHide = new RegExp('\\b' + this.classTabHide + '\\b', 'gi');

  /* Array of objects holding info about each tab */
  this.tabs = new Array();

  /* If the main tabber div was specified, call init() now */
  if (this.div) {

    this.init(this.div);

    /* We don't need the main div anymore, and to prevent a memory leak
       in IE, we must remove the circular reference between the div
       and the tabber object. */
    this.div = null;
  }
}


/*--------------------------------------------------
  Methods for tabberObj
  --------------------------------------------------*/


tabberObj.prototype.init = function(e)
{
  /* Set up the tabber interface.

     e = element (the main containing div)

     Example:
     init(document.getElementById('mytabberdiv'))
   */

  var
  childNodes, /* child nodes of the tabber div */
  i, i2, /* loop indices */
  t, /* object to store info about a single tab */
  defaultTab=0, /* which tab to select by default */
  DOM_ul, /* tabbernav list */
  DOM_li, /* tabbernav list item */
  DOM_a, /* tabbernav link */
  aId, /* A unique id for DOM_a */
  headingElement; /* searching for text to use in the tab */

  /* Verify that the browser supports DOM scripting */
  if (!document.getElementsByTagName) { return false; }

  /* If the main DIV has an ID then save it. */
  if (e.id) {
    this.id = e.id;
  }

  /* Clear the tabs array (but it should normally be empty) */
  this.tabs.length = 0;

  /* Loop through an array of all the child nodes within our tabber element. */
  childNodes = e.childNodes;
  for(i=0; i < childNodes.length; i++) {

    /* Find the nodes where class="tabbertab" */
    if(childNodes[i].className &&
       childNodes[i].className.match(this.REclassTab)) {
      
      /* Create a new object to save info about this tab */
      t = new Object();
      
      /* Save a pointer to the div for this tab */
      t.div = childNodes[i];
      
      /* Add the new object to the array of tabs */
      this.tabs[this.tabs.length] = t;

      /* If the class name contains classTabDefault,
	 then select this tab by default.
      */
      if (childNodes[i].className.match(this.REclassTabDefault)) {
	defaultTab = this.tabs.length-1;
      }
    }
  }

  /* Create a new UL list to hold the tab headings */
  DOM_ul = document.createElement("ul");
  DOM_ul.className = this.classNav;
  
  /* Loop through each tab we found */
  for (i=0; i < this.tabs.length; i++) {

    t = this.tabs[i];

    /* Get the label to use for this tab:
       From the title attribute on the DIV,
       Or from one of the this.titleElements[] elements,
       Or use an automatically generated number.
     */
    t.headingText = t.div.title;

    /* Remove the title attribute to prevent a tooltip from appearing */
    if (this.removeTitle) { t.div.title = ''; }

    if (!t.headingText) {

      /* Title was not defined in the title of the DIV,
	 So try to get the title from an element within the DIV.
	 Go through the list of elements in this.titleElements
	 (typically heading elements ['h2','h3','h4'])
      */
      for (i2=0; i2<this.titleElements.length; i2++) {
	headingElement = t.div.getElementsByTagName(this.titleElements[i2])[0];
	if (headingElement) {
	  t.headingText = headingElement.innerHTML;
	  if (this.titleElementsStripHTML) {
	    t.headingText.replace(/<br>/gi," ");
	    t.headingText = t.headingText.replace(/<[^>]+>/g,"");
	  }
	  break;
	}
      }
    }

    if (!t.headingText) {
      /* Title was not found (or is blank) so automatically generate a
         number for the tab.
      */
      t.headingText = i + 1;
    }

    /* Create a list element for the tab */
    DOM_li = document.createElement("li");

    /* Save a reference to this list item so we can later change it to
       the "active" class */
    t.li = DOM_li;

    /* Create a link to activate the tab */
    DOM_a = document.createElement("a");
    DOM_a.appendChild(document.createTextNode(t.headingText));
    DOM_a.href = "javascript:void(null);";
    DOM_a.title = t.headingText;
    DOM_a.onclick = this.navClick;

    /* Add some properties to the link so we can identify which tab
       was clicked. Later the navClick method will need this.
    */
    DOM_a.tabber = this;
    DOM_a.tabberIndex = i;

    /* Do we need to add an id to DOM_a? */
    if (this.addLinkId && this.linkIdFormat) {

      /* Determine the id name */
      aId = this.linkIdFormat;
      aId = aId.replace(/<tabberid>/gi, this.id);
      aId = aId.replace(/<tabnumberzero>/gi, i);
      aId = aId.replace(/<tabnumberone>/gi, i+1);
      aId = aId.replace(/<tabtitle>/gi, t.headingText.replace(/[^a-zA-Z0-9\-]/gi, ''));

      DOM_a.id = aId;
    }

    /* Add the link to the list element */
    DOM_li.appendChild(DOM_a);

    /* Add the list element to the list */
    DOM_ul.appendChild(DOM_li);
  }

  /* Add the UL list to the beginning of the tabber div */
  e.insertBefore(DOM_ul, e.firstChild);

  /* Make the tabber div "live" so different CSS can be applied */
  e.className = e.className.replace(this.REclassMain, this.classMainLive);

  /* Activate the default tab, and do not call the onclick handler */
  this.tabShow(defaultTab);

  /* If the user specified an onLoad function, call it now. */
  if (typeof this.onLoad == 'function') {
    this.onLoad({tabber:this});
  }

  return this;
};


tabberObj.prototype.navClick = function(event)
{
  /* This method should only be called by the onClick event of an <A>
     element, in which case we will determine which tab was clicked by
     examining a property that we previously attached to the <A>
     element.

     Since this was triggered from an onClick event, the variable
     "this" refers to the <A> element that triggered the onClick
     event (and not to the tabberObj).

     When tabberObj was initialized, we added some extra properties
     to the <A> element, for the purpose of retrieving them now. Get
     the tabberObj object, plus the tab number that was clicked.
  */

  var
  rVal, /* Return value from the user onclick function */
  a, /* element that triggered the onclick event */
  self, /* the tabber object */
  tabberIndex, /* index of the tab that triggered the event */
  onClickArgs; /* args to send the onclick function */

  a = this;
  if (!a.tabber) { return false; }

  self = a.tabber;
  tabberIndex = a.tabberIndex;

  /* Remove focus from the link because it looks ugly.
     I don't know if this is a good idea...
  */
  a.blur();

  /* If the user specified an onClick function, call it now.
     If the function returns false then do not continue.
  */
  if (typeof self.onClick == 'function') {

    onClickArgs = {'tabber':self, 'index':tabberIndex, 'event':event};

    /* IE uses a different way to access the event object */
    if (!event) { onClickArgs.event = window.event; }

    rVal = self.onClick(onClickArgs);
    if (rVal === false) { return false; }
  }

  self.tabShow(tabberIndex);

  return false;
};


tabberObj.prototype.tabHideAll = function()
{
  var i; /* counter */

  /* Hide all tabs and make all navigation links inactive */
  for (i = 0; i < this.tabs.length; i++) {
    this.tabHide(i);
  }
};


tabberObj.prototype.tabHide = function(tabberIndex)
{
  var div;

  if (!this.tabs[tabberIndex]) { return false; }

  /* Hide a single tab and make its navigation link inactive */
  div = this.tabs[tabberIndex].div;

  /* Hide the tab contents by adding classTabHide to the div */
  if (!div.className.match(this.REclassTabHide)) {
    div.className += ' ' + this.classTabHide;
  }
  this.navClearActive(tabberIndex);

  return this;
};


tabberObj.prototype.tabShow = function(tabberIndex)
{
  /* Show the tabberIndex tab and hide all the other tabs */

  var div;

  if (!this.tabs[tabberIndex]) { return false; }

  /* Hide all the tabs first */
  this.tabHideAll();

  /* Get the div that holds this tab */
  div = this.tabs[tabberIndex].div;

  /* Remove classTabHide from the div */
  div.className = div.className.replace(this.REclassTabHide, '');

  /* Mark this tab navigation link as "active" */
  this.navSetActive(tabberIndex);

  /* If the user specified an onTabDisplay function, call it now. */
  if (typeof this.onTabDisplay == 'function') {
    this.onTabDisplay({'tabber':this, 'index':tabberIndex});
  }

  return this;
};

tabberObj.prototype.navSetActive = function(tabberIndex)
{
  /* Note: this method does *not* enforce the rule
     that only one nav item can be active at a time.
  */

  /* Set classNavActive for the navigation list item */
  this.tabs[tabberIndex].li.className = this.classNavActive;

  return this;
};


tabberObj.prototype.navClearActive = function(tabberIndex)
{
  /* Note: this method does *not* enforce the rule
     that one nav should always be active.
  */

  /* Remove classNavActive from the navigation list item */
  this.tabs[tabberIndex].li.className = '';

  return this;
};


/*==================================================*/


function tabberAutomatic(tabberArgs)
{
  /* This function finds all DIV elements in the document where
     class=tabber.classMain, then converts them to use the tabber
     interface.

     tabberArgs = an object to send to "new tabber()"
  */
  var
    tempObj, /* Temporary tabber object */
    divs, /* Array of all divs on the page */
    i; /* Loop index */

  if (!tabberArgs) { tabberArgs = {}; }

  /* Create a tabber object so we can get the value of classMain */
  tempObj = new tabberObj(tabberArgs);

  /* Find all DIV elements in the document that have class=tabber */

  /* First get an array of all DIV elements and loop through them */
  divs = document.getElementsByTagName("div");
  for (i=0; i < divs.length; i++) {
    
    /* Is this DIV the correct class? */
    if (divs[i].className &&
	divs[i].className.match(tempObj.REclassMain)) {
      
      /* Now tabify the DIV */
      tabberArgs.div = divs[i];
      divs[i].tabber = new tabberObj(tabberArgs);
    }
  }
  
  return this;
}


/*==================================================*/


function tabberAutomaticOnLoad(tabberArgs)
{
  /* This function adds tabberAutomatic to the window.onload event,
     so it will run after the document has finished loading.
  */
  var oldOnLoad;

  if (!tabberArgs) { tabberArgs = {}; }

  /* Taken from: http://simon.incutio.com/archive/2004/05/26/addLoadEvent */

  oldOnLoad = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = function() {
      tabberAutomatic(tabberArgs);
    };
  } else {
    window.onload = function() {
      oldOnLoad();
      tabberAutomatic(tabberArgs);
    };
  }
}


/*==================================================*/


/* Run tabberAutomaticOnload() unless the "manualStartup" option was specified */

if (typeof tabberOptions == 'undefined') {

    tabberAutomaticOnLoad();

} else {

  if (!tabberOptions['manualStartup']) {
    tabberAutomaticOnLoad(tabberOptions);
  }

}
;
PAYS = {
				FRANCE: 1,
				BELGIQUE: 2,
				LUXEMBOURGH: 3,
				SUISSE: 4		
			}

var profilComplet = new function() {

	var pays;
	
	return {
		loadFields:function(){
			//document.getElementById('txtRegionLabel').value = document.saisieProfilCompanyActionForm.regionLabel.value;
			//document.getElementById('txtDepartementLabel').value = document.saisieProfilCompanyActionForm.departementLabel.value;
			pays = parseInt(document.saisieProfilCompanyActionForm.numPays.value);
			
		},
		
		getRegionDepartment:function(codePostal){
		
		pays = parseInt(document.saisieProfilCompanyActionForm.numPays.value);
		
		var errorExists=false;
			//Validate Code Postal
			if (isNaN(codePostal)==true) 
			{ 
				//this is not an integer value
				errorExists = true;
			}else{
				switch (pays){
					case 1://France
						if (codePostal.length != 5){
							//France length should be 5
							errorExists = true;
						}
						break;
					case 2://Belgique
						if (codePostal.length != 4){
							//Belgique length should be 4
							errorExists = true;
						}
						break;
					default:
						errorExists = true;
				}
			}
			
			if (errorExists == true){
				document.getElementById('txtRegionLabel').value = '';
				document.saisieProfilCompanyActionForm.regionValue.value = 0;
				document.getElementById('txtDepartementLabel').value = '';
				document.saisieProfilCompanyActionForm.departementValue.value = 0;
				//region and departement not populated and hence not visible
				return false;
			}
			var ai = new AJAXInteractionServlet('ZipCode_Servlet?codePostal='+codePostal+'&pays='+pays,function (responseXML){
													profilComplet.regionDepartment(responseXML);
												});	
						
			ai.doPost();				
	
		},
		
		regionDepartment:function(responseXML){

			var xmlDoc = responseXML.documentElement;
			
				if (xmlDoc !=null){
					var region = url.decode(xmlDoc.getElementsByTagName('regionLabel')[0].firstChild.nodeValue);
					region = region.ReplaceAll("+"," ");
					document.getElementById('txtRegionLabel').value = region;
					document.saisieProfilCompanyActionForm.regionValue.value = 
						xmlDoc.getElementsByTagName('regionValue')[0].firstChild.nodeValue;
					if(document.saisieProfilCompanyActionForm.regionValue.value != 0){
						document.getElementById('trRegion').style.display = '';
						document.getElementById('tdRegionFrance').style.display = '';
					}else{
						document.getElementById('tdRegionFrance').style.display = 'none';
						document.getElementById('trRegion').style.display = 'none';
					}
					try{
						var departement = url.decode(xmlDoc.getElementsByTagName('departementLabel')[0].firstChild.nodeValue);
						departement = departement.ReplaceAll("+"," ");
						document.getElementById('txtDepartementLabel').value = departement;
						document.saisieProfilCompanyActionForm.departementValue.value = 
							xmlDoc.getElementsByTagName('departementValue')[0].firstChild.nodeValue;
						if(document.saisieProfilCompanyActionForm.departementValue.value != 0){
						document.getElementById('trDepartement').style.display = '';
						}else{
							document.getElementById('trDepartement').style.display = 'none';
						}
					}catch(e){
						document.getElementById('txtDepartementLabel').value= '';
					}
				}
		},
		getRegions:function(pays, form){
			if (document.saisieProfilCompanyActionForm.noRegion.value == 'false'){
				document.getElementById('trRegionSelected').style.display = 'none';
			}
			var ai = new AJAXInteractionServlet('Region_Servlet?pays='+pays,function (responseXML){
													profilComplet.populateRegion(responseXML, form);
												});	
						
			ai.doPost();	
		},
		
		populateSecteur: function (){
			if (document.saisieProfilCompanyActionForm.noRegion.value == 'false'){
				document.getElementById('numRegionList').value = 0;	
			}
		},
		
		populateRegion: function (responseXML, form) {
			  var xmlDoc = responseXML.documentElement;
			  var objDDL = form.region_list;
			  objDDL.options.length = 0;
			  var xRows = xmlDoc.getElementsByTagName('entry');
			  for(i=0;i<xRows.length;i++) {
				   var theText = '';
				   var theValue = '';
				   if (xRows[i].getElementsByTagName('optionText')[0].firstChild)
				    	theText = xRows[i].getElementsByTagName('optionText')[0].firstChild.nodeValue;
				   if (xRows[i].getElementsByTagName('optionValue')[0].firstChild)
				    	theValue = xRows[i].getElementsByTagName('optionValue')[0].firstChild.nodeValue;
				   var option = new Option((url.decode(theText)).replace(/\+/g,' '), theValue);
				   try {
				    	objDDL.add(option, null);
				   } catch(e) {
				    	objDDL.add(option, -1);
				   }
			  }
			  
			  if (xRows.length > 0){
			  	document.getElementById('trRegion').style.display = '';
			  }else{
			  	document.getElementById('trRegion').style.display = 'none';
			  }
		}
	}
}

;

function checkMail(){
			document.notificationsActionForm.dispatch.value = "sauvegarder";
			document.notificationsActionForm.submit();
	}
	
	function ajouter(){
		document.notificationsActionForm.action.value = "";
		document.notificationsActionForm.dispatch.value = "ajouterEmailCompte";		
	}
    ;
    PAYS = {
				FRANCE: 1,
				BELGIQUE: 2,
				LUXEMBOURGH: 3,
				SUISSE: 4		
			}
			
var dealproposal = new function(){
	
	var pays;

	return{
		/**
		 * This function is used to display a dynamic message when the user
		 * selects a type of visibility for his deal.
		 */
		changeTextVisibility:function(){
			if(document.getElementById('numVisibity').value==0){
				document.getElementById('textVisibilityPublic').style.display='';
				document.getElementById('textVisibilityIntern').style.display='none';
				document.getElementById('textVisibilityConfidential').style.display='none';
			}else if(document.getElementById('numVisibity').value==1){
				document.getElementById('textVisibilityIntern').style.display='';
				document.getElementById('textVisibilityPublic').style.display='none';
				document.getElementById('textVisibilityConfidential').style.display='none';
			}else if(document.getElementById('numVisibity').value==2){
				document.getElementById('textVisibilityConfidential').style.display='';
				document.getElementById('textVisibilityPublic').style.display='none';
				document.getElementById('textVisibilityIntern').style.display='none';
			}

		},
/*
 * function to dynamically populate text and summary upon creation of a deal
 */
        populateTextAndSummary: function (id){
			  var valueText = document.getElementById(id).value;
			  if(id == 'title-dpr'){
			  	document.getElementById('vignette_title').innerHTML=valueText;
			  }else  if(id == 'pointFort-dpr'){
			  	document.getElementById('vignette_pointFort').innerHTML=valueText;
			  }else  if(id == 'budget-dpr'){
			  	document.getElementById('vignette_budget').innerHTML=valueText;
			  }else{
			  	var num = 150;
			  	if (valueText.length > num) {
			  		var string = valueText.substring(0,num);
			  		var lstIndex = string.lastIndexOf(' ');
			  		num = lstIndex;			  			  		
			  	}			  
			  	 document.getElementById('vignette_summary').innerHTML=valueText.substring(0,num);
			  	 dealproposal.breakText(valueText);
			  	 changeWordWrap('wordwrap'); // change wordwrap depending on text
			  }	    
        },
        
        breakText: function(text) {
        	var selectedTest = text.substring(0,150);
        	var num = selectedTest.lastIndexOf(" ");
        	var txt = selectedTest.substring(0,num);
       },
        
        checkTitle: function(id){  	
        	var valueText = document.getElementById(id).value;
        	//document.getElementById('titleMessages').style.display='none';
        	if(trim(valueText).length == 0){
        		document.getElementById('titleMessages').style.display='none';
        		document.getElementById('errorTitle').style.display='';
        		document.getElementById('okTitle').style.display='none';
        	}else{
        		document.getElementById('titleMessages').style.display='none';
        		document.getElementById('errorTitle').style.display='none';
        		document.getElementById('okTitle').style.display='';
        	}
        },
        
        checkPointFort: function(id){  	
        	var valueText = document.getElementById(id).value;
        	//document.getElementById('titleMessages').style.display='none';
        	if(trim(valueText).length == 0){
        		document.getElementById('pointFortMessages').style.display='none';
        		document.getElementById('errorPointFort').style.display='';
        		document.getElementById('okPointFort').style.display='none';
        	}else{
        		document.getElementById('pointFortMessages').style.display='none';
        		document.getElementById('errorPointFort').style.display='none';
        		document.getElementById('okPointFort').style.display='';
        	}
        },
        
         checkBudget: function(id){  	
        	var valueText = document.getElementById(id).value;
        	//document.getElementById('titleMessages').style.display='none';
        	if(trim(valueText).length > 0){
        		document.getElementById('budgetMessages').style.display='none';
        		document.getElementById('okBudget').style.display='';
        	}
        },
        
        populateTime:function(){
			document.getElementById('vignette_date').innerHTML=EU_TEXT.DEAL_MESSAGE_TIME;  	
        },
        
        loadFields:function(){
			dealproposal.enableDisableFields(document.getElementById('numPays').value);			
			pays = parseInt(document.getElementById('numPays').value);
			
		},
		
		enableDisableFields:function (selectedpays){
			pays = parseInt(selectedpays);
			switch (pays){
				case 1://France					
					if(document.getElementById('numPays').value==1) {
						document.getElementById('regFrance').style.display = '';
						document.getElementById('regSuisse').style.display = 'none';
						document.getElementById('regBelgique').style.display = 'none';
						document.getElementById('numRegionSuisse').value=0;
						document.getElementById('numRegionBelgique').value=0;
					}			
					break;
				case 2://Belgique					
					if(document.getElementById('numPays').value==2){
						document.getElementById('regBelgique').style.display = '';
						document.getElementById('regSuisse').style.display = 'none';
						document.getElementById('regFrance').style.display = 'none';
						document.getElementById('numRegionFrance').value=0;
						document.getElementById('numRegionSuisse').value=0;
					}							
					break;
				case 3://Luxembourg
					if(document.getElementById('numPays').value==3){
						document.getElementById('regBelgique').style.display = 'none';	
						document.getElementById('regFrance').style.display = 'none';
						document.getElementById('regSuisse').style.display = 'none';
					}								
					break;
				case 4://Suisse
					if(document.getElementById('numPays').value==4) {
						document.getElementById('regSuisse').style.display = '';
						document.getElementById('regBelgique').style.display = 'none';	
						document.getElementById('regFrance').style.display = 'none';	
						document.getElementById('numRegionFrance').value=0;
						document.getElementById('numRegionBelgique').value=0;	
					}					
					break;
				default:
					document.getElementById('regFrance').style.display = 'none';
					document.getElementById('regSuisse').style.display = 'none';
					document.getElementById('regBelgique').style.display = 'none';
					break;
			}
		},
        
        checkDate: function(id){  	
        	var valueText = document.getElementById(id).value;
        	
        	if(trim(valueText).length == 0){
        		document.getElementById('dateMessages').style.display='none';
        		document.getElementById('dateTitle').style.display='';
        		document.getElementById('okDate').style.display='none';
        	}else{
        		document.getElementById('dateTitle').style.display='none';
        		document.getElementById('dateTitle').style.display='none';
        		document.getElementById('okDate').style.display='';        		
        	}
        },
        
        changeText: function (){
        	if (document.getElementById('calendarDateDebut-dpr').value != "") {
        		dealproposal.populateApercuEvent('calendarDateDebut-dpr');
        	}
        },
                
        populateApercuEvent: function (id){
			  var valueText = document.getElementById(id).value;
			  if(id == 'title-dpr'){
			  	document.getElementById('vignette_title').innerHTML=valueText;
			  } else if(id == 'calendarDateDebut-dpr'){
			  	var text = '';
			  	var list;
			  	var labelRegion;
			  	text = valueText;			  	
			  	
			  	if(document.getElementById('numPays').value==1 && document.getElementById('numRegionFrance').value > 0) {
			  		//france
			  		list = document.getElementById('numRegionFrance');
			  		labelRegion = list.options[list.selectedIndex].text;
			  	} else if(document.getElementById('numPays').value==2 && document.getElementById('numRegionBelgique').value > 0) {
			  		//Belgique
			  		list = document.getElementById('numRegionBelgique');
			  		labelRegion = list.options[list.selectedIndex].text;
			  	}  else if(document.getElementById('numPays').value==3) {
			  		//Luxembourg
			  		list = document.getElementById('numPays');
			  		labelRegion = list.options[list.selectedIndex].text;
			  	} else if(document.getElementById('numPays').value==4 && document.getElementById('numRegionSuisse').value > 0) {
			  		//suisse			  		
			  		list = document.getElementById('numRegionSuisse');
			  		labelRegion = list.options[list.selectedIndex].text;
			  	} else {
			  		labelRegion = "";
			  	}
			  	
			  	if (labelRegion != "") {
			  		text = text + ' en ' +  labelRegion;
			  	}
			  	
			  	if (document.getElementById(id).value == null || document.getElementById(id).value == '') {
			  		text = '';
			  		document.getElementById('title1_dpr').style.display='none';			  		
			  	} else {
			  		document.getElementById('title1_dpr').style.display='';	
			  	}
			  	document.getElementById('vignette_dateRegion').innerHTML=text;
			  	
			  } else{
			  	var num = 100;
			  	if (valueText.length > num) {
			  		var string = valueText.substring(0,num);
			  		var lstIndex = string.lastIndexOf(' ');
			  		num = lstIndex;			  			  		
			  	}
			  	document.getElementById('vignette_description').innerHTML=valueText.substring(0,num);
			  	changeWordWrap('wordwrap'); // change wordwrap depending on text
			  }	    
        },
        
        closeDeal: function (loginCompany, stringIdDeal,newDealProxyIndex, action){
        	
			var params = 'login='+loginCompany+'&id='+stringIdDeal;

			if (action == 'close'){
				$("TABLE#"+newDealProxyIndex).fadeOut('fast', function() {
			    	// FONCTION AJAX A APPELER POUR SUPPRIMER CETTE NOUVELLE
			  	
					var params = 'login='+loginCompany+'&id='+stringIdDeal+'&action=close';
		        	if (confirm(EU_TEXT.CLOSE_DEAL_PROPOSAL) ){
		        		actionfeedback.doActionFeedback('CLOSE'+stringIdDeal,'/CloseDealProposal_Servlet',params);
		        	}
				});
			}else if (action == 'open'){
				var params = 'login='+loginCompany+'&id='+stringIdDeal+'&action=open';
				actionfeedback.doActionFeedback('OPEN_DEAL'+stringIdDeal,'/CloseDealProposal_Servlet',params);
			}
        },
       
       closeSelectedDeal: function (loginCompany, stringIdDeal, action){
        	
			var params = 'login='+loginCompany+'&id='+stringIdDeal;
			
			if (action == 'close'){
				var params = 'login='+loginCompany+'&id='+stringIdDeal+'&action=close';
	        	if (confirm(EU_TEXT.CLOSE_DEAL_PROPOSAL) ){
	        		actionfeedback.doActionFeedback('CLOSE'+stringIdDeal,'/CloseDealProposal_Servlet',params);
	        	}
			}else if (action == 'open'){
				var params = 'login='+loginCompany+'&id='+stringIdDeal+'&action=open';
				actionfeedback.doActionFeedback('OPEN_DEAL'+stringIdDeal,'/CloseDealProposal_Servlet',params);
			}
        },
        
        answerQuestion: function (loginCompany,stringIdDeal){
        	var canCommunicate = $('#canLoggedUserCommunicate').val();
	  		if (canCommunicate == "true"){
	  			var description =document.getElementById('txtDescriptionReponse'+stringIdDeal).value;
	        	if (url.decode(description) == url.decode(EU_TEXT.REPONDRE_PUBLIQUEMENT)){
	        		return;
	        	}
	        	var params ='login='+loginCompany+'&id='+stringIdDeal+'&description='+url.encode(description);
	        	
	        	
	        	var ai = new AJAXInteractionServlet( '/AnswerDealProposalQuestion_Servlet', function (responseXML){
                	dealproposal.setTextReponseTag(responseXML,stringIdDeal);
	            });
	            ai.doPost(params);
	  		}else{
	  			subscription.displayMessageCannotCommunicate(EU_TEXT.USER_FREEMIUM_CANNOT_MAIL);
	  		}
        } ,
        
        setTextReponseTag:function (responseXML, stringIdDeal){
        	
            var xmlDoc = responseXML.documentElement;
            if (xmlDoc !=null){
                var type = xmlDoc.getElementsByTagName('type')[0].firstChild.nodeValue;
                if (type=='VALID'){
                	
                	var description  = document.getElementById('txtDescriptionReponse'+stringIdDeal).value;
       	        	description = description.replace(/\n/g,"<br>"); // to display the break lines
	                document.getElementById('txtDescriptionReponse'+stringIdDeal).value ='';
	                var newSize = parseInt(document.getElementById('size'+stringIdDeal).innerHTML) + 1;
	                document.getElementById('size'+stringIdDeal).innerHTML=newSize;
	                if (newSize == 2){
	                	document.getElementById('TEXT'+stringIdDeal).innerHTML=EU_TEXT.TEXT_REPONSES;
	                }
	               // alert(document.getElementById('size'+stringIdDeal).innerHTML);
	       			document.getElementById('reponse'+stringIdDeal).innerHTML=description;
	       			document.getElementById('oldReponse'+stringIdDeal).style.display = 'none';
	       			document.getElementById('newReponse'+stringIdDeal).style.display = '';
                }
            }
        }       
	}
	
}
;var dealproposalmail = new function() {
	var feedbackId;
	var logindestinataire;
	var logindealproposal;
	var dealAuthorCompanyId;
	
	return {
		/**
		 * takes the parameters for subscription from DealProposalAction and sets all on thickbox to be displayed
		 *
		 */
		mailSubscriptionToDealProposerCompany: function (userlogin,dealProposalLogin,feedbackid){ //used in partenariat		//dealprposallogin
			feedbackId = feedbackid;
			
			var dealProposalMailCode='<table cellpadding="2" cellspacing="2">'+
				
				'<tr><td colspan="2" id="mailresponse" style="color:red"></td></tr>'+
				'<tr><td colspan="2">'+EU_TEXT.DEAL_PROPOSAL_SUBSCRIPTION_MESSAGE+'</td></tr>'+
				'<tr><th valign="top">'+EU_TEXT.DEAL_PROPOSAL_SUBSCRIPTION_PROPOSITION+' :</th><td><textarea name="message" id="message" rows="15" cols="50" style="width:400px"></textarea></td></tr>'+
				'<tr><th></th><td><br/><input type="button" value="'+EU_TEXT.DEAL_PROPOSAL_SUBSCRIPTION_ENVOYER_DEMANDE+'" class="button" style="float:right;width:200px" onclick="dealproposalmail.sendMailDealProposal();"/></td></tr>'+
			'</table>';
	
	
			displayThickbox(EU_TEXT.DEAL_PROPOSAL_SUBSCRIPTION_TITRE,dealProposalMailCode,500,350);
			//set login & message
			document.getElementById('message').value='';
			document.getElementById('mailresponse').innerHTML='';
			
			logindestinataire=userlogin;
			logindealproposal=dealProposalLogin;
			mailtype=MAIL_TYPE.SUBSCRIPTION_TO_DEAL_PROPOSAL;//mail simple to societe
		},
		
		/**
		 * calls the required servlet with the appropriate parameters and returns the feedback
		 */
		sendMailDealProposal:function (){
			document.getElementById('mailresponse').innerHTML='';
			var message = document.getElementById('message').value;
			var destinataire = logindestinataire;
			var loginDealProposal=logindealproposal;
			
			var params ='text='+url.encode(message)+'&mail_type='+mailtype;
			
			if (mailtype==MAIL_TYPE.SUBSCRIPTION_TO_DEAL_PROPOSAL)
				params+='&loginRecipient='+destinataire+'&logindealproposal='+loginDealProposal;
			
			if (destinataire!=null && destinataire.length>0){
				mailfeedback.doMailFeedback(feedbackId,true,'/DealProposalMessage_Servlet',params);
			}
		},
		
		/**
		 * takes the parameters for Forward from DealProposalAction and sets all on thickbox to be displayed
		 *
		 */
		mailForwardToUser:function(dealProposalTitle, dealProposalLink, dealProposalAuthorName, dealProposalLogin, dealAuthorCompanyid){
			logindealproposal=dealProposalLogin;
			dealAuthorCompanyId=dealAuthorCompanyid;
			document.getElementById('forward_destinataire_new').innerHTML='';
			document.getElementById('forward_sujet_new').value=EU_TEXT.DEAL_PROPOSAL_FORWARD_SUJET;
			
			var forwardDealCode=EU_TEXT.DEAL_PROPOSAL_FORWARD_MESSAGE1+'\n\n'+EU_TEXT.DEAL_PROPOSAL_FORWARD_MESSAGE2+'\n'+dealProposalTitle
									+'\n\n'+EU_TEXT.DEAL_PROPOSAL_FORWARD_MESSAGE3+'\n'+dealProposalLink
									+'\n\n'+EU_TEXT.DEAL_PROPOSAL_FORWARD_MESSAGE4+'\n'+dealProposalAuthorName;
									
			document.getElementById('forward_message_new').value=forwardDealCode;
			document.getElementById('forwardmailresponse').innerHTML='';
		},
		
		/**
		 * Function to send mail forwardDealProposal to single or multiple users
		 * Appropriate servlet is called
		 */
		sendmailforward:function (){
				var logins = addressbook.getChosenLogins();
				var dealAuthorCompanyid=dealAuthorCompanyId;
				var loginDealProposal=logindealproposal;
				var sujet= url.encode(document.getElementById('forward_sujet_new').value);
				var message =  url.encode(document.getElementById('forward_message_new').value);
				var destinataire = logins;
				var mailtype = MAIL_TYPE.FORWARD_DEAL_PROPOSAL; 
				var params = 'sujet='+sujet+'&text='+message+'&mail_type='+mailtype+'&loginRecipient='+destinataire+'&logindealproposal='+loginDealProposal+'&dealAuthorCompanyId='+dealAuthorCompanyId;
				var text=EU_TEXT.DEAL_PROPOSAL_FORWARD_MESSAGE5;
				
				addressbook.clearLogins();
				if (destinataire.length > 0){
					mailfeedback.doMailFeedback('forwardmailresponse',false,'/DealProposalMessage_Servlet',params);
				}else{
					document.getElementById('forwardmailresponse').innerHTML=text;
				}
		}
	}
}
;
var broadcastNewsDeal = new function() {
	return {
		broadcast: function(stringId,companylogin,feedbackId){
			var params = 'stringId='+stringId+'&companylogin='+companylogin;
			actionfeedback.doActionFeedback(feedbackId,'/BroadcastNewsDeal_Servlet',params);
			
			broadcastNewsDeal.updateBroadcast(companylogin+'_'+stringId);
		},
		
		broadcastOnebyOne: function(stringId,companylogin,feedbackId, companyToBroadcast){
			var params = 'stringId='+stringId+'&companylogin='+companylogin+'&companyToBroadcast='+companyToBroadcast;
			actionfeedback.doActionFeedback(feedbackId,'/BroadcastNewsDealByCompanyServlet_Servlet',params);
			
			broadcastNewsDeal.updateBroadcastForBroadcastOneByOne(companylogin+'_'+stringId);
		},
		updateBroadcastForBroadcastOneByOne: function (broadcastid){ // called in actionfeedback.js
			//update number of followers to broadcast (V2)
			var numFollowers = parseInt($('SPAN#BROADCAST_TO_UPDATE_'+broadcastid).html());
			if (numFollowers == null)
				$('SPAN#BROADCAST_TO_UPDATE_'+broadcastid).remove();
			else{
				numFollowers = numFollowers - 1;
			
				if (numFollowers > 1){
					$('SPAN#BROADCAST_TO_UPDATE_'+broadcastid).html(numFollowers);
				}else if (numFollowers == 1){
					var isPageAnnonces = $('INPUT[id=pageAnnonces]').val();
					if (isPageAnnonces == 'true'){
						 $('SPAN#BROADCAST_TO_UPDATE_'+broadcastid).parent().html('<span style="font:12px Arial;color:#FFFFFF" id ="BROADCAST_TO_UPDATE_'+broadcastid+'">'+EU_TEXT.DEAL_BROADCAST_ONE_FOLLOWER+'</span>');
					}else
						$('SPAN#BROADCAST_TO_UPDATE_'+broadcastid).parent().html('<span style="font:12px Arial" id ="BROADCAST_TO_UPDATE_'+broadcastid+'">'+EU_TEXT.DEAL_BROADCAST_ONE_FOLLOWER+'</span>');
				}else if (numFollowers == 0){
					$('SPAN#BROADCAST_TO_UPDATE_'+broadcastid).parent().remove();
				}else{
					$('SPAN#BROADCAST_TO_UPDATE_'+broadcastid).parent().remove();
					
				}
			}
			
			
		},
		updateBroadcast:function(broadcastid){
			$('SPAN#BROADCAST_ONEBYONE_TO_UPDATE_'+broadcastid).remove();
		}
	}
}
;var dealproposalTraffic = new function(){

	return{
		/**
		 * This function is used to check and uncheck all the sub categories for the property
		 */
		checkUncheckAll:function(property, frm_obj) {
			for (var i=0;i<frm_obj.elements.length;i++) {
				var e = frm_obj.elements[i];
				if (e.id == property){ //get the value of the main checkbox id
					check = e.checked;
				}
				if (e.name == property){ 
				//set the value of all checkboxes with name of the main checkbox id
					e.checked=check;
				}
			}
		},

		/**
		 * Show hide specific element for the '+' sign and set it to '-' sign
		 */
		showHide: function(element){
			if (document.getElementById(element).style.display==''){
				document.getElementById(element).style.display='none';
				document.getElementById('plus_'+element).innerHTML='+';
			}else {
				document.getElementById(element).style.display='';
				document.getElementById('plus_'+element).innerHTML='-';
			}
		}
		
	}	
}
;/*
 * Date prototype extensions. Doesn't depend on any
 * other code. Doens't overwrite existing methods.
 *
 * Adds dayNames, abbrDayNames, monthNames and abbrMonthNames static properties and isLeapYear,
 * isWeekend, isWeekDay, getDaysInMonth, getDayName, getMonthName, getDayOfYear, getWeekOfYear,
 * setDayOfYear, addYears, addMonths, addDays, addHours, addMinutes, addSeconds methods
 *
 * Copyright (c) 2006 Jörn Zaefferer and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 *
 * Additional methods and properties added by Kelvin Luck: firstDayOfWeek, dateFormat, zeroTime, asString, fromString -
 * I've added my name to these methods so you know who to blame if they are broken!
 * 
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 */

/**
 * An Array of day names starting with Sunday.
 * 
 * @example dayNames[0]
 * @result 'Sunday'
 *
 * @name dayNames
 * @type Array
 * @cat Plugins/Methods/Date
 */
Date.dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

/**
 * An Array of abbreviated day names starting with Sun.
 * 
 * @example abbrDayNames[0]
 * @result 'Sun'
 *
 * @name abbrDayNames
 * @type Array
 * @cat Plugins/Methods/Date
 */
Date.abbrDayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];

/**
 * An Array of month names starting with Janurary.
 * 
 * @example monthNames[0]
 * @result 'January'
 *
 * @name monthNames
 * @type Array
 * @cat Plugins/Methods/Date
 */
Date.monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

/**
 * An Array of abbreviated month names starting with Jan.
 * 
 * @example abbrMonthNames[0]
 * @result 'Jan'
 *
 * @name monthNames
 * @type Array
 * @cat Plugins/Methods/Date
 */
Date.abbrMonthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

/**
 * The first day of the week for this locale.
 *
 * @name firstDayOfWeek
 * @type Number
 * @cat Plugins/Methods/Date
 * @author Kelvin Luck
 */
Date.firstDayOfWeek = 1;

/**
 * The format that string dates should be represented as (e.g. 'dd/mm/yyyy' for UK, 'mm/dd/yyyy' for US, 'yyyy-mm-dd' for Unicode etc).
 *
 * @name format
 * @type String
 * @cat Plugins/Methods/Date
 * @author Kelvin Luck
 */
Date.format = 'dd/mm/yyyy';
//Date.format = 'mm/dd/yyyy';
//Date.format = 'yyyy-mm-dd';
//Date.format = 'dd mmm yy';

/**
 * The first two numbers in the century to be used when decoding a two digit year. Since a two digit year is ambiguous (and date.setYear
 * only works with numbers < 99 and so doesn't allow you to set years after 2000) we need to use this to disambiguate the two digit year codes.
 *
 * @name format
 * @type String
 * @cat Plugins/Methods/Date
 * @author Kelvin Luck
 */
Date.fullYearStart = '20';

(function() {

	/**
	 * Adds a given method under the given name 
	 * to the Date prototype if it doesn't
	 * currently exist.
	 *
	 * @private
	 */
	function add(name, method) {
		if( !Date.prototype[name] ) {
			Date.prototype[name] = method;
		}
	};
	
	/**
	 * Checks if the year is a leap year.
	 *
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.isLeapYear();
	 * @result true
	 *
	 * @name isLeapYear
	 * @type Boolean
	 * @cat Plugins/Methods/Date
	 */
	add("isLeapYear", function() {
		var y = this.getFullYear();
		return (y%4==0 && y%100!=0) || y%400==0;
	});
	
	/**
	 * Checks if the day is a weekend day (Sat or Sun).
	 *
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.isWeekend();
	 * @result false
	 *
	 * @name isWeekend
	 * @type Boolean
	 * @cat Plugins/Methods/Date
	 */
	add("isWeekend", function() {
		return this.getDay()==0 || this.getDay()==6;
	});
	
	/**
	 * Check if the day is a day of the week (Mon-Fri)
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.isWeekDay();
	 * @result false
	 * 
	 * @name isWeekDay
	 * @type Boolean
	 * @cat Plugins/Methods/Date
	 */
	add("isWeekDay", function() {
		return !this.isWeekend();
	});
	
	/**
	 * Gets the number of days in the month.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.getDaysInMonth();
	 * @result 31
	 * 
	 * @name getDaysInMonth
	 * @type Number
	 * @cat Plugins/Methods/Date
	 */
	add("getDaysInMonth", function() {
		return [31,(this.isLeapYear() ? 29:28),31,30,31,30,31,31,30,31,30,31][this.getMonth()];
	});
	
	/**
	 * Gets the name of the day.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.getDayName();
	 * @result 'Saturday'
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.getDayName(true);
	 * @result 'Sat'
	 * 
	 * @param abbreviated Boolean When set to true the name will be abbreviated.
	 * @name getDayName
	 * @type String
	 * @cat Plugins/Methods/Date
	 */
	add("getDayName", function(abbreviated) {
		return abbreviated ? Date.abbrDayNames[this.getDay()] : Date.dayNames[this.getDay()];
	});

	/**
	 * Gets the name of the month.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.getMonthName();
	 * @result 'Janurary'
	 *
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.getMonthName(true);
	 * @result 'Jan'
	 * 
	 * @param abbreviated Boolean When set to true the name will be abbreviated.
	 * @name getDayName
	 * @type String
	 * @cat Plugins/Methods/Date
	 */
	add("getMonthName", function(abbreviated) {
		return abbreviated ? Date.abbrMonthNames[this.getMonth()] : Date.monthNames[this.getMonth()];
	});

	/**
	 * Get the number of the day of the year.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.getDayOfYear();
	 * @result 11
	 * 
	 * @name getDayOfYear
	 * @type Number
	 * @cat Plugins/Methods/Date
	 */
	add("getDayOfYear", function() {
		var tmpdtm = new Date("1/1/" + this.getFullYear());
		return Math.floor((this.getTime() - tmpdtm.getTime()) / 86400000);
	});
	
	/**
	 * Get the number of the week of the year.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.getWeekOfYear();
	 * @result 2
	 * 
	 * @name getWeekOfYear
	 * @type Number
	 * @cat Plugins/Methods/Date
	 */
	add("getWeekOfYear", function() {
		return Math.ceil(this.getDayOfYear() / 7);
	});

	/**
	 * Set the day of the year.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.setDayOfYear(1);
	 * dtm.toString();
	 * @result 'Tue Jan 01 2008 00:00:00'
	 * 
	 * @name setDayOfYear
	 * @type Date
	 * @cat Plugins/Methods/Date
	 */
	add("setDayOfYear", function(day) {
		this.setMonth(0);
		this.setDate(day);
		return this;
	});
	
	/**
	 * Add a number of years to the date object.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.addYears(1);
	 * dtm.toString();
	 * @result 'Mon Jan 12 2009 00:00:00'
	 * 
	 * @name addYears
	 * @type Date
	 * @cat Plugins/Methods/Date
	 */
	add("addYears", function(num) {
		this.setFullYear(this.getFullYear() + num);
		return this;
	});
	
	/**
	 * Add a number of months to the date object.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.addMonths(1);
	 * dtm.toString();
	 * @result 'Tue Feb 12 2008 00:00:00'
	 * 
	 * @name addMonths
	 * @type Date
	 * @cat Plugins/Methods/Date
	 */
	add("addMonths", function(num) {
		var tmpdtm = this.getDate();
		
		this.setMonth(this.getMonth() + num);
		
		if (tmpdtm > this.getDate())
			this.addDays(-this.getDate());
		
		return this;
	});
	
	/**
	 * Add a number of days to the date object.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.addDays(1);
	 * dtm.toString();
	 * @result 'Sun Jan 13 2008 00:00:00'
	 * 
	 * @name addDays
	 * @type Date
	 * @cat Plugins/Methods/Date
	 */
	add("addDays", function(num) {
		//this.setDate(this.getDate() + num);
		this.setTime(this.getTime() + (num*86400000) );
		return this;
	});
	
	/**
	 * Add a number of hours to the date object.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.addHours(24);
	 * dtm.toString();
	 * @result 'Sun Jan 13 2008 00:00:00'
	 * 
	 * @name addHours
	 * @type Date
	 * @cat Plugins/Methods/Date
	 */
	add("addHours", function(num) {
		this.setHours(this.getHours() + num);
		return this;
	});

	/**
	 * Add a number of minutes to the date object.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.addMinutes(60);
	 * dtm.toString();
	 * @result 'Sat Jan 12 2008 01:00:00'
	 * 
	 * @name addMinutes
	 * @type Date
	 * @cat Plugins/Methods/Date
	 */
	add("addMinutes", function(num) {
		this.setMinutes(this.getMinutes() + num);
		return this;
	});
	
	/**
	 * Add a number of seconds to the date object.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.addSeconds(60);
	 * dtm.toString();
	 * @result 'Sat Jan 12 2008 00:01:00'
	 * 
	 * @name addSeconds
	 * @type Date
	 * @cat Plugins/Methods/Date
	 */
	add("addSeconds", function(num) {
		this.setSeconds(this.getSeconds() + num);
		return this;
	});
	
	/**
	 * Sets the time component of this Date to zero for cleaner, easier comparison of dates where time is not relevant.
	 * 
	 * @example var dtm = new Date();
	 * dtm.zeroTime();
	 * dtm.toString();
	 * @result 'Sat Jan 12 2008 00:01:00'
	 * 
	 * @name zeroTime
	 * @type Date
	 * @cat Plugins/Methods/Date
	 * @author Kelvin Luck
	 */
	add("zeroTime", function() {
		this.setMilliseconds(0);
		this.setSeconds(0);
		this.setMinutes(0);
		this.setHours(0);
		return this;
	});
	
	/**
	 * Returns a string representation of the date object according to Date.format.
	 * (Date.toString may be used in other places so I purposefully didn't overwrite it)
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.asString();
	 * @result '12/01/2008' // (where Date.format == 'dd/mm/yyyy'
	 * 
	 * @name asString
	 * @type Date
	 * @cat Plugins/Methods/Date
	 * @author Kelvin Luck
	 */
	add("asString", function(format) {
		var r = format || Date.format;
		return r
			.split('yyyy').join(this.getFullYear())
			.split('yy').join((this.getFullYear() + '').substring(2))
			.split('mmmm').join(this.getMonthName(false))
			.split('mmm').join(this.getMonthName(true))
			.split('mm').join(_zeroPad(this.getMonth()+1))
			.split('dd').join(_zeroPad(this.getDate()))
			.split('hh').join(_zeroPad(this.getHours()))
			.split('min').join(_zeroPad(this.getMinutes()))
			.split('ss').join(_zeroPad(this.getSeconds()));
	});
	
	/**
	 * Returns a new date object created from the passed String according to Date.format or false if the attempt to do this results in an invalid date object
	 * (We can't simple use Date.parse as it's not aware of locale and I chose not to overwrite it incase it's functionality is being relied on elsewhere)
	 *
	 * @example var dtm = Date.fromString("12/01/2008");
	 * dtm.toString();
	 * @result 'Sat Jan 12 2008 00:00:00' // (where Date.format == 'dd/mm/yyyy'
	 * 
	 * @name fromString
	 * @type Date
	 * @cat Plugins/Methods/Date
	 * @author Kelvin Luck
	 */
	Date.fromString = function(s, format)
	{
		var f = format || Date.format;
		var d = new Date('01/01/1977');
		
		var mLength = 0;

		var iM = f.indexOf('mmmm');
		if (iM > -1) {
			for (var i=0; i<Date.monthNames.length; i++) {
				var mStr = s.substr(iM, Date.monthNames[i].length);
				if (Date.monthNames[i] == mStr) {
					mLength = Date.monthNames[i].length - 4;
					break;
				}
			}
			d.setMonth(i);
		} else {
			iM = f.indexOf('mmm');
			if (iM > -1) {
				var mStr = s.substr(iM, 3);
				for (var i=0; i<Date.abbrMonthNames.length; i++) {
					if (Date.abbrMonthNames[i] == mStr) break;
				}
				d.setMonth(i);
			} else {
				d.setMonth(Number(s.substr(f.indexOf('mm'), 2)) - 1);
			}
		}
		
		var iY = f.indexOf('yyyy');

		if (iY > -1) {
			if (iM < iY)
			{
				iY += mLength;
			}
			d.setFullYear(Number(s.substr(iY, 4)));
		} else {
			if (iM < iY)
			{
				iY += mLength;
			}
			// TODO - this doesn't work very well - are there any rules for what is meant by a two digit year?
			d.setFullYear(Number(Date.fullYearStart + s.substr(f.indexOf('yy'), 2)));
		}
		var iD = f.indexOf('dd');
		if (iM < iD)
		{
			iD += mLength;
		}
		d.setDate(Number(s.substr(iD, 2)));
		if (isNaN(d.getTime())) {
			return false;
		}
		return d;
	};
	
	// utility method
	var _zeroPad = function(num) {
		var s = '0'+num;
		return s.substring(s.length-2)
		//return ('0'+num).substring(-2); // doesn't work on IE :(
	};
	
})();/*
 * jQuery UI Datepicker 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/Datepicker
 *
 * Depends:
 *	ui.core.js
 */

(function($) { // hide the namespace

$.extend($.ui, { datepicker: { version: "1.7.2" } });

var PROP_NAME = 'datepicker';

/* Date picker manager.
   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
   Settings for (groups of) date pickers are maintained in an instance object,
   allowing multiple different settings on the same page. */

function Datepicker() {
	this.debug = false; // Change this to true to start debugging
	this._curInst = null; // The current instance in use
	this._keyEvent = false; // If the last event was a key event
	this._disabledInputs = []; // List of date picker inputs that have been disabled
	this._datepickerShowing = false; // True if the popup picker is showing , false if not
	this._inDialog = false; // True if showing within a "dialog", false if not
	this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
	this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
	this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
	this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
	this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
	this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
	this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
	this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
	this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
	this.regional = []; // Available regional settings, indexed by language code
	this.regional[''] = { // Default regional settings
		closeText: 'Done', // Display text for close link
		prevText: 'Prev', // Display text for previous month link
		nextText: 'Next', // Display text for next month link
		currentText: 'Today', // Display text for current month link
		monthNames: ['January','February','March','April','May','June',
			'July','August','September','October','November','December'], // Names of months for drop-down and formatting
		monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
		dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
		dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
		dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
		dateFormat: 'dd/mm/yy', // See format options on parseDate
		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
		isRTL: false // True if right-to-left language, false if left-to-right
	};
	this._defaults = { // Global defaults for all the date picker instances
		showOn: 'focus', // 'focus' for popup on focus,
			// 'button' for trigger button, or 'both' for either
		showAnim: 'show', // Name of jQuery animation for popup
		showOptions: {}, // Options for enhanced animations
		defaultDate: null, // Used when field is blank: actual date,
			// +/-number for offset from today, null for today
		appendText: '', // Display text following the input box, e.g. showing the format
		buttonText: '...', // Text for trigger button
		buttonImage: '', // URL for trigger button image
		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
		hideIfNoPrevNext: false, // True to hide next/previous month links
			// if not applicable, false to just disable them
		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
		gotoCurrent: false, // True if today link goes back to current selection instead
		changeMonth: false, // True if month can be selected directly, false if only prev/next
		changeYear: false, // True if year can be selected directly, false if only prev/next
		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
		yearRange: '-10:+10', // Range of years to display in drop-down,
			// either relative to current year (-nn:+nn) or absolute (nnnn:nnnn)
		showOtherMonths: false, // True to show dates in other months, false to leave blank
		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
			// takes a Date and returns the number of the week for it
		shortYearCutoff: '+10', // Short year values < this are in the current century,
			// > this are in the previous century,
			// string value starting with '+' for current year + value
		minDate: null, // The earliest selectable date, or null for no limit
		maxDate: null, // The latest selectable date, or null for no limit
		duration: 'normal', // Duration of display/closure
		beforeShowDay: null, // Function that takes a date and returns an array with
			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
		beforeShow: null, // Function that takes an input field and
			// returns a set of custom settings for the date picker
		onSelect: null, // Define a callback function when a date is selected
		onChangeMonthYear: null, // Define a callback function when the month or year is changed
		onClose: null, // Define a callback function when the datepicker is closed
		numberOfMonths: 1, // Number of months to show at a time
		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
		stepMonths: 1, // Number of months to step back/forward
		stepBigMonths: 12, // Number of months to step back/forward for the big links
		altField: '', // Selector for an alternate field to store selected dates into
		altFormat: '', // The date format to use for the alternate field
		constrainInput: true, // The input is constrained by the current date format
		showButtonPanel: false // True to show button panel, false to not show it
	};
	$.extend(this._defaults, this.regional['']);
	this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
}

$.extend(Datepicker.prototype, {
	/* Class name added to elements to indicate already configured with a date picker. */
	markerClassName: 'hasDatepicker',

	/* Debug logging (if enabled). */
	log: function () {
		if (this.debug)
			console.log.apply('', arguments);
	},

	/* Override the default settings for all instances of the date picker.
	   @param  settings  object - the new settings to use as defaults (anonymous object)
	   @return the manager object */
	setDefaults: function(settings) {
		extendRemove(this._defaults, settings || {});
		return this;
	},

	/* Attach the date picker to a jQuery selection.
	   @param  target    element - the target input field or division or span
	   @param  settings  object - the new settings to use for this date picker instance (anonymous) */
	_attachDatepicker: function(target, settings) {
		// check for settings on the control itself - in namespace 'date:'
		var inlineSettings = null;
		for (var attrName in this._defaults) {
			var attrValue = target.getAttribute('date:' + attrName);
			if (attrValue) {
				inlineSettings = inlineSettings || {};
				try {
					inlineSettings[attrName] = eval(attrValue);
				} catch (err) {
					inlineSettings[attrName] = attrValue;
				}
			}
		}
		var nodeName = target.nodeName.toLowerCase();
		var inline = (nodeName == 'div' || nodeName == 'span');
		if (!target.id)
			target.id = 'dp' + (++this.uuid);
		var inst = this._newInst($(target), inline);
		inst.settings = $.extend({}, settings || {}, inlineSettings || {});
		if (nodeName == 'input') {
			this._connectDatepicker(target, inst);
		} else if (inline) {
			this._inlineDatepicker(target, inst);
		}
	},

	/* Create a new instance object. */
	_newInst: function(target, inline) {
		var id = target[0].id.replace(/([:\[\]\.])/g, '\\\\$1'); // escape jQuery meta chars
		return {id: id, input: target, // associated target
			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
			drawMonth: 0, drawYear: 0, // month being drawn
			inline: inline, // is datepicker inline or not
			dpDiv: (!inline ? this.dpDiv : // presentation div
			$('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
	},

	/* Attach the date picker to an input field. */
	_connectDatepicker: function(target, inst) {
		var input = $(target);
		inst.append = $([]);
		inst.trigger = $([]);
		if (input.hasClass(this.markerClassName))
			return;
		var appendText = this._get(inst, 'appendText');
		var isRTL = this._get(inst, 'isRTL');
		if (appendText) {
			inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
			input[isRTL ? 'before' : 'after'](inst.append);
		}
		var showOn = this._get(inst, 'showOn');
		if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
			input.focus(this._showDatepicker);
		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
			var buttonText = this._get(inst, 'buttonText');
			var buttonImage = this._get(inst, 'buttonImage');
			inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
				$('<img/>').addClass(this._triggerClass).
					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
				$('<button type="button"></button>').addClass(this._triggerClass).
					html(buttonImage == '' ? buttonText : $('<img/>').attr(
					{ src:buttonImage, alt:buttonText, title:buttonText })));
			input[isRTL ? 'before' : 'after'](inst.trigger);
			inst.trigger.click(function() {
				if ($.datepicker._datepickerShowing && $.datepicker._lastInput == target)
					$.datepicker._hideDatepicker();
				else
					$.datepicker._showDatepicker(target);
				return false;
			});
		}
		input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).
			bind("setData.datepicker", function(event, key, value) {
				inst.settings[key] = value;
			}).bind("getData.datepicker", function(event, key) {
				return this._get(inst, key);
			});
		$.data(target, PROP_NAME, inst);
	},

	/* Attach an inline date picker to a div. */
	_inlineDatepicker: function(target, inst) {
		var divSpan = $(target);
		if (divSpan.hasClass(this.markerClassName))
			return;
		divSpan.addClass(this.markerClassName).append(inst.dpDiv).
			bind("setData.datepicker", function(event, key, value){
				inst.settings[key] = value;
			}).bind("getData.datepicker", function(event, key){
				return this._get(inst, key);
			});
		$.data(target, PROP_NAME, inst);
		this._setDate(inst, this._getDefaultDate(inst));
		this._updateDatepicker(inst);
		this._updateAlternate(inst);
	},

	/* Pop-up the date picker in a "dialog" box.
	   @param  input     element - ignored
	   @param  dateText  string - the initial date to display (in the current format)
	   @param  onSelect  function - the function(dateText) to call when a date is selected
	   @param  settings  object - update the dialog date picker instance's settings (anonymous object)
	   @param  pos       int[2] - coordinates for the dialog's position within the screen or
	                     event - with x/y coordinates or
	                     leave empty for default (screen centre)
	   @return the manager object */
	_dialogDatepicker: function(input, dateText, onSelect, settings, pos) {
		var inst = this._dialogInst; // internal instance
		if (!inst) {
			var id = 'dp' + (++this.uuid);
			this._dialogInput = $('<input type="text" id="' + id +
				'" size="1" style="position: absolute; top: -100px;"/>');
			this._dialogInput.keydown(this._doKeyDown);
			$('body').append(this._dialogInput);
			inst = this._dialogInst = this._newInst(this._dialogInput, false);
			inst.settings = {};
			$.data(this._dialogInput[0], PROP_NAME, inst);
		}
		extendRemove(inst.settings, settings || {});
		this._dialogInput.val(dateText);

		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
		if (!this._pos) {
			var browserWidth = window.innerWidth || document.documentElement.clientWidth ||	document.body.clientWidth;
			var browserHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
			this._pos = // should use actual width/height below
				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
		}

		// move input on screen for focus, but hidden behind dialog
		this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px');
		inst.settings.onSelect = onSelect;
		this._inDialog = true;
		this.dpDiv.addClass(this._dialogClass);
		this._showDatepicker(this._dialogInput[0]);
		if ($.blockUI)
			$.blockUI(this.dpDiv);
		$.data(this._dialogInput[0], PROP_NAME, inst);
		return this;
	},

	/* Detach a datepicker from its control.
	   @param  target    element - the target input field or division or span */
	_destroyDatepicker: function(target) {
		var $target = $(target);
		var inst = $.data(target, PROP_NAME);
		if (!$target.hasClass(this.markerClassName)) {
			return;
		}
		var nodeName = target.nodeName.toLowerCase();
		$.removeData(target, PROP_NAME);
		if (nodeName == 'input') {
			inst.append.remove();
			inst.trigger.remove();
			$target.removeClass(this.markerClassName).
				unbind('focus', this._showDatepicker).
				unbind('keydown', this._doKeyDown).
				unbind('keypress', this._doKeyPress);
		} else if (nodeName == 'div' || nodeName == 'span')
			$target.removeClass(this.markerClassName).empty();
	},

	/* Enable the date picker to a jQuery selection.
	   @param  target    element - the target input field or division or span */
	_enableDatepicker: function(target) {
		var $target = $(target);
		var inst = $.data(target, PROP_NAME);
		if (!$target.hasClass(this.markerClassName)) {
			return;
		}
		var nodeName = target.nodeName.toLowerCase();
		if (nodeName == 'input') {
			target.disabled = false;
			inst.trigger.filter('button').
				each(function() { this.disabled = false; }).end().
				filter('img').css({opacity: '1.0', cursor: ''});
		}
		else if (nodeName == 'div' || nodeName == 'span') {
			var inline = $target.children('.' + this._inlineClass);
			inline.children().removeClass('ui-state-disabled');
		}
		this._disabledInputs = $.map(this._disabledInputs,
			function(value) { return (value == target ? null : value); }); // delete entry
	},

	/* Disable the date picker to a jQuery selection.
	   @param  target    element - the target input field or division or span */
	_disableDatepicker: function(target) {
		var $target = $(target);
		var inst = $.data(target, PROP_NAME);
		if (!$target.hasClass(this.markerClassName)) {
			return;
		}
		var nodeName = target.nodeName.toLowerCase();
		if (nodeName == 'input') {
			target.disabled = true;
			inst.trigger.filter('button').
				each(function() { this.disabled = true; }).end().
				filter('img').css({opacity: '0.5', cursor: 'default'});
		}
		else if (nodeName == 'div' || nodeName == 'span') {
			var inline = $target.children('.' + this._inlineClass);
			inline.children().addClass('ui-state-disabled');
		}
		this._disabledInputs = $.map(this._disabledInputs,
			function(value) { return (value == target ? null : value); }); // delete entry
		this._disabledInputs[this._disabledInputs.length] = target;
	},

	/* Is the first field in a jQuery collection disabled as a datepicker?
	   @param  target    element - the target input field or division or span
	   @return boolean - true if disabled, false if enabled */
	_isDisabledDatepicker: function(target) {
		if (!target) {
			return false;
		}
		for (var i = 0; i < this._disabledInputs.length; i++) {
			if (this._disabledInputs[i] == target)
				return true;
		}
		return false;
	},

	/* Retrieve the instance data for the target control.
	   @param  target  element - the target input field or division or span
	   @return  object - the associated instance data
	   @throws  error if a jQuery problem getting data */
	_getInst: function(target) {
		try {
			return $.data(target, PROP_NAME);
		}
		catch (err) {
			throw 'Missing instance data for this datepicker';
		}
	},

	/* Update or retrieve the settings for a date picker attached to an input field or division.
	   @param  target  element - the target input field or division or span
	   @param  name    object - the new settings to update or
	                   string - the name of the setting to change or retrieve,
	                   when retrieving also 'all' for all instance settings or
	                   'defaults' for all global defaults
	   @param  value   any - the new value for the setting
	                   (omit if above is an object or to retrieve a value) */
	_optionDatepicker: function(target, name, value) {
		var inst = this._getInst(target);
		if (arguments.length == 2 && typeof name == 'string') {
			return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
				(inst ? (name == 'all' ? $.extend({}, inst.settings) :
				this._get(inst, name)) : null));
		}
		var settings = name || {};
		if (typeof name == 'string') {
			settings = {};
			settings[name] = value;
		}
		if (inst) {
			if (this._curInst == inst) {
				this._hideDatepicker(null);
			}
			var date = this._getDateDatepicker(target);
			extendRemove(inst.settings, settings);
			this._setDateDatepicker(target, date);
			this._updateDatepicker(inst);
		}
	},

	// change method deprecated
	_changeDatepicker: function(target, name, value) {
		this._optionDatepicker(target, name, value);
	},

	/* Redraw the date picker attached to an input field or division.
	   @param  target  element - the target input field or division or span */
	_refreshDatepicker: function(target) {
		var inst = this._getInst(target);
		if (inst) {
			this._updateDatepicker(inst);
		}
	},

	/* Set the dates for a jQuery selection.
	   @param  target   element - the target input field or division or span
	   @param  date     Date - the new date
	   @param  endDate  Date - the new end date for a range (optional) */
	_setDateDatepicker: function(target, date, endDate) {
		var inst = this._getInst(target);
		if (inst) {
			this._setDate(inst, date, endDate);
			this._updateDatepicker(inst);
			this._updateAlternate(inst);
		}
	},

	/* Get the date(s) for the first entry in a jQuery selection.
	   @param  target  element - the target input field or division or span
	   @return Date - the current date or
	           Date[2] - the current dates for a range */
	_getDateDatepicker: function(target) {
		var inst = this._getInst(target);
		if (inst && !inst.inline)
			this._setDateFromField(inst);
		return (inst ? this._getDate(inst) : null);
	},

	/* Handle keystrokes. */
	_doKeyDown: function(event) {
		var inst = $.datepicker._getInst(event.target);
		var handled = true;
		var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
		inst._keyEvent = true;
		if ($.datepicker._datepickerShowing)
			switch (event.keyCode) {
				case 9:  $.datepicker._hideDatepicker(null, '');
						break; // hide on tab out
				case 13: var sel = $('td.' + $.datepicker._dayOverClass +
							', td.' + $.datepicker._currentClass, inst.dpDiv);
						if (sel[0])
							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
						else
							$.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
						return false; // don't submit the form
						break; // select the value on enter
				case 27: $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
						break; // hide on escape
				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
							-$.datepicker._get(inst, 'stepBigMonths') :
							-$.datepicker._get(inst, 'stepMonths')), 'M');
						break; // previous month/year on page up/+ ctrl
				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
							+$.datepicker._get(inst, 'stepBigMonths') :
							+$.datepicker._get(inst, 'stepMonths')), 'M');
						break; // next month/year on page down/+ ctrl
				case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
						handled = event.ctrlKey || event.metaKey;
						break; // clear on ctrl or command +end
				case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
						handled = event.ctrlKey || event.metaKey;
						break; // current on ctrl or command +home
				case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
						handled = event.ctrlKey || event.metaKey;
						// -1 day on ctrl or command +left
						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
									-$.datepicker._get(inst, 'stepBigMonths') :
									-$.datepicker._get(inst, 'stepMonths')), 'M');
						// next month/year on alt +left on Mac
						break;
				case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
						handled = event.ctrlKey || event.metaKey;
						break; // -1 week on ctrl or command +up
				case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
						handled = event.ctrlKey || event.metaKey;
						// +1 day on ctrl or command +right
						if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
									+$.datepicker._get(inst, 'stepBigMonths') :
									+$.datepicker._get(inst, 'stepMonths')), 'M');
						// next month/year on alt +right
						break;
				case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
						handled = event.ctrlKey || event.metaKey;
						break; // +1 week on ctrl or command +down
				default: handled = false;
			}
		else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
			$.datepicker._showDatepicker(this);
		else {
			handled = false;
		}
		if (handled) {
			event.preventDefault();
			event.stopPropagation();
		}
	},

	/* Filter entered characters - based on date format. */
	_doKeyPress: function(event) {
		var inst = $.datepicker._getInst(event.target);
		if ($.datepicker._get(inst, 'constrainInput')) {
			var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
			var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
			return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
		}
	},

	/* Pop-up the date picker for a given input field.
	   @param  input  element - the input field attached to the date picker or
	                  event - if triggered by focus */
	_showDatepicker: function(input) {
		input = input.target || input;
		if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
			input = $('input', input.parentNode)[0];
		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
			return;
		var inst = $.datepicker._getInst(input);
		var beforeShow = $.datepicker._get(inst, 'beforeShow');
		extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
		$.datepicker._hideDatepicker(null, '');
		$.datepicker._lastInput = input;
		$.datepicker._setDateFromField(inst);
		if ($.datepicker._inDialog) // hide cursor
			input.value = '';
		if (!$.datepicker._pos) { // position below input
			$.datepicker._pos = $.datepicker._findPos(input);
			$.datepicker._pos[1] += input.offsetHeight; // add the height
		}
		var isFixed = false;
		$(input).parents().each(function() {
			isFixed |= $(this).css('position') == 'fixed';
			return !isFixed;
		});
		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
			$.datepicker._pos[0] -= document.documentElement.scrollLeft;
			$.datepicker._pos[1] -= document.documentElement.scrollTop;
		}
		var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
		$.datepicker._pos = null;
		inst.rangeStart = null;
		// determine sizing offscreen
		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
		$.datepicker._updateDatepicker(inst);
		// fix width for dynamic number of date pickers
		// and adjust position before showing
		offset = $.datepicker._checkOffset(inst, offset, isFixed);
		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
			'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
			left: offset.left + 'px', top: offset.top + 'px'});
		if (!inst.inline) {
			var showAnim = $.datepicker._get(inst, 'showAnim') || 'show';
			var duration = $.datepicker._get(inst, 'duration');
			var postProcess = function() {
				$.datepicker._datepickerShowing = true;
				if ($.browser.msie && parseInt($.browser.version,10) < 7) // fix IE < 7 select problems
					$('iframe.ui-datepicker-cover').css({width: inst.dpDiv.width() + 4,
						height: inst.dpDiv.height() + 4});
			};
			if ($.effects && $.effects[showAnim])
				inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
			else
				inst.dpDiv[showAnim](duration, postProcess);
			if (duration == '')
				postProcess();
			if (inst.input[0].type != 'hidden')
				inst.input[0].focus();
			$.datepicker._curInst = inst;
		}
	},

	/* Generate the date picker content. */
	_updateDatepicker: function(inst) {
		var dims = {width: inst.dpDiv.width() + 4,
			height: inst.dpDiv.height() + 4};
		var self = this;
		inst.dpDiv.empty().append(this._generateHTML(inst))
			.find('iframe.ui-datepicker-cover').
				css({width: dims.width, height: dims.height})
			.end()
			.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
				.bind('mouseout', function(){
					$(this).removeClass('ui-state-hover');
					if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
					if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
				})
				.bind('mouseover', function(){
					if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
						$(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
						$(this).addClass('ui-state-hover');
						if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
						if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
					}
				})
			.end()
			.find('.' + this._dayOverClass + ' a')
				.trigger('mouseover')
			.end();
		var numMonths = this._getNumberOfMonths(inst);
		var cols = numMonths[1];
		var width = 17;
		if (cols > 1) {
			inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
		} else {
			inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
		}
		inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
			'Class']('ui-datepicker-multi');
		inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
			'Class']('ui-datepicker-rtl');
		if (inst.input && inst.input[0].type != 'hidden' && inst == $.datepicker._curInst)
			$(inst.input[0]).focus();
	},

	/* Check positioning to remain on screen. */
	_checkOffset: function(inst, offset, isFixed) {
		var dpWidth = inst.dpDiv.outerWidth();
		var dpHeight = inst.dpDiv.outerHeight();
		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
		var viewWidth = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) + $(document).scrollLeft();
		var viewHeight = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) + $(document).scrollTop();

		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;

		// now check if datepicker is showing outside window viewport - move to a better place if so.
		offset.left -= (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? Math.abs(offset.left + dpWidth - viewWidth) : 0;
		offset.top -= (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? Math.abs(offset.top + dpHeight + inputHeight*2 - viewHeight) : 0;

		return offset;
	},

	/* Find an object's position on the screen. */
	_findPos: function(obj) {
        while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
            obj = obj.nextSibling;
        }
        var position = $(obj).offset();
	    return [position.left, position.top];
	},

	/* Hide the date picker from view.
	   @param  input  element - the input field attached to the date picker
	   @param  duration  string - the duration over which to close the date picker */
	_hideDatepicker: function(input, duration) {
		var inst = this._curInst;
		if (!inst || (input && inst != $.data(input, PROP_NAME)))
			return;
		if (inst.stayOpen)
			this._selectDate('#' + inst.id, this._formatDate(inst,
				inst.currentDay, inst.currentMonth, inst.currentYear));
		inst.stayOpen = false;
		if (this._datepickerShowing) {
			duration = (duration != null ? duration : this._get(inst, 'duration'));
			var showAnim = this._get(inst, 'showAnim');
			var postProcess = function() {
				$.datepicker._tidyDialog(inst);
			};
			if (duration != '' && $.effects && $.effects[showAnim])
				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'),
					duration, postProcess);
			else
				inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' :
					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess);
			if (duration == '')
				this._tidyDialog(inst);
			var onClose = this._get(inst, 'onClose');
			if (onClose)
				onClose.apply((inst.input ? inst.input[0] : null),
					[(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
			this._datepickerShowing = false;
			this._lastInput = null;
			if (this._inDialog) {
				this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
				if ($.blockUI) {
					$.unblockUI();
					$('body').append(this.dpDiv);
				}
			}
			this._inDialog = false;
		}
		this._curInst = null;
	},

	/* Tidy up after a dialog display. */
	_tidyDialog: function(inst) {
		inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
	},

	/* Close date picker if clicked elsewhere. */
	_checkExternalClick: function(event) {
		if (!$.datepicker._curInst)
			return;
		var $target = $(event.target);
		if (($target.parents('#' + $.datepicker._mainDivId).length == 0) &&
				!$target.hasClass($.datepicker.markerClassName) &&
				!$target.hasClass($.datepicker._triggerClass) &&
				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
			$.datepicker._hideDatepicker(null, '');
	},

	/* Adjust one of the date sub-fields. */
	_adjustDate: function(id, offset, period) {
		var target = $(id);
		var inst = this._getInst(target[0]);
		if (this._isDisabledDatepicker(target[0])) {
			return;
		}
		this._adjustInstDate(inst, offset +
			(period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
			period);
		this._updateDatepicker(inst);
	},

	/* Action for current link. */
	_gotoToday: function(id) {
		var target = $(id);
		var inst = this._getInst(target[0]);
		if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
			inst.selectedDay = inst.currentDay;
			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
			inst.drawYear = inst.selectedYear = inst.currentYear;
		}
		else {
		var date = new Date();
		inst.selectedDay = date.getDate();
		inst.drawMonth = inst.selectedMonth = date.getMonth();
		inst.drawYear = inst.selectedYear = date.getFullYear();
		}
		this._notifyChange(inst);
		this._adjustDate(target);
	},

	/* Action for selecting a new month/year. */
	_selectMonthYear: function(id, select, period) {
		var target = $(id);
		var inst = this._getInst(target[0]);
		inst._selectingMonthYear = false;
		inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
		inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
			parseInt(select.options[select.selectedIndex].value,10);
		this._notifyChange(inst);
		this._adjustDate(target);
	},

	/* Restore input focus after not changing month/year. */
	_clickMonthYear: function(id) {
		var target = $(id);
		var inst = this._getInst(target[0]);
		if (inst.input && inst._selectingMonthYear && !$.browser.msie)
			inst.input[0].focus();
		inst._selectingMonthYear = !inst._selectingMonthYear;
	},

	/* Action for selecting a day. */
	_selectDay: function(id, month, year, td) {
		var target = $(id);
		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
			return;
		}
		var inst = this._getInst(target[0]);
		inst.selectedDay = inst.currentDay = $('a', td).html();
		inst.selectedMonth = inst.currentMonth = month;
		inst.selectedYear = inst.currentYear = year;
		if (inst.stayOpen) {
			inst.endDay = inst.endMonth = inst.endYear = null;
		}
		this._selectDate(id, this._formatDate(inst,
			inst.currentDay, inst.currentMonth, inst.currentYear));
		if (inst.stayOpen) {
			inst.rangeStart = this._daylightSavingAdjust(
				new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
			this._updateDatepicker(inst);
		}
	},

	/* Erase the input field and hide the date picker. */
	_clearDate: function(id) {
		var target = $(id);
		var inst = this._getInst(target[0]);
		inst.stayOpen = false;
		inst.endDay = inst.endMonth = inst.endYear = inst.rangeStart = null;
		this._selectDate(target, '');
	},

	/* Update the input field with the selected date. */
	_selectDate: function(id, dateStr) {
		var target = $(id);
		var inst = this._getInst(target[0]);
		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
		if (inst.input)
			inst.input.val(dateStr);
		this._updateAlternate(inst);
		var onSelect = this._get(inst, 'onSelect');
		if (onSelect)
			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
		else if (inst.input)
			inst.input.trigger('change'); // fire the change event
		if (inst.inline)
			this._updateDatepicker(inst);
		else if (!inst.stayOpen) {
			this._hideDatepicker(null, this._get(inst, 'duration'));
			this._lastInput = inst.input[0];
			if (typeof(inst.input[0]) != 'object')
				inst.input[0].focus(); // restore focus
			this._lastInput = null;
		}
	},

	/* Update any alternate field to synchronise with the main field. */
	_updateAlternate: function(inst) {
		var altField = this._get(inst, 'altField');
		if (altField) { // update alternate field too
			var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
			var date = this._getDate(inst);
			dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
			$(altField).each(function() { $(this).val(dateStr); });
		}
	},

	/* Set as beforeShowDay function to prevent selection of weekends.
	   @param  date  Date - the date to customise
	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
	noWeekends: function(date) {
		var day = date.getDay();
		return [(day > 0 && day < 6), ''];
	},

	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
	   @param  date  Date - the date to get the week for
	   @return  number - the number of the week within the year that contains this date */
	iso8601Week: function(date) {
		var checkDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
		var firstMon = new Date(checkDate.getFullYear(), 1 - 1, 4); // First week always contains 4 Jan
		var firstDay = firstMon.getDay() || 7; // Day of week: Mon = 1, ..., Sun = 7
		firstMon.setDate(firstMon.getDate() + 1 - firstDay); // Preceding Monday
		if (firstDay < 4 && checkDate < firstMon) { // Adjust first three days in year if necessary
			checkDate.setDate(checkDate.getDate() - 3); // Generate for previous year
			return $.datepicker.iso8601Week(checkDate);
		} else if (checkDate > new Date(checkDate.getFullYear(), 12 - 1, 28)) { // Check last three days in year
			firstDay = new Date(checkDate.getFullYear() + 1, 1 - 1, 4).getDay() || 7;
			if (firstDay > 4 && (checkDate.getDay() || 7) < firstDay - 3) { // Adjust if necessary
				return 1;
			}
		}
		return Math.floor(((checkDate - firstMon) / 86400000) / 7) + 1; // Weeks to given date
	},

	/* Parse a string value into a date object.
	   See formatDate below for the possible formats.

	   @param  format    string - the expected format of the date
	   @param  value     string - the date in the above format
	   @param  settings  Object - attributes include:
	                     shortYearCutoff  number - the cutoff year for determining the century (optional)
	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
	                     dayNames         string[7] - names of the days from Sunday (optional)
	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
	                     monthNames       string[12] - names of the months (optional)
	   @return  Date - the extracted date value or null if value is blank */
	parseDate: function (format, value, settings) {
		if (format == null || value == null)
			throw 'Invalid arguments';
		value = (typeof value == 'object' ? value.toString() : value + '');
		if (value == '')
			return null;
		var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
		var year = -1;
		var month = -1;
		var day = -1;
		var doy = -1;
		var literal = false;
		// Check whether a format character is doubled
		var lookAhead = function(match) {
			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
			if (matches)
				iFormat++;
			return matches;
		};
		// Extract a number from the string value
		var getNumber = function(match) {
			lookAhead(match);
			var origSize = (match == '@' ? 14 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)));
			var size = origSize;
			var num = 0;
			while (size > 0 && iValue < value.length &&
					value.charAt(iValue) >= '0' && value.charAt(iValue) <= '9') {
				num = num * 10 + parseInt(value.charAt(iValue++),10);
				size--;
			}
			if (size == origSize)
				throw 'Missing number at position ' + iValue;
			return num;
		};
		// Extract a name from the string value and convert to an index
		var getName = function(match, shortNames, longNames) {
			var names = (lookAhead(match) ? longNames : shortNames);
			var size = 0;
			for (var j = 0; j < names.length; j++)
				size = Math.max(size, names[j].length);
			var name = '';
			var iInit = iValue;
			while (size > 0 && iValue < value.length) {
				name += value.charAt(iValue++);
				for (var i = 0; i < names.length; i++)
					if (name == names[i])
						return i + 1;
				size--;
			}
			throw 'Unknown name at position ' + iInit;
		};
		// Confirm that a literal character matches the string value
		var checkLiteral = function() {
			if (value.charAt(iValue) != format.charAt(iFormat))
				throw 'Unexpected literal at position ' + iValue;
			iValue++;
		};
		var iValue = 0;
		for (var iFormat = 0; iFormat < format.length; iFormat++) {
			if (literal)
				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
					literal = false;
				else
					checkLiteral();
			else
				switch (format.charAt(iFormat)) {
					case 'd':
						day = getNumber('d');
						break;
					case 'D':
						getName('D', dayNamesShort, dayNames);
						break;
					case 'o':
						doy = getNumber('o');
						break;
					case 'm':
						month = getNumber('m');
						break;
					case 'M':
						month = getName('M', monthNamesShort, monthNames);
						break;
					case 'y':
						year = getNumber('y');
						break;
					case '@':
						var date = new Date(getNumber('@'));
						year = date.getFullYear();
						month = date.getMonth() + 1;
						day = date.getDate();
						break;
					case "'":
						if (lookAhead("'"))
							checkLiteral();
						else
							literal = true;
						break;
					default:
						checkLiteral();
				}
		}
		if (year == -1)
			year = new Date().getFullYear();
		else if (year < 100)
			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
				(year <= shortYearCutoff ? 0 : -100);
		if (doy > -1) {
			month = 1;
			day = doy;
			do {
				var dim = this._getDaysInMonth(year, month - 1);
				if (day <= dim)
					break;
				month++;
				day -= dim;
			} while (true);
		}
		var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
		if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
			throw 'Invalid date'; // E.g. 31/02/*
		return date;
	},

	/* Standard date formats. */
	ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
	COOKIE: 'D, dd M yy',
	ISO_8601: 'yy-mm-dd',
	RFC_822: 'D, d M y',
	RFC_850: 'DD, dd-M-y',
	RFC_1036: 'D, d M y',
	RFC_1123: 'D, d M yy',
	RFC_2822: 'D, d M yy',
	RSS: 'D, d M y', // RFC 822
	TIMESTAMP: '@',
	W3C: 'yy-mm-dd', // ISO 8601

	/* Format a date object into a string value.
	   The format can be combinations of the following:
	   d  - day of month (no leading zero)
	   dd - day of month (two digit)
	   o  - day of year (no leading zeros)
	   oo - day of year (three digit)
	   D  - day name short
	   DD - day name long
	   m  - month of year (no leading zero)
	   mm - month of year (two digit)
	   M  - month name short
	   MM - month name long
	   y  - year (two digit)
	   yy - year (four digit)
	   @ - Unix timestamp (ms since 01/01/1970)
	   '...' - literal text
	   '' - single quote

	   @param  format    string - the desired format of the date
	   @param  date      Date - the date value to format
	   @param  settings  Object - attributes include:
	                     dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
	                     dayNames         string[7] - names of the days from Sunday (optional)
	                     monthNamesShort  string[12] - abbreviated names of the months (optional)
	                     monthNames       string[12] - names of the months (optional)
	   @return  string - the date in the above format */
	formatDate: function (format, date, settings) {
		if (!date)
			return '';
		var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
		var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
		var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
		var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
		// Check whether a format character is doubled
		var lookAhead = function(match) {
			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
			if (matches)
				iFormat++;
			return matches;
		};
		// Format a number, with leading zero if necessary
		var formatNumber = function(match, value, len) {
			var num = '' + value;
			if (lookAhead(match))
				while (num.length < len)
					num = '0' + num;
			return num;
		};
		// Format a name, short or long as requested
		var formatName = function(match, value, shortNames, longNames) {
			return (lookAhead(match) ? longNames[value] : shortNames[value]);
		};
		var output = '';
		var literal = false;
		if (date)
			for (var iFormat = 0; iFormat < format.length; iFormat++) {
				if (literal)
					if (format.charAt(iFormat) == "'" && !lookAhead("'"))
						literal = false;
					else
						output += format.charAt(iFormat);
				else
					switch (format.charAt(iFormat)) {
						case 'd':
							output += formatNumber('d', date.getDate(), 2);
							break;
						case 'D':
							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
							break;
						case 'o':
							var doy = date.getDate();
							for (var m = date.getMonth() - 1; m >= 0; m--)
								doy += this._getDaysInMonth(date.getFullYear(), m);
							output += formatNumber('o', doy, 3);
							break;
						case 'm':
							output += formatNumber('m', date.getMonth() + 1, 2);
							break;
						case 'M':
							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
							break;
						case 'y':
							output += (lookAhead('y') ? date.getFullYear() :
								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
							break;
						case '@':
							output += date.getTime();
							break;
						case "'":
							if (lookAhead("'"))
								output += "'";
							else
								literal = true;
							break;
						default:
							output += format.charAt(iFormat);
					}
			}
		return output;
	},

	/* Extract all possible characters from the date format. */
	_possibleChars: function (format) {
		var chars = '';
		var literal = false;
		for (var iFormat = 0; iFormat < format.length; iFormat++)
			if (literal)
				if (format.charAt(iFormat) == "'" && !lookAhead("'"))
					literal = false;
				else
					chars += format.charAt(iFormat);
			else
				switch (format.charAt(iFormat)) {
					case 'd': case 'm': case 'y': case '@':
						chars += '0123456789';
						break;
					case 'D': case 'M':
						return null; // Accept anything
					case "'":
						if (lookAhead("'"))
							chars += "'";
						else
							literal = true;
						break;
					default:
						chars += format.charAt(iFormat);
				}
		return chars;
	},

	/* Get a setting value, defaulting if necessary. */
	_get: function(inst, name) {
		return inst.settings[name] !== undefined ?
			inst.settings[name] : this._defaults[name];
	},

	/* Parse existing date and initialise date picker. */
	_setDateFromField: function(inst) {
		var dateFormat = this._get(inst, 'dateFormat');
		var dates = inst.input ? inst.input.val() : null;
		inst.endDay = inst.endMonth = inst.endYear = null;
		var date = defaultDate = this._getDefaultDate(inst);
		var settings = this._getFormatConfig(inst);
		try {
			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
		} catch (event) {
			this.log(event);
			date = defaultDate;
		}
		inst.selectedDay = date.getDate();
		inst.drawMonth = inst.selectedMonth = date.getMonth();
		inst.drawYear = inst.selectedYear = date.getFullYear();
		inst.currentDay = (dates ? date.getDate() : 0);
		inst.currentMonth = (dates ? date.getMonth() : 0);
		inst.currentYear = (dates ? date.getFullYear() : 0);
		this._adjustInstDate(inst);
	},

	/* Retrieve the default date shown on opening. */
	_getDefaultDate: function(inst) {
		var date = this._determineDate(this._get(inst, 'defaultDate'), new Date());
		var minDate = this._getMinMaxDate(inst, 'min', true);
		var maxDate = this._getMinMaxDate(inst, 'max');
		date = (minDate && date < minDate ? minDate : date);
		date = (maxDate && date > maxDate ? maxDate : date);
		return date;
	},

	/* A date may be specified as an exact value or a relative one. */
	_determineDate: function(date, defaultDate) {
		var offsetNumeric = function(offset) {
			var date = new Date();
			date.setDate(date.getDate() + offset);
			return date;
		};
		var offsetString = function(offset, getDaysInMonth) {
			var date = new Date();
			var year = date.getFullYear();
			var month = date.getMonth();
			var day = date.getDate();
			var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
			var matches = pattern.exec(offset);
			while (matches) {
				switch (matches[2] || 'd') {
					case 'd' : case 'D' :
						day += parseInt(matches[1],10); break;
					case 'w' : case 'W' :
						day += parseInt(matches[1],10) * 7; break;
					case 'm' : case 'M' :
						month += parseInt(matches[1],10);
						day = Math.min(day, getDaysInMonth(year, month));
						break;
					case 'y': case 'Y' :
						year += parseInt(matches[1],10);
						day = Math.min(day, getDaysInMonth(year, month));
						break;
				}
				matches = pattern.exec(offset);
			}
			return new Date(year, month, day);
		};
		date = (date == null ? defaultDate :
			(typeof date == 'string' ? offsetString(date, this._getDaysInMonth) :
			(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
		date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
		if (date) {
			date.setHours(0);
			date.setMinutes(0);
			date.setSeconds(0);
			date.setMilliseconds(0);
		}
		return this._daylightSavingAdjust(date);
	},

	/* Handle switch to/from daylight saving.
	   Hours may be non-zero on daylight saving cut-over:
	   > 12 when midnight changeover, but then cannot generate
	   midnight datetime, so jump to 1AM, otherwise reset.
	   @param  date  (Date) the date to check
	   @return  (Date) the corrected date */
	_daylightSavingAdjust: function(date) {
		if (!date) return null;
		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
		return date;
	},

	/* Set the date(s) directly. */
	_setDate: function(inst, date, endDate) {
		var clear = !(date);
		var origMonth = inst.selectedMonth;
		var origYear = inst.selectedYear;
		date = this._determineDate(date, new Date());
		inst.selectedDay = inst.currentDay = date.getDate();
		inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
		inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
		if (origMonth != inst.selectedMonth || origYear != inst.selectedYear)
			this._notifyChange(inst);
		this._adjustInstDate(inst);
		if (inst.input) {
			inst.input.val(clear ? '' : this._formatDate(inst));
		}
	},

	/* Retrieve the date(s) directly. */
	_getDate: function(inst) {
		var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
			this._daylightSavingAdjust(new Date(
			inst.currentYear, inst.currentMonth, inst.currentDay)));
			return startDate;
	},

	/* Generate the HTML for the current state of the date picker. */
	_generateHTML: function(inst) {
		var today = new Date();
		today = this._daylightSavingAdjust(
			new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
		var isRTL = this._get(inst, 'isRTL');
		var showButtonPanel = this._get(inst, 'showButtonPanel');
		var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
		var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
		var numMonths = this._getNumberOfMonths(inst);
		var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
		var stepMonths = this._get(inst, 'stepMonths');
		var stepBigMonths = this._get(inst, 'stepBigMonths');
		var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
		var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
			new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
		var minDate = this._getMinMaxDate(inst, 'min', true);
		var maxDate = this._getMinMaxDate(inst, 'max');
		var drawMonth = inst.drawMonth - showCurrentAtPos;
		var drawYear = inst.drawYear;
		if (drawMonth < 0) {
			drawMonth += 12;
			drawYear--;
		}
		if (maxDate) {
			var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
				maxDate.getMonth() - numMonths[1] + 1, maxDate.getDate()));
			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
				drawMonth--;
				if (drawMonth < 0) {
					drawMonth = 11;
					drawYear--;
				}
			}
		}
		inst.drawMonth = drawMonth;
		inst.drawYear = drawYear;
		var prevText = this._get(inst, 'prevText');
		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
			this._getFormatConfig(inst)));
		var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
			'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
			' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
		var nextText = this._get(inst, 'nextText');
		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
			this._getFormatConfig(inst)));
		var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
			'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
			' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
			(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
		var currentText = this._get(inst, 'currentText');
		var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
		currentText = (!navigationAsDateFormat ? currentText :
			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
		var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
		var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
			(this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery.datepicker._gotoToday(\'#' + inst.id + '\');"' +
			'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
		var firstDay = parseInt(this._get(inst, 'firstDay'),10);
		firstDay = (isNaN(firstDay) ? 0 : firstDay);
		var dayNames = this._get(inst, 'dayNames');
		var dayNamesShort = this._get(inst, 'dayNamesShort');
		var dayNamesMin = this._get(inst, 'dayNamesMin');
		var monthNames = this._get(inst, 'monthNames');
		var monthNamesShort = this._get(inst, 'monthNamesShort');
		var beforeShowDay = this._get(inst, 'beforeShowDay');
		var showOtherMonths = this._get(inst, 'showOtherMonths');
		var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
		var endDate = inst.endDay ? this._daylightSavingAdjust(
			new Date(inst.endYear, inst.endMonth, inst.endDay)) : currentDate;
		var defaultDate = this._getDefaultDate(inst);
		var html = '';
		for (var row = 0; row < numMonths[0]; row++) {
			var group = '';
			for (var col = 0; col < numMonths[1]; col++) {
				var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
				var cornerClass = ' ui-corner-all';
				var calender = '';
				if (isMultiMonth) {
					calender += '<div class="ui-datepicker-group ui-datepicker-group-';
					switch (col) {
						case 0: calender += 'first'; cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
						case numMonths[1]-1: calender += 'last'; cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
						default: calender += 'middle'; cornerClass = ''; break;
					}
					calender += '">';
				}
				calender += '<div class="ui-datepicker-header ui-widget-header1 ui-helper-clearfix' + cornerClass + '">' +
					(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
					(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
					selectedDate, row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
					'</div><table class="ui-datepicker-calendar"><thead>' +
					'<tr>';
				var thead = '';
				for (var dow = 0; dow < 7; dow++) { // days of the week
					var day = (dow + firstDay) % 7;
					thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
						'<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
				}
				calender += thead + '</tr></thead><tbody>';
				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
				if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
				var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
				var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
				var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
				for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
					calender += '<tr>';
					var tbody = '';
					for (var dow = 0; dow < 7; dow++) { // create date picker days
						var daySettings = (beforeShowDay ?
							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
						var otherMonth = (printDate.getMonth() != drawMonth);
						var unselectable = otherMonth || !daySettings[0] ||
							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
						tbody += '<td class="' +
							((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
							(otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
							((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
							(defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
							// or defaultDate is current printedDate and defaultDate is selectedDate
							' ' + this._dayOverClass : '') + // highlight selected day
							(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
							(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
							(printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ? // in current range
							' ' + this._currentClass : '') + // highlight selected day
							(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
							((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
							(unselectable ? '' : ' onclick="DP_jQuery.datepicker._selectDay(\'#' +
							inst.id + '\',' + drawMonth + ',' + drawYear + ', this);return false;"') + '>' + // actions
							(otherMonth ? (showOtherMonths ? printDate.getDate() : '&#xa0;') : // display for other months
							(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
							(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
							(printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ? // in current range
							' ui-state-active' : '') + // highlight selected day
							'" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display for this month
						printDate.setDate(printDate.getDate() + 1);
						printDate = this._daylightSavingAdjust(printDate);
					}
					calender += tbody + '</tr>';
				}
				drawMonth++;
				if (drawMonth > 11) {
					drawMonth = 0;
					drawYear++;
				}
				calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
							((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
				group += calender;
			}
			html += group;
		}
		html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
			'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
		inst._keyEvent = false;
		return html;
	},

	/* Generate the month and year header. */
	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
			selectedDate, secondary, monthNames, monthNamesShort) {
		minDate = (inst.rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate);
		var changeMonth = this._get(inst, 'changeMonth');
		var changeYear = this._get(inst, 'changeYear');
		var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
		var html = '<div class="ui-datepicker-title">';
		var monthHtml = '';
		// month selection
		if (secondary || !changeMonth)
			monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span> ';
		else {
			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
			monthHtml += '<select class="ui-datepicker-month" ' +
				'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
				'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
			 	'>';
			for (var month = 0; month < 12; month++) {
				if ((!inMinYear || month >= minDate.getMonth()) &&
						(!inMaxYear || month <= maxDate.getMonth()))
					monthHtml += '<option value="' + month + '"' +
						(month == drawMonth ? ' selected="selected"' : '') +
						'>' + monthNamesShort[month] + '</option>';
			}
			monthHtml += '</select>';
		}
		if (!showMonthAfterYear)
			html += monthHtml + ((secondary || changeMonth || changeYear) && (!(changeMonth && changeYear)) ? '&#xa0;' : '');
		// year selection
		if (secondary || !changeYear)
			html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
		else {
			// determine range of years to display
			var years = this._get(inst, 'yearRange').split(':');
			var year = 0;
			var endYear = 0;
			if (years.length != 2) {
				year = drawYear - 10;
				endYear = drawYear + 10;
			} else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') {
				year = drawYear + parseInt(years[0], 10);
				endYear = drawYear + parseInt(years[1], 10);
			} else {
				year = parseInt(years[0], 10);
				endYear = parseInt(years[1], 10);
			}
			year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
			endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
			html += '<select class="ui-datepicker-year" ' +
				'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
				'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
				'>';
			for (; year <= endYear; year++) {
				html += '<option value="' + year + '"' +
					(year == drawYear ? ' selected="selected"' : '') +
					'>' + year + '</option>';
			}
			html += '</select>';
		}
		if (showMonthAfterYear)
			html += (secondary || changeMonth || changeYear ? '&#xa0;' : '') + monthHtml;
		html += '</div>'; // Close datepicker_header
		return html;
	},

	/* Adjust one of the date sub-fields. */
	_adjustInstDate: function(inst, offset, period) {
		var year = inst.drawYear + (period == 'Y' ? offset : 0);
		var month = inst.drawMonth + (period == 'M' ? offset : 0);
		var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
			(period == 'D' ? offset : 0);
		var date = this._daylightSavingAdjust(new Date(year, month, day));
		// ensure it is within the bounds set
		var minDate = this._getMinMaxDate(inst, 'min', true);
		var maxDate = this._getMinMaxDate(inst, 'max');
		date = (minDate && date < minDate ? minDate : date);
		date = (maxDate && date > maxDate ? maxDate : date);
		inst.selectedDay = date.getDate();
		inst.drawMonth = inst.selectedMonth = date.getMonth();
		inst.drawYear = inst.selectedYear = date.getFullYear();
		if (period == 'M' || period == 'Y')
			this._notifyChange(inst);
	},

	/* Notify change of month/year. */
	_notifyChange: function(inst) {
		var onChange = this._get(inst, 'onChangeMonthYear');
		if (onChange)
			onChange.apply((inst.input ? inst.input[0] : null),
				[inst.selectedYear, inst.selectedMonth + 1, inst]);
	},

	/* Determine the number of months to show. */
	_getNumberOfMonths: function(inst) {
		var numMonths = this._get(inst, 'numberOfMonths');
		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
	},

	/* Determine the current maximum date - ensure no time components are set - may be overridden for a range. */
	_getMinMaxDate: function(inst, minMax, checkRange) {
		var date = this._determineDate(this._get(inst, minMax + 'Date'), null);
		return (!checkRange || !inst.rangeStart ? date :
			(!date || inst.rangeStart > date ? inst.rangeStart : date));
	},

	/* Find the number of days in a given month. */
	_getDaysInMonth: function(year, month) {
		return 32 - new Date(year, month, 32).getDate();
	},

	/* Find the day of the week of the first of a month. */
	_getFirstDayOfMonth: function(year, month) {
		return new Date(year, month, 1).getDay();
	},

	/* Determines if we should allow a "next/prev" month display change. */
	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
		var numMonths = this._getNumberOfMonths(inst);
		var date = this._daylightSavingAdjust(new Date(
			curYear, curMonth + (offset < 0 ? offset : numMonths[1]), 1));
		if (offset < 0)
			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
		return this._isInRange(inst, date);
	},

	/* Is the given date in the accepted range? */
	_isInRange: function(inst, date) {
		// during range selection, use minimum of selected date and range start
		var newMinDate = (!inst.rangeStart ? null : this._daylightSavingAdjust(
			new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay)));
		newMinDate = (newMinDate && inst.rangeStart < newMinDate ? inst.rangeStart : newMinDate);
		var minDate = newMinDate || this._getMinMaxDate(inst, 'min');
		var maxDate = this._getMinMaxDate(inst, 'max');
		return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
	},

	/* Provide the configuration settings for formatting/parsing. */
	_getFormatConfig: function(inst) {
		var shortYearCutoff = this._get(inst, 'shortYearCutoff');
		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
		return {shortYearCutoff: shortYearCutoff,
			dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
			monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
	},

	/* Format the given date for display. */
	_formatDate: function(inst, day, month, year) {
		if (!day) {
			inst.currentDay = inst.selectedDay;
			inst.currentMonth = inst.selectedMonth;
			inst.currentYear = inst.selectedYear;
		}
		var date = (day ? (typeof day == 'object' ? day :
			this._daylightSavingAdjust(new Date(year, month, day))) :
			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
		return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
	}
});

/* jQuery extend now ignores nulls! */
function extendRemove(target, props) {
	$.extend(target, props);
	for (var name in props)
		if (props[name] == null || props[name] == undefined)
			target[name] = props[name];
	return target;
};

/* Determine whether an object is an array. */
function isArray(a) {
	return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
		(a.constructor && a.constructor.toString().match(/\Array\(\)/))));
};

/* Invoke the datepicker functionality.
   @param  options  string - a command, optionally followed by additional parameters or
                    Object - settings for attaching new datepicker functionality
   @return  jQuery object */
$.fn.datepicker = function(options){

	/* Initialise the date picker. */
	if (!$.datepicker.initialized) {
		$(document).mousedown($.datepicker._checkExternalClick).
			find('body').append($.datepicker.dpDiv);
		$.datepicker.initialized = true;
	}

	var otherArgs = Array.prototype.slice.call(arguments, 1);
	if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate'))
		return $.datepicker['_' + options + 'Datepicker'].
			apply($.datepicker, [this[0]].concat(otherArgs));
	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
		return $.datepicker['_' + options + 'Datepicker'].
			apply($.datepicker, [this[0]].concat(otherArgs));
	return this.each(function() {
		typeof options == 'string' ?
			$.datepicker['_' + options + 'Datepicker'].
				apply($.datepicker, [this].concat(otherArgs)) :
			$.datepicker._attachDatepicker(this, options);
	});
};

$.datepicker = new Datepicker(); // singleton instance
$.datepicker.initialized = false;
$.datepicker.uuid = new Date().getTime();
$.datepicker.version = "1.7.2";

// Workaround for #4055
// Add another global to avoid noConflict issues with inline event handlers
window.DP_jQuery = $;

})(jQuery);
ï»¿/* French initialisation for the jQuery UI date picker plugin. */
/* Written by Keith Wood (kbwood@virginbroadband.com.au) and StÃ©phane Nahmani (sholby@sholby.net). */
jQuery(function($){
	$.datepicker.regional['fr'] = {
		closeText: 'Fermer',
		prevText: '&#x3c;PrÃ©c',
		nextText: 'Suiv&#x3e;',
		currentText: 'Courant',
		monthNames: ['Janvier','FÃ©vrier','Mars','Avril','Mai','Juin',
		'Juillet','AoÃ»t','Septembre','Octobre','Novembre','DÃ©cembre'],
		monthNamesShort: ['Jan','FÃ©v','Mar','Avr','Mai','Jun',
		'Jul','AoÃ»','Sep','Oct','Nov','DÃ©c'],
		dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
		dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],
		dayNamesMin: ['Di','Lu','Ma','Me','Je','Ve','Sa'],
		dateFormat: 'dd/mm/yy', firstDay: 1,
		isRTL: false};
	$.datepicker.setDefaults($.datepicker.regional['fr']);
});/* 
    Document   : suggestion framework
    Author     : Arnaud CAVAILHEZ
*/

var eusuggestion = new function(){
	
    return {

		
        askForSuggestion: function (id){

            var valueToSuggest = document.getElementById(id).value;
		 
            //method AJAXInteractionServlet (from ajaxServlet.js) used to call the servlet
            var ai = new AJAXInteractionServlet('/SuggestionDealProposalRegularTitle_Servlet?value='+valueToSuggest,function (responseJSON){
                eusuggestion.suggestBack(id,responseJSON);
            });
            ai.doGet();
        },

        suggestBack: function(id,responseJSON){

            $("#"+id).unautocomplete();//remove previous suggestion values
			
            var xmlDoc = responseJSON.documentElement;
            if (xmlDoc){
	            var xRows = xmlDoc.getElementsByTagName('list');
	      
				if (xRows[0].firstChild!=null){
		            var suggestionlist = xRows[0].firstChild.nodeValue.split(";");
		
		            $("#"+id).autocomplete(suggestionlist, {
		                matchContains: "word" // true: search in whole word, word: search only beginning of word
		            });
				}
            }
        }
    };
}
;
var eufrontpage = {

    checkMail: function (){
        var mail = document.frontPageRegisterForm.mailRegister.value;
        var ai = new  AJAXInteractionServlet('/FPMail_Servlet?mail='+mail,
            function (responseXML){
                eufrontpage.handleMailMessage(responseXML);
            });
        ai.doGet();
    },

    handleMailMessage : function (responseXML){
        var xmlDoc = responseXML.documentElement
        var xRows = xmlDoc.getElementsByTagName('message');
        var html = "";
        for (i = 0; i < xRows.length ; i++) {
            var message = url.decode(xRows[i].firstChild.nodeValue);
            message = message.ReplaceAll("+"," ");
            html+=message+"<br/>"
        }
        if (html != ""){
        	document.getElementById('fp-mail-messages').innerHTML=html;
        }
    },
    
    setloginCompanyToBeFollowed : function(loginCompanyToBeFollowed){
		document.frontPageLoginForm.loginToBeFollowedCompanyBouton.value=loginCompanyToBeFollowed;
		document.frontPageLoginForm.submit();
	},
	
	
	populateSecteur: function (id,val){
		var value = parseInt(val)		
		var setSelectVal;
		if (parseInt(value) > 0) {			
			if (value == 2 || value == 4 || value == 6) {
				setSelectVal = value - 1; 
			} else {
				setSelectVal = value;
			}		
			document.getElementById(id).value = parseInt(setSelectVal);
		}
	},
	
	//inscription - accessed from many pages
	createUser:function (emailFieldId,secteurFieldId,errorFieldId){
		
		var selectedSecteur=0;
		var email = document.getElementById(emailFieldId).value;	
		var secteur = document.getElementById(secteurFieldId).value;	
		
		if (email == EU_TEXT.REGISTER_NULL_EMAIL) {
			email='';			
		}
		
		
			
		if (email.length > 0 && parseInt(secteur) > 0){			
			var params = 'email='+email+'&secteur='+parseInt(secteur);
			actionfeedback.doActionFeedback(errorFieldId,'/RegistrationServlet_Servlet',params);
		} else {
			if (email.length==0)
				document.getElementById(errorFieldId).innerHTML=EU_TEXT.REGISTER_WRONG_EMAIL;  
			else
				document.getElementById(errorFieldId).innerHTML=EU_TEXT.REGISTER_WRONG_SECTEUR;          
		}
	},
	
	resetFormSubscriptionPrestataire:function(){
		document.getElementById('txtEmailPrestataire').value = "";
        document.getElementById('cbSecteurPrestataire').value=0; 
        document.getElementById('errLoginPrestataire').innerHTML = "";  
        $('#txtEmailPrestataire').smartFocus(EU_TEXT.FRONTPAGE_TEMPLATE_EMAIL);       		
	},
	
	resetFormSubscriptionMarchandMedia:function(){
		document.getElementById('userregister').value = "";
        document.getElementById('cbSecteur').value=0; 
        document.getElementById('errLoginMsg').innerHTML = "";  
        $('#userregister').smartFocus(EU_TEXT.FRONTPAGE_TEMPLATE_EMAIL);       					
	}
	
}
;
/*
 Name:    Highcharts
 Version: 1.1.3 (2010-02-03)
 Author:  Vevstein Web
 Support: www.highcharts.com/support
 License: www.highcharts.com/license
*/
(function(){function Kb(a){return a&&a.constructor==Array}function hb(a,b,c){var d,e="",f=c?"print":"",h=function(g){return W("style",{type:"text/css",media:g?"print":""},null,la.getElementsByTagName("HEAD")[0])};zb||(zb=h());for(d in b)e+=kb(d)+":"+b[d]+";";if(ya){b=la.styleSheets;c&&h(true);for(c=b.length-1;c>=0&&b[c].media!=f;)c--;f=b[c];f.addRule(a,e)}else zb.appendChild(la.createTextNode(a+" {"+e+"}\n"))}function K(a,b){a||(a={});for(var c in b)a[c]=b[c];return a}function Zb(a){return Ja=R(Ja,
a)}function Wa(a,b){var c=function(){};c.prototype=new a;K(c.prototype,b);return c}function Ab(a){for(var b=[],c=a.length-1;c>=0;c--)b.push(a[c]);return b}function Lb(a,b){if(typeof a=="string")return a;else if(a.linearGradient){var c=b.createLinearGradient.apply(b,a.linearGradient);s(a.stops,function(d){c.addColorStop(d[0],d[1])});return c}}function W(a,b,c,d,e){a=la.createElement(a);b&&K(a,b);e&&ua(a,{padding:0,border:"none",margin:0});c&&ua(a,c);d&&d.appendChild(a);return a}function ua(a,b){if(ya)if(b.opacity!==
ha)b.filter="alpha(opacity="+b.opacity*100+")";K(a.style,b)}function $b(a,b,c,d){a=a;var e=isNaN(b=va(b))?2:b;b=c===ha?".":c;d=d===ha?",":d;c=a<0?"-":"";var f=parseInt(a=va(+a||0).toFixed(e))+"",h=(h=f.length)>3?h%3:0;return c+(h?f.substr(0,h)+d:"")+f.substr(h).replace(/(\d{3})(?=\d)/g,"$1"+d)+(e?b+va(a-f).toFixed(e).slice(2):"")}function Mb(a,b,c){function d(y){return y.toString().replace(/^([0-9])$/,"0$1")}b=new Date(b*za);var e=b.getUTCHours(),f=b.getUTCDay(),h=b.getUTCDate(),g=b.getUTCMonth(),
i=b.getUTCFullYear(),k=Ja.lang,r=k.weekdays;k=k.months;b={a:r[f].substr(0,3),A:r[f],d:d(h),e:h,b:k[g].substr(0,3),B:k[g],m:d(g+1),y:i.toString().substr(2,2),Y:i,H:d(e),I:d(e%12||12),l:e%12||12,M:d(b.getUTCMinutes()),p:e<12?"AM":"PM",P:e<12?"am":"pm",S:d(b.getUTCSeconds())};for(var l in b)a=a.replace("%"+l,b[l]);return c?a.substr(0,1).toUpperCase()+a.substr(1):a}function Nb(a){for(var b={x:a.offsetLeft,y:a.offsetTop};a.offsetParent;){a=a.offsetParent;b.x+=a.offsetLeft;b.y+=a.offsetTop;if(a!=la.body&&
a!=la.documentElement){b.x-=a.scrollLeft;b.y-=a.scrollTop}}return b}function ac(a){function b(){var p={line:Ca,spline:Ob,area:bc,areaspline:cc,column:Bb,bar:dc,pie:ec,scatter:fc},j,v;s(a.series,function(M){j=p[M.type||n.defaultSeriesType];v=new j;v.init(w,M);if(v.inverted)Qa=true;Xa.push(v)})}function c(){var p=a.xAxis||{},j=a.yAxis||{};Kb(p)||(p=[p]);s(p,function(v,M){v.index=M;v.isX=true});Kb(j)||(j=[j]);s(j,function(v,M){v.index=M});Ka=p.concat(j);Ka=Ra(Ka,function(v){return new i(w,v)});s(Ka,
function(v){v.adjustTickAmount()})}function d(){var p=true;for(var j in w.resources)w.resources[j]||(p=false);p&&h()}function e(p){w.toolbar.add("zoom",EU_TEXT.HIGHCHART_ZOOM,"Reset zoom level 1:1",function(){Fa(w,"selection",{resetSelection:true},e);w.toolbar.remove("zoom")});db=null;if(p.resetSelection)s(Ka,function(j){j.reset()});else{w.tracker.zoomX&&s(p.xAxis,function(j){j.axis.setExtremes(j.min,j.max)});w.tracker.zoomY&&s(p.yAxis,function(j){j.axis.setExtremes(j.min,j.max)})}s(Ka,function(j){j.adjustTickAmount()});
ib.hide();s(w.series,function(j){s(j.areas,function(v){v.parentNode&&v.parentNode.removeChild(v)});j.translate();j.createArea();j.clear();j.type=="spline"&&j.getSplineData()});lb&&s(Ka,function(j){j.render()});s(Xa,function(j){j.render()})}function f(){if(!w.titleLayer){var p=new ka("title-layer",Y,null,{zIndex:5});a.title&&W("h2",{className:"highcharts-title",innerHTML:a.title.text},a.title.style,p.div);a.subtitle&&W("h3",{className:"highcharts-subtitle",innerHTML:a.subtitle.text},a.subtitle.style,
p.div);w.titleLayer=p}}function h(){c();s(Xa,function(p){p.translate();a.tooltip.enabled
