//MooTools, My Object Oriented Javascript Tools. Copyright (c) 2006 Valerio Proietti, <http://mad4milk.net>, MIT Style License.
var MooTools={version:"1.12"};function $defined(a){return(a!=undefined)}function $type(b){if(!$defined(b)){return false}if(b.htmlElement){return"element"}var a=typeof b;if(a=="object"&&b.nodeName){switch(b.nodeType){case 1:return"element";case 3:return(/\S/).test(b.nodeValue)?"textnode":"whitespace"}}if(a=="object"||a=="function"){switch(b.constructor){case Array:return"array";case RegExp:return"regexp";case Class:return"class"}if(typeof b.length=="number"){if(b.item){return"collection"}if(b.callee){return"arguments"}}}return a}function $merge(){var c={};for(var b=0;b<arguments.length;b++){for(var f in arguments[b]){var a=arguments[b][f];var d=c[f];if(d&&$type(a)=="object"&&$type(d)=="object"){c[f]=$merge(d,a)}else{c[f]=a}}}return c}var $extend=function(){var a=arguments;if(!a[1]){a=[this,a[0]]}for(var b in a[1]){a[0][b]=a[1][b]}return a[0]};var $native=function(){for(var b=0,a=arguments.length;b<a;b++){arguments[b].extend=function(c){for(var d in c){if(!this.prototype[d]){this.prototype[d]=c[d]}if(!this[d]){this[d]=$native.generic(d)}}}}};$native.generic=function(a){return function(b){return this.prototype[a].apply(b,Array.prototype.slice.call(arguments,1))}};$native(Function,Array,String,Number);function $chk(a){return !!(a||a===0)}function $pick(b,a){return $defined(b)?b:a}function $random(b,a){return Math.floor(Math.random()*(a-b+1)+b)}function $time(){return new Date().getTime()}function $clear(a){clearTimeout(a);clearInterval(a);return null}var Abstract=function(a){a=a||{};a.extend=$extend;return a};var Window=new Abstract(window);var Document=new Abstract(document);document.head=document.getElementsByTagName("head")[0];window.xpath=!!(document.evaluate);if(window.ActiveXObject){window.ie=window[window.XMLHttpRequest?"ie7":"ie6"]=true}else{if(document.childNodes&&!document.all&&!navigator.taintEnabled){window.webkit=window[window.xpath?"webkit420":"webkit419"]=true}else{if(document.getBoxObjectFor!=null||window.mozInnerScreenX!=null){window.gecko=true}}}window.khtml=window.webkit;Object.extend=$extend;if(typeof HTMLElement=="undefined"){var HTMLElement=function(){};if(window.webkit){document.createElement("iframe")}HTMLElement.prototype=(window.webkit)?window["[[DOMElement.prototype]]"]:{}}HTMLElement.prototype.htmlElement=function(){};if(window.ie6){try{document.execCommand("BackgroundImageCache",false,true)}catch(e){}}var Class=function(b){var a=function(){return(arguments[0]!==null&&this.initialize&&$type(this.initialize)=="function")?this.initialize.apply(this,arguments):this};$extend(a,this);a.prototype=b;a.constructor=Class;return a};Class.empty=function(){};Class.prototype={extend:function(b){var c=new this(null);for(var d in b){var a=c[d];c[d]=Class.Merge(a,b[d])}return new Class(c)},implement:function(){for(var b=0,a=arguments.length;b<a;b++){$extend(this.prototype,arguments[b])}}};Class.Merge=function(c,d){if(c&&c!=d){var b=$type(d);if(b!=$type(c)){return d}switch(b){case"function":var a=function(){this.parent=arguments.callee.parent;return d.apply(this,arguments)};a.parent=c;return a;case"object":return $merge(c,d)}}return d};var Chain=new Class({chain:function(a){this.chains=this.chains||[];this.chains.push(a);return this},callChain:function(){if(this.chains&&this.chains.length){this.chains.shift().delay(10,this)}},clearChain:function(){this.chains=[]}});var Events=new Class({addEvent:function(b,a){if(a!=Class.empty){this.$events=this.$events||{};this.$events[b]=this.$events[b]||[];this.$events[b].include(a)}return this},fireEvent:function(c,b,a){if(this.$events&&this.$events[c]){this.$events[c].each(function(d){d.create({bind:this,delay:a,"arguments":b})()},this)}return this},removeEvent:function(b,a){if(this.$events&&this.$events[b]){this.$events[b].remove(a)}return this}});var Options=new Class({setOptions:function(){this.options=$merge.apply(null,[this.options].extend(arguments));if(this.addEvent){for(var a in this.options){if($type(this.options[a]=="function")&&(/^on[A-Z]/).test(a)){this.addEvent(a,this.options[a])}}}return this}});Array.extend({forEach:function(c,d){for(var b=0,a=this.length;b<a;b++){c.call(d,this[b],b,this)}},filter:function(d,f){var c=[];for(var b=0,a=this.length;b<a;b++){if(d.call(f,this[b],b,this)){c.push(this[b])}}return c},map:function(d,f){var c=[];for(var b=0,a=this.length;b<a;b++){c[b]=d.call(f,this[b],b,this)}return c},every:function(c,d){for(var b=0,a=this.length;b<a;b++){if(!c.call(d,this[b],b,this)){return false}}return true},some:function(c,d){for(var b=0,a=this.length;b<a;b++){if(c.call(d,this[b],b,this)){return true}}return false},indexOf:function(c,d){var a=this.length;for(var b=(d<0)?Math.max(0,a+d):d||0;b<a;b++){if(this[b]===c){return b}}return -1},copy:function(d,c){d=d||0;if(d<0){d=this.length+d}c=c||(this.length-d);var a=[];for(var b=0;b<c;b++){a[b]=this[d++]}return a},remove:function(c){var b=0;var a=this.length;while(b<a){if(this[b]===c){this.splice(b,1);a--}else{b++}}return this},contains:function(a,b){return this.indexOf(a,b)!=-1},associate:function(c){var d={},b=Math.min(this.length,c.length);for(var a=0;a<b;a++){d[c[a]]=this[a]}return d},extend:function(c){for(var b=0,a=c.length;b<a;b++){this.push(c[b])}return this},merge:function(c){for(var b=0,a=c.length;b<a;b++){this.include(c[b])}return this},include:function(a){if(!this.contains(a)){this.push(a)}return this},getRandom:function(){return this[$random(0,this.length-1)]||null},getLast:function(){return this[this.length-1]||null}});Array.prototype.each=Array.prototype.forEach;Array.each=Array.forEach;function $A(a){return Array.copy(a)}function $each(c,b,d){if(c&&typeof c.length=="number"&&$type(c)!="object"){Array.forEach(c,b,d)}else{for(var a in c){b.call(d||c,c[a],a)}}}Array.prototype.test=Array.prototype.contains;String.extend({test:function(a,b){return(($type(a)=="string")?new RegExp(a,b):a).test(this)},toInt:function(){return parseInt(this,10)},toFloat:function(){return parseFloat(this)},camelCase:function(){return this.replace(/-\D/g,function(a){return a.charAt(1).toUpperCase()})},hyphenate:function(){return this.replace(/\w[A-Z]/g,function(a){return(a.charAt(0)+"-"+a.charAt(1).toLowerCase())})},capitalize:function(){return this.replace(/\b[a-z]/g,function(a){return a.toUpperCase()})},trim:function(){return this.replace(/^\s+|\s+$/g,"")},clean:function(){return this.replace(/\s{2,}/g," ").trim()},rgbToHex:function(b){var a=this.match(/\d{1,3}/g);return(a)?a.rgbToHex(b):false},hexToRgb:function(b){var a=this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);return(a)?a.slice(1).hexToRgb(b):false},contains:function(a,b){return(b)?(b+this+b).indexOf(b+a+b)>-1:this.indexOf(a)>-1},escapeRegExp:function(){return this.replace(/([.*+?^${}()|[\]\/\\])/g,"\\$1")}});Array.extend({rgbToHex:function(d){if(this.length<3){return false}if(this.length==4&&this[3]==0&&!d){return"transparent"}var b=[];for(var a=0;a<3;a++){var c=(this[a]-0).toString(16);b.push((c.length==1)?"0"+c:c)}return d?b:"#"+b.join("")},hexToRgb:function(c){if(this.length!=3){return false}var a=[];for(var b=0;b<3;b++){a.push(parseInt((this[b].length==1)?this[b]+this[b]:this[b],16))}return c?a:"rgb("+a.join(",")+")"}});Function.extend({create:function(a){var b=this;a=$merge({bind:b,event:false,"arguments":null,delay:false,periodical:false,attempt:false},a);if($chk(a.arguments)&&$type(a.arguments)!="array"){a.arguments=[a.arguments]}return function(f){var c;if(a.event){f=f||window.event;c=[(a.event===true)?f:new a.event(f)];if(a.arguments){c.extend(a.arguments)}}else{c=a.arguments||arguments}var g=function(){return b.apply($pick(a.bind,b),c)};if(a.delay){return setTimeout(g,a.delay)}if(a.periodical){return setInterval(g,a.periodical)}if(a.attempt){try{return g()}catch(d){return false}}return g()}},pass:function(a,b){return this.create({"arguments":a,bind:b})},attempt:function(a,b){return this.create({"arguments":a,bind:b,attempt:true})()},bind:function(b,a){return this.create({bind:b,"arguments":a})},bindAsEventListener:function(b,a){return this.create({bind:b,event:true,"arguments":a})},delay:function(b,c,a){return this.create({delay:b,bind:c,"arguments":a})()},periodical:function(a,c,b){return this.create({periodical:a,bind:c,"arguments":b})()}});Number.extend({toInt:function(){return parseInt(this)},toFloat:function(){return parseFloat(this)},limit:function(b,a){return Math.min(a,Math.max(b,this))},round:function(a){a=Math.pow(10,a||0);return Math.round(this*a)/a},times:function(b){for(var a=0;a<this;a++){b(a)}}});var Element=new Class({initialize:function(d,c){if($type(d)=="string"){if(window.ie&&c&&(c.name||c.type)){var a=(c.name)?' name="'+c.name+'"':"";var b=(c.type)?' type="'+c.type+'"':"";delete c.name;delete c.type;d="<"+d+a+b+">"}d=document.createElement(d)}d=$(d);return(!c||!d)?d:d.set(c)}});var Elements=new Class({initialize:function(a){return(a)?$extend(a,this):this}});Elements.extend=function(a){for(var b in a){this.prototype[b]=a[b];this[b]=$native.generic(b)}};function $(b){if(!b){return null}if(b.htmlElement){return Garbage.collect(b)}if([window,document].contains(b)){return b}var a=$type(b);if(a=="string"){b=document.getElementById(b);a=(b)?"element":false}if(a!="element"){return null}if(b.htmlElement){return Garbage.collect(b)}if(["object","embed"].contains(b.tagName.toLowerCase())){return b}$extend(b,Element.prototype);b.htmlElement=function(){};return Garbage.collect(b)}document.getElementsBySelector=document.getElementsByTagName;function $$(){var d=[];for(var c=0,b=arguments.length;c<b;c++){var a=arguments[c];switch($type(a)){case"element":d.push(a);case"boolean":break;case false:break;case"string":a=document.getElementsBySelector(a,true);default:d.extend(a)}}return $$.unique(d)}$$.unique=function(j){var f=[];for(var c=0,a=j.length;c<a;c++){if(j[c].$included){continue}var b=$(j[c]);if(b&&!b.$included){b.$included=true;f.push(b)}}for(var h=0,g=f.length;h<g;h++){f[h].$included=null}return new Elements(f)};Elements.Multi=function(a){return function(){var d=arguments;var b=[];var h=true;for(var f=0,c=this.length,g;f<c;f++){g=this[f][a].apply(this[f],d);if($type(g)!="element"){h=false}b.push(g)}return(h)?$$.unique(b):b}};Element.extend=function(a){for(var b in a){HTMLElement.prototype[b]=a[b];Element.prototype[b]=a[b];Element[b]=$native.generic(b);var c=(Array.prototype[b])?b+"Elements":b;Elements.prototype[c]=Elements.Multi(b)}};Element.extend({set:function(a){for(var c in a){var b=a[c];switch(c){case"styles":this.setStyles(b);break;case"events":if(this.addEvents){this.addEvents(b)}break;case"properties":this.setProperties(b);break;default:this.setProperty(c,b)}}return this},inject:function(c,a){c=$(c);switch(a){case"before":c.parentNode.insertBefore(this,c);break;case"after":var b=c.getNext();if(!b){c.parentNode.appendChild(this)}else{c.parentNode.insertBefore(this,b)}break;case"top":var d=c.firstChild;if(d){c.insertBefore(this,d);break}default:c.appendChild(this)}return this},injectBefore:function(a){return this.inject(a,"before")},injectAfter:function(a){return this.inject(a,"after")},injectInside:function(a){return this.inject(a,"bottom")},injectTop:function(a){return this.inject(a,"top")},adopt:function(){var a=[];$each(arguments,function(b){a=a.concat(b)});$$(a).inject(this);return this},remove:function(){return this.parentNode.removeChild(this)},clone:function(c){var b=$(this.cloneNode(c!==false));if(!b.$events){return b}b.$events={};for(var a in this.$events){b.$events[a]={keys:$A(this.$events[a].keys),values:$A(this.$events[a].values)}}return b.removeEvents()},replaceWith:function(a){a=$(a);this.parentNode.replaceChild(a,this);return a},appendText:function(a){this.appendChild(document.createTextNode(a));return this},hasClass:function(a){return this.className.contains(a," ")},addClass:function(a){if(!this.hasClass(a)){this.className=(this.className+" "+a).clean()}return this},removeClass:function(a){this.className=this.className.replace(new RegExp("(^|\\s)"+a+"(?:\\s|$)"),"$1").clean();return this},toggleClass:function(a){return this.hasClass(a)?this.removeClass(a):this.addClass(a)},setStyle:function(b,a){switch(b){case"opacity":return this.setOpacity(parseFloat(a));case"float":b=(window.ie)?"styleFloat":"cssFloat"}b=b.camelCase();switch($type(a)){case"number":if(!["zIndex","zoom"].contains(b)){a+="px"}break;case"array":a="rgb("+a.join(",")+")"}this.style[b]=a;return this},setStyles:function(a){switch($type(a)){case"object":Element.setMany(this,"setStyle",a);break;case"string":this.style.cssText=a}return this},setOpacity:function(a){if(a==0){if(this.style.visibility!="hidden"){this.style.visibility="hidden"}}else{if(this.style.visibility!="visible"){this.style.visibility="visible"}}if(!this.currentStyle||!this.currentStyle.hasLayout){this.style.zoom=1}if(window.ie){this.style.filter=(a==1)?"":"alpha(opacity="+a*100+")"}this.style.opacity=this.$tmp.opacity=a;return this},getStyle:function(c){c=c.camelCase();var a=this.style[c];if(!$chk(a)){if(c=="opacity"){return this.$tmp.opacity}a=[];for(var b in Element.Styles){if(c==b){Element.Styles[b].each(function(g){var f=this.getStyle(g);a.push(parseInt(f)?f:"0px")},this);if(c=="border"){var d=a.every(function(f){return(f==a[0])});return(d)?a[0]:false}return a.join(" ")}}if(c.contains("border")){if(Element.Styles.border.contains(c)){return["Width","Style","Color"].map(function(f){return this.getStyle(c+f)},this).join(" ")}else{if(Element.borderShort.contains(c)){return["Top","Right","Bottom","Left"].map(function(f){return this.getStyle("border"+f+c.replace("border",""))},this).join(" ")}}}if(document.defaultView){a=document.defaultView.getComputedStyle(this,null).getPropertyValue(c.hyphenate())}else{if(this.currentStyle){a=this.currentStyle[c]}}}if(window.ie){a=Element.fixStyle(c,a,this)}if(a&&c.test(/color/i)&&a.contains("rgb")){return a.split("rgb").splice(1,4).map(function(f){return f.rgbToHex()}).join(" ")}return a},getStyles:function(){return Element.getMany(this,"getStyle",arguments)},walk:function(a,c){a+="Sibling";var b=(c)?this[c]:this[a];while(b&&$type(b)!="element"){b=b[a]}return $(b)},getPrevious:function(){return this.walk("previous")},getNext:function(){return this.walk("next")},getFirst:function(){return this.walk("next","firstChild")},getLast:function(){return this.walk("previous","lastChild")},getParent:function(){return $(this.parentNode)},getChildren:function(){return $$(this.childNodes)},hasChild:function(a){return !!$A(this.getElementsByTagName("*")).contains(a)},getProperty:function(d){var b=Element.Properties[d];if(b){return this[b]}var a=Element.PropertiesIFlag[d]||0;if(!window.ie||a){return this.getAttribute(d,a)}var c=this.attributes[d];return(c)?c.nodeValue:null},removeProperty:function(b){var a=Element.Properties[b];if(a){this[a]=""}else{this.removeAttribute(b)}return this},getProperties:function(){return Element.getMany(this,"getProperty",arguments)},setProperty:function(c,b){var a=Element.Properties[c];if(a){this[a]=b}else{this.setAttribute(c,b)}return this},setProperties:function(a){return Element.setMany(this,"setProperty",a)},setHTML:function(){this.innerHTML=$A(arguments).join("");return this},setText:function(b){var a=this.getTag();if(["style","script"].contains(a)){if(window.ie){if(a=="style"){this.styleSheet.cssText=b}else{if(a=="script"){this.setProperty("text",b)}}return this}else{this.removeChild(this.firstChild);return this.appendText(b)}}this[$defined(this.innerText)?"innerText":"textContent"]=b;return this},getText:function(){var a=this.getTag();if(["style","script"].contains(a)){if(window.ie){if(a=="style"){return this.styleSheet.cssText}else{if(a=="script"){return this.getProperty("text")}}}else{return this.innerHTML}}return($pick(this.innerText,this.textContent))},getTag:function(){return this.tagName.toLowerCase()},empty:function(){Garbage.trash(this.getElementsByTagName("*"));return this.setHTML("")}});Element.fixStyle=function(f,a,d){if($chk(parseInt(a))){return a}if(["height","width"].contains(f)){var b=(f=="width")?["left","right"]:["top","bottom"];var c=0;b.each(function(g){c+=d.getStyle("border-"+g+"-width").toInt()+d.getStyle("padding-"+g).toInt()});return d["offset"+f.capitalize()]-c+"px"}else{if(f.test(/border(.+)Width|margin|padding/)){return"0px"}}return a};Element.Styles={border:[],padding:[],margin:[]};["Top","Right","Bottom","Left"].each(function(b){for(var a in Element.Styles){Element.Styles[a].push(a+b)}});Element.borderShort=["borderWidth","borderStyle","borderColor"];Element.getMany=function(b,d,c){var a={};$each(c,function(f){a[f]=b[d](f)});return a};Element.setMany=function(b,d,c){for(var a in c){b[d](a,c[a])}return b};Element.Properties=new Abstract({"class":"className","for":"htmlFor",colspan:"colSpan",rowspan:"rowSpan",accesskey:"accessKey",tabindex:"tabIndex",maxlength:"maxLength",readonly:"readOnly",frameborder:"frameBorder",value:"value",disabled:"disabled",checked:"checked",multiple:"multiple",selected:"selected"});Element.PropertiesIFlag={href:2,src:2};Element.Methods={Listeners:{addListener:function(b,a){if(this.addEventListener){this.addEventListener(b,a,false)}else{this.attachEvent("on"+b,a)}return this},removeListener:function(b,a){if(this.removeEventListener){this.removeEventListener(b,a,false)}else{this.detachEvent("on"+b,a)}return this}}};window.extend(Element.Methods.Listeners);document.extend(Element.Methods.Listeners);Element.extend(Element.Methods.Listeners);var Garbage={elements:[],collect:function(a){if(!a.$tmp){Garbage.elements.push(a);a.$tmp={opacity:1}}return a},trash:function(f){for(var b=0,a=f.length,c;b<a;b++){if(!(c=f[b])||!c.$tmp){continue}if(c.$events){c.fireEvent("trash").removeEvents()}for(var g in c.$tmp){c.$tmp[g]=null}for(var h in Element.prototype){c[h]=null}Garbage.elements[Garbage.elements.indexOf(c)]=null;c.htmlElement=c.$tmp=c=null}Garbage.elements.remove(null)},empty:function(){Garbage.collect(window);Garbage.collect(document);Garbage.trash(Garbage.elements)}};window.addListener("beforeunload",function(){window.addListener("unload",Garbage.empty);if(window.ie){window.addListener("unload",CollectGarbage)}});var Event=new Class({initialize:function(c){if(c&&c.$extended){return c}this.$extended=true;c=c||window.event;this.event=c;this.type=c.type;this.target=c.target||c.srcElement;if(this.target.nodeType==3){this.target=this.target.parentNode}this.shift=c.shiftKey;this.control=c.ctrlKey;this.alt=c.altKey;this.meta=c.metaKey;if(["DOMMouseScroll","mousewheel"].contains(this.type)){this.wheel=(c.wheelDelta)?c.wheelDelta/120:-(c.detail||0)/3}else{if(this.type.contains("key")){this.code=c.which||c.keyCode;for(var b in Event.keys){if(Event.keys[b]==this.code){this.key=b;break}}if(this.type=="keydown"){var a=this.code-111;if(a>0&&a<13){this.key="f"+a}}this.key=this.key||String.fromCharCode(this.code).toLowerCase()}else{if(this.type.test(/(click|mouse|menu)/)){this.page={x:c.pageX||c.clientX+document.documentElement.scrollLeft,y:c.pageY||c.clientY+document.documentElement.scrollTop};this.client={x:c.pageX?c.pageX-window.pageXOffset:c.clientX,y:c.pageY?c.pageY-window.pageYOffset:c.clientY};this.rightClick=(c.which==3)||(c.button==2);switch(this.type){case"mouseover":this.relatedTarget=c.relatedTarget||c.fromElement;break;case"mouseout":this.relatedTarget=c.relatedTarget||c.toElement}this.fixRelatedTarget()}}}return this},stop:function(){return this.stopPropagation().preventDefault()},stopPropagation:function(){if(this.event.stopPropagation){this.event.stopPropagation()}else{this.event.cancelBubble=true}return this},preventDefault:function(){if(this.event.preventDefault){this.event.preventDefault()}else{this.event.returnValue=false}return this}});Event.fix={relatedTarget:function(){if(this.relatedTarget&&this.relatedTarget.nodeType==3){this.relatedTarget=this.relatedTarget.parentNode}},relatedTargetGecko:function(){try{Event.fix.relatedTarget.call(this)}catch(a){this.relatedTarget=this.target}}};Event.prototype.fixRelatedTarget=(window.gecko)?Event.fix.relatedTargetGecko:Event.fix.relatedTarget;Event.keys=new Abstract({enter:13,up:38,down:40,left:37,right:39,esc:27,space:32,backspace:8,tab:9,"delete":46});Element.Methods.Events={addEvent:function(c,b){this.$events=this.$events||{};this.$events[c]=this.$events[c]||{keys:[],values:[]};if(this.$events[c].keys.contains(b)){return this}this.$events[c].keys.push(b);var a=c;var d=Element.Events[c];if(d){if(d.add){d.add.call(this,b)}if(d.map){b=d.map}if(d.type){a=d.type}}if(!this.addEventListener){b=b.create({bind:this,event:true})}this.$events[c].values.push(b);return(Element.NativeEvents.contains(a))?this.addListener(a,b):this},removeEvent:function(c,b){if(!this.$events||!this.$events[c]){return this}var g=this.$events[c].keys.indexOf(b);if(g==-1){return this}var a=this.$events[c].keys.splice(g,1)[0];var f=this.$events[c].values.splice(g,1)[0];var d=Element.Events[c];if(d){if(d.remove){d.remove.call(this,b)}if(d.type){c=d.type}}return(Element.NativeEvents.contains(c))?this.removeListener(c,f):this},addEvents:function(a){return Element.setMany(this,"addEvent",a)},removeEvents:function(a){if(!this.$events){return this}if(!a){for(var b in this.$events){this.removeEvents(b)}this.$events=null}else{if(this.$events[a]){this.$events[a].keys.each(function(c){this.removeEvent(a,c)},this);this.$events[a]=null}}return this},fireEvent:function(c,b,a){if(this.$events&&this.$events[c]){this.$events[c].keys.each(function(d){d.create({bind:this,delay:a,"arguments":b})()},this)}return this},cloneEvents:function(c,a){if(!c.$events){return this}if(!a){for(var b in c.$events){this.cloneEvents(c,b)}}else{if(c.$events[a]){c.$events[a].keys.each(function(d){this.addEvent(a,d)},this)}}return this}};window.extend(Element.Methods.Events);document.extend(Element.Methods.Events);Element.extend(Element.Methods.Events);Element.Events=new Abstract({mouseenter:{type:"mouseover",map:function(a){a=new Event(a);if(a.relatedTarget!=this&&!this.hasChild(a.relatedTarget)){this.fireEvent("mouseenter",a)}}},mouseleave:{type:"mouseout",map:function(a){a=new Event(a);if(a.relatedTarget!=this&&!this.hasChild(a.relatedTarget)){this.fireEvent("mouseleave",a)}}},mousewheel:{type:(window.gecko)?"DOMMouseScroll":"mousewheel"}});Element.NativeEvents=["click","dblclick","mouseup","mousedown","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","keydown","keypress","keyup","load","unload","beforeunload","resize","move","focus","blur","change","submit","reset","select","error","abort","contextmenu","scroll"];Function.extend({bindWithEvent:function(b,a){return this.create({bind:b,"arguments":a,event:Event})}});Elements.extend({filterByTag:function(a){return new Elements(this.filter(function(b){return(Element.getTag(b)==a)}))},filterByClass:function(a,c){var b=this.filter(function(d){return(d.className&&d.className.contains(a," "))});return(c)?b:new Elements(b)},filterById:function(c,b){var a=this.filter(function(d){return(d.id==c)});return(b)?a:new Elements(a)},filterByAttribute:function(b,a,d,f){var c=this.filter(function(g){var h=Element.getProperty(g,b);if(!h){return false}if(!a){return true}switch(a){case"=":return(h==d);case"*=":return(h.contains(d));case"^=":return(h.substr(0,d.length)==d);case"$=":return(h.substr(h.length-d.length)==d);case"!=":return(h!=d);case"~=":return h.contains(d," ")}return false});return(f)?c:new Elements(c)}});function $E(a,b){return($(b)||document).getElement(a)}function $ES(a,b){return($(b)||document).getElementsBySelector(a)}$$.shared={regexp:/^(\w*|\*)(?:#([\w-]+)|\.([\w-]+))?(?:\[(\w+)(?:([!*^$]?=)["']?([^"'\]]*)["']?)?])?$/,xpath:{getParam:function(b,d,f,c){var a=[d.namespaceURI?"xhtml:":"",f[1]];if(f[2]){a.push('[@id="',f[2],'"]')}if(f[3]){a.push('[contains(concat(" ", @class, " "), " ',f[3],' ")]')}if(f[4]){if(f[5]&&f[6]){switch(f[5]){case"*=":a.push("[contains(@",f[4],', "',f[6],'")]');break;case"^=":a.push("[starts-with(@",f[4],', "',f[6],'")]');break;case"$=":a.push("[substring(@",f[4],", string-length(@",f[4],") - ",f[6].length,' + 1) = "',f[6],'"]');break;case"=":a.push("[@",f[4],'="',f[6],'"]');break;case"!=":a.push("[@",f[4],'!="',f[6],'"]')}}else{a.push("[@",f[4],"]")}}b.push(a.join(""));return b},getItems:function(b,f,h){var g=[];var a=document.evaluate(".//"+b.join("//"),f,$$.shared.resolver,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);for(var d=0,c=a.snapshotLength;d<c;d++){g.push(a.snapshotItem(d))}return(h)?g:new Elements(g.map($))}},normal:{getParam:function(a,c,f,b){if(b==0){if(f[2]){var d=c.getElementById(f[2]);if(!d||((f[1]!="*")&&(Element.getTag(d)!=f[1]))){return false}a=[d]}else{a=$A(c.getElementsByTagName(f[1]))}}else{a=$$.shared.getElementsByTagName(a,f[1]);if(f[2]){a=Elements.filterById(a,f[2],true)}}if(f[3]){a=Elements.filterByClass(a,f[3],true)}if(f[4]){a=Elements.filterByAttribute(a,f[4],f[5],f[6],true)}return a},getItems:function(a,b,c){return(c)?a:$$.unique(a)}},resolver:function(a){return(a=="xhtml")?"http://www.w3.org/1999/xhtml":false},getElementsByTagName:function(d,c){var f=[];for(var b=0,a=d.length;b<a;b++){f.extend(d[b].getElementsByTagName(c))}return f}};$$.shared.method=(window.xpath)?"xpath":"normal";Element.Methods.Dom={getElements:function(a,k){var c=[];a=a.trim().split(" ");for(var f=0,d=a.length;f<d;f++){var g=a[f];var h=g.match($$.shared.regexp);if(!h){break}h[1]=h[1]||"*";var b=$$.shared[$$.shared.method].getParam(c,this,h,f);if(!b){break}c=b}return $$.shared[$$.shared.method].getItems(c,this,k)},getElement:function(a){return $(this.getElements(a,true)[0]||false)},getElementsBySelector:function(a,f){var d=[];a=a.split(",");for(var c=0,b=a.length;c<b;c++){d=d.concat(this.getElements(a[c],true))}return(f)?d:$$.unique(d)}};Element.extend({getElementById:function(c){var b=document.getElementById(c);if(!b){return false}for(var a=b.parentNode;a!=this;a=a.parentNode){if(!a){return false}}return b},getElementsByClassName:function(a){return this.getElements("."+a)}});document.extend(Element.Methods.Dom);Element.extend(Element.Methods.Dom);Element.extend({getValue:function(){switch(this.getTag()){case"select":var a=[];$each(this.options,function(b){if(b.selected){a.push($pick(b.value,b.text))}});return(this.multiple)?a:a[0];case"input":if(!(this.checked&&["checkbox","radio"].contains(this.type))&&!["hidden","text","password"].contains(this.type)){break}case"textarea":return this.value}return false},getFormElements:function(){return $$(this.getElementsByTagName("input"),this.getElementsByTagName("select"),this.getElementsByTagName("textarea"))},toQueryString:function(){var a=[];this.getFormElements().each(function(d){var c=d.name;var f=d.getValue();if(f===false||!c||d.disabled){return}var b=function(g){a.push(c+"="+encodeURIComponent(g))};if($type(f)=="array"){f.each(b)}else{b(f)}});return a.join("&")}});Element.extend({scrollTo:function(a,b){this.scrollLeft=a;this.scrollTop=b},getSize:function(){return{scroll:{x:this.scrollLeft,y:this.scrollTop},size:{x:this.offsetWidth,y:this.offsetHeight},scrollSize:{x:this.scrollWidth,y:this.scrollHeight}}},getPosition:function(a){a=a||[];var b=this,d=0,c=0;do{d+=b.offsetLeft||0;c+=b.offsetTop||0;b=b.offsetParent}while(b);a.each(function(f){d-=f.scrollLeft||0;c-=f.scrollTop||0});return{x:d,y:c}},getTop:function(a){return this.getPosition(a).y},getLeft:function(a){return this.getPosition(a).x},getCoordinates:function(b){var a=this.getPosition(b);var c={width:this.offsetWidth,height:this.offsetHeight,left:a.x,top:a.y};c.right=c.left+c.width;c.bottom=c.top+c.height;return c}});Element.Events.domready={add:function(b){if(window.loaded){b.call(this);return}var a=function(){if(window.loaded){return}window.loaded=true;window.timer=$clear(window.timer);this.fireEvent("domready")}.bind(this);if(document.readyState&&window.webkit){window.timer=function(){if(["loaded","complete"].contains(document.readyState)){a()}}.periodical(50)}else{if(document.readyState&&window.ie){if(!$("ie_ready")){var c=(window.location.protocol=="https:")?"://0":"javascript:void(0)";document.write('<script id="ie_ready" defer src="'+c+'"><\/script>');$("ie_ready").onreadystatechange=function(){if(this.readyState=="complete"){a()}}}}else{window.addListener("load",a);document.addListener("DOMContentLoaded",a)}}}};window.onDomReady=function(a){return this.addEvent("domready",a)};window.extend({getWidth:function(){if(this.webkit419){return this.innerWidth}if(this.opera){return document.body.clientWidth}return document.documentElement.clientWidth},getHeight:function(){if(this.webkit419){return this.innerHeight}if(this.opera){return document.body.clientHeight}return document.documentElement.clientHeight},getScrollWidth:function(){if(this.ie){return Math.max(document.documentElement.offsetWidth,document.documentElement.scrollWidth)}if(this.webkit){return document.body.scrollWidth}return document.documentElement.scrollWidth},getScrollHeight:function(){if(this.ie){return Math.max(document.documentElement.offsetHeight,document.documentElement.scrollHeight)}if(this.webkit){return document.body.scrollHeight}return document.documentElement.scrollHeight},getScrollLeft:function(){return this.pageXOffset||document.documentElement.scrollLeft},getScrollTop:function(){return this.pageYOffset||document.documentElement.scrollTop},getSize:function(){return{size:{x:this.getWidth(),y:this.getHeight()},scrollSize:{x:this.getScrollWidth(),y:this.getScrollHeight()},scroll:{x:this.getScrollLeft(),y:this.getScrollTop()}}},getPosition:function(){return{x:0,y:0}}});var Fx={};Fx.Base=new Class({options:{onStart:Class.empty,onComplete:Class.empty,onCancel:Class.empty,transition:function(a){return -(Math.cos(Math.PI*a)-1)/2},duration:500,unit:"px",wait:true,fps:50},initialize:function(a){this.element=this.element||null;this.setOptions(a);if(this.options.initialize){this.options.initialize.call(this)}},step:function(){var a=$time();if(a<this.time+this.options.duration){this.delta=this.options.transition((a-this.time)/this.options.duration);this.setNow();this.increase()}else{this.stop(true);this.set(this.to);this.fireEvent("onComplete",this.element,10);this.callChain()}},set:function(a){this.now=a;this.increase();return this},setNow:function(){this.now=this.compute(this.from,this.to)},compute:function(b,a){return(a-b)*this.delta+b},start:function(b,a){if(!this.options.wait){this.stop()}else{if(this.timer){return this}}this.from=b;this.to=a;this.change=this.to-this.from;this.time=$time();this.timer=this.step.periodical(Math.round(1000/this.options.fps),this);this.fireEvent("onStart",this.element);return this},stop:function(a){if(!this.timer){return this}this.timer=$clear(this.timer);if(!a){this.fireEvent("onCancel",this.element)}return this},custom:function(b,a){return this.start(b,a)},clearTimer:function(a){return this.stop(a)}});Fx.Base.implement(new Chain,new Events,new Options);Fx.CSS={select:function(b,c){if(b.test(/color/i)){return this.Color}var a=$type(c);if((a=="array")||(a=="string"&&c.contains(" "))){return this.Multi}return this.Single},parse:function(c,d,a){if(!a.push){a=[a]}var g=a[0],f=a[1];if(!$chk(f)){f=g;g=c.getStyle(d)}var b=this.select(d,f);return{from:b.parse(g),to:b.parse(f),css:b}}};Fx.CSS.Single={parse:function(a){return parseFloat(a)},getNow:function(c,b,a){return a.compute(c,b)},getValue:function(c,a,b){if(a=="px"&&b!="opacity"){c=Math.round(c)}return c+a}};Fx.CSS.Multi={parse:function(a){return a.push?a:a.split(" ").map(function(b){return parseFloat(b)})},getNow:function(f,d,c){var a=[];for(var b=0;b<f.length;b++){a[b]=c.compute(f[b],d[b])}return a},getValue:function(c,a,b){if(a=="px"&&b!="opacity"){c=c.map(Math.round)}return c.join(a+" ")+a}};Fx.CSS.Color={parse:function(a){return a.push?a:a.hexToRgb(true)},getNow:function(f,d,c){var a=[];for(var b=0;b<f.length;b++){a[b]=Math.round(c.compute(f[b],d[b]))}return a},getValue:function(a){return"rgb("+a.join(",")+")"}};Fx.Style=Fx.Base.extend({initialize:function(b,c,a){this.element=$(b);this.property=c;this.parent(a)},hide:function(){return this.set(0)},setNow:function(){this.now=this.css.getNow(this.from,this.to,this)},set:function(a){this.css=Fx.CSS.select(this.property,a);return this.parent(this.css.parse(a))},start:function(c,b){if(this.timer&&this.options.wait){return this}var a=Fx.CSS.parse(this.element,this.property,[c,b]);this.css=a.css;return this.parent(a.from,a.to)},increase:function(){this.element.setStyle(this.property,this.css.getValue(this.now,this.options.unit,this.property))}});Element.extend({effect:function(b,a){return new Fx.Style(this,b,a)}});Fx.Styles=Fx.Base.extend({initialize:function(b,a){this.element=$(b);this.parent(a)},setNow:function(){for(var a in this.from){this.now[a]=this.css[a].getNow(this.from[a],this.to[a],this)}},set:function(c){var a={};this.css={};for(var b in c){this.css[b]=Fx.CSS.select(b,c[b]);a[b]=this.css[b].parse(c[b])}return this.parent(a)},start:function(c){if(this.timer&&this.options.wait){return this}this.now={};this.css={};var f={},d={};for(var b in c){var a=Fx.CSS.parse(this.element,b,c[b]);f[b]=a.from;d[b]=a.to;this.css[b]=a.css}return this.parent(f,d)},increase:function(){for(var a in this.now){this.element.setStyle(a,this.css[a].getValue(this.now[a],this.options.unit,a))}}});Element.extend({effects:function(a){return new Fx.Styles(this,a)}});Fx.Elements=Fx.Base.extend({initialize:function(b,a){this.elements=$$(b);this.parent(a)},setNow:function(){for(var c in this.from){var g=this.from[c],f=this.to[c],b=this.css[c],a=this.now[c]={};for(var d in g){a[d]=b[d].getNow(g[d],f[d],this)}}},set:function(h){var b={};this.css={};for(var d in h){var g=h[d],c=this.css[d]={},a=b[d]={};for(var f in g){c[f]=Fx.CSS.select(f,g[f]);a[f]=c[f].parse(g[f])}}return this.parent(b)},start:function(d){if(this.timer&&this.options.wait){return this}this.now={};this.css={};var k={},l={};for(var f in d){var h=d[f],a=k[f]={},j=l[f]={},c=this.css[f]={};for(var b in h){var g=Fx.CSS.parse(this.elements[f],b,h[b]);a[b]=g.from;j[b]=g.to;c[b]=g.css}}return this.parent(k,l)},increase:function(){for(var c in this.now){var a=this.now[c],b=this.css[c];for(var d in a){this.elements[c].setStyle(d,b[d].getValue(a[d],this.options.unit,d))}}}});Fx.Scroll=Fx.Base.extend({options:{overflown:[],offset:{x:0,y:0},wheelStops:true},initialize:function(b,a){this.now=[];this.element=$(b);this.bound={stop:this.stop.bind(this,false)};this.parent(a);if(this.options.wheelStops){this.addEvent("onStart",function(){document.addEvent("mousewheel",this.bound.stop)}.bind(this));this.addEvent("onComplete",function(){document.removeEvent("mousewheel",this.bound.stop)}.bind(this))}},setNow:function(){for(var a=0;a<2;a++){this.now[a]=this.compute(this.from[a],this.to[a])}},scrollTo:function(b,g){if(this.timer&&this.options.wait){return this}var d=this.element.getSize();var c={x:b,y:g};for(var f in d.size){var a=d.scrollSize[f]-d.size[f];if($chk(c[f])){c[f]=($type(c[f])=="number")?c[f].limit(0,a):a}else{c[f]=d.scroll[f]}c[f]+=this.options.offset[f]}return this.start([d.scroll.x,d.scroll.y],[c.x,c.y])},toTop:function(){return this.scrollTo(false,0)},toBottom:function(){return this.scrollTo(false,"full")},toLeft:function(){return this.scrollTo(0,false)},toRight:function(){return this.scrollTo("full",false)},toElement:function(b){var a=this.element.getPosition(this.options.overflown);var c=$(b).getPosition(this.options.overflown);return this.scrollTo(c.x-a.x,c.y-a.y)},increase:function(){this.element.scrollTo(this.now[0],this.now[1])}});Fx.Slide=Fx.Base.extend({options:{mode:"vertical"},initialize:function(b,a){this.element=$(b);this.wrapper=new Element("div",{styles:$extend(this.element.getStyles("margin"),{overflow:"hidden"})}).injectAfter(this.element).adopt(this.element);this.element.setStyle("margin",0);this.setOptions(a);this.now=[];this.parent(this.options);this.open=true;this.addEvent("onComplete",function(){this.open=(this.now[0]===0)});if(window.webkit419){this.addEvent("onComplete",function(){if(this.open){this.element.remove().inject(this.wrapper)}})}},setNow:function(){for(var a=0;a<2;a++){this.now[a]=this.compute(this.from[a],this.to[a])}},vertical:function(){this.margin="margin-top";this.layout="height";this.offset=this.element.offsetHeight},horizontal:function(){this.margin="margin-left";this.layout="width";this.offset=this.element.offsetWidth},slideIn:function(a){this[a||this.options.mode]();return this.start([this.element.getStyle(this.margin).toInt(),this.wrapper.getStyle(this.layout).toInt()],[0,this.offset])},slideOut:function(a){this[a||this.options.mode]();return this.start([this.element.getStyle(this.margin).toInt(),this.wrapper.getStyle(this.layout).toInt()],[-this.offset,0])},hide:function(a){this[a||this.options.mode]();this.open=false;return this.set([-this.offset,0])},show:function(a){this[a||this.options.mode]();this.open=true;return this.set([0,this.offset])},toggle:function(a){if(this.wrapper.offsetHeight==0||this.wrapper.offsetWidth==0){return this.slideIn(a)}return this.slideOut(a)},increase:function(){this.element.setStyle(this.margin,this.now[0]+this.options.unit);this.wrapper.setStyle(this.layout,this.now[1]+this.options.unit)}});Fx.Transition=function(b,a){a=a||[];if($type(a)!="array"){a=[a]}return $extend(b,{easeIn:function(c){return b(c,a)},easeOut:function(c){return 1-b(1-c,a)},easeInOut:function(c){return(c<=0.5)?b(2*c,a)/2:(2-b(2*(1-c),a))/2}})};Fx.Transitions=new Abstract({linear:function(a){return a}});Fx.Transitions.extend=function(a){for(var b in a){Fx.Transitions[b]=new Fx.Transition(a[b]);Fx.Transitions.compat(b)}};Fx.Transitions.compat=function(a){["In","Out","InOut"].each(function(b){Fx.Transitions[a.toLowerCase()+b]=Fx.Transitions[a]["ease"+b]})};Fx.Transitions.extend({Pow:function(b,a){return Math.pow(b,a[0]||6)},Expo:function(a){return Math.pow(2,8*(a-1))},Circ:function(a){return 1-Math.sin(Math.acos(a))},Sine:function(a){return 1-Math.sin((1-a)*Math.PI/2)},Back:function(b,a){a=a[0]||1.618;return Math.pow(b,2)*((a+1)*b-a)},Bounce:function(g){var f;for(var d=0,c=1;1;d+=c,c/=2){if(g>=(7-4*d)/11){f=-Math.pow((11-6*d-11*g)/4,2)+c*c;break}}return f},Elastic:function(b,a){return Math.pow(2,10*--b)*Math.cos(20*b*Math.PI*(a[0]||1)/3)}});["Quad","Cubic","Quart","Quint"].each(function(b,a){Fx.Transitions[b]=new Fx.Transition(function(c){return Math.pow(c,[a+2])});Fx.Transitions.compat(b)});var Drag={};Drag.Base=new Class({options:{handle:false,unit:"px",onStart:Class.empty,onBeforeStart:Class.empty,onComplete:Class.empty,onSnap:Class.empty,onDrag:Class.empty,limit:false,modifiers:{x:"left",y:"top"},grid:false,snap:6},initialize:function(b,a){this.setOptions(a);this.element=$(b);this.handle=$(this.options.handle)||this.element;this.mouse={now:{},pos:{}};this.value={start:{},now:{}};this.bound={start:this.start.bindWithEvent(this),check:this.check.bindWithEvent(this),drag:this.drag.bindWithEvent(this),stop:this.stop.bind(this)};this.attach();if(this.options.initialize){this.options.initialize.call(this)}},attach:function(){this.handle.addEvent("mousedown",this.bound.start);return this},detach:function(){this.handle.removeEvent("mousedown",this.bound.start);return this},start:function(c){this.fireEvent("onBeforeStart",this.element);this.mouse.start=c.page;var a=this.options.limit;this.limit={x:[],y:[]};for(var d in this.options.modifiers){if(!this.options.modifiers[d]){continue}this.value.now[d]=this.element.getStyle(this.options.modifiers[d]).toInt();this.mouse.pos[d]=c.page[d]-this.value.now[d];if(a&&a[d]){for(var b=0;b<2;b++){if($chk(a[d][b])){this.limit[d][b]=($type(a[d][b])=="function")?a[d][b]():a[d][b]}}}}if($type(this.options.grid)=="number"){this.options.grid={x:this.options.grid,y:this.options.grid}}document.addListener("mousemove",this.bound.check);document.addListener("mouseup",this.bound.stop);this.fireEvent("onStart",this.element);c.stop()},check:function(a){var b=Math.round(Math.sqrt(Math.pow(a.page.x-this.mouse.start.x,2)+Math.pow(a.page.y-this.mouse.start.y,2)));if(b>this.options.snap){document.removeListener("mousemove",this.bound.check);document.addListener("mousemove",this.bound.drag);this.drag(a);this.fireEvent("onSnap",this.element)}a.stop()},drag:function(a){this.out=false;this.mouse.now=a.page;for(var b in this.options.modifiers){if(!this.options.modifiers[b]){continue}this.value.now[b]=this.mouse.now[b]-this.mouse.pos[b];if(this.limit[b]){if($chk(this.limit[b][1])&&(this.value.now[b]>this.limit[b][1])){this.value.now[b]=this.limit[b][1];this.out=true}else{if($chk(this.limit[b][0])&&(this.value.now[b]<this.limit[b][0])){this.value.now[b]=this.limit[b][0];this.out=true}}}if(this.options.grid[b]){this.value.now[b]-=(this.value.now[b]%this.options.grid[b])}this.element.setStyle(this.options.modifiers[b],this.value.now[b]+this.options.unit)}this.fireEvent("onDrag",this.element);a.stop()},stop:function(){document.removeListener("mousemove",this.bound.check);document.removeListener("mousemove",this.bound.drag);document.removeListener("mouseup",this.bound.stop);this.fireEvent("onComplete",this.element)}});Drag.Base.implement(new Events,new Options);Element.extend({makeResizable:function(a){return new Drag.Base(this,$merge({modifiers:{x:"width",y:"height"}},a))}});Drag.Move=Drag.Base.extend({options:{droppables:[],container:false,overflown:[]},initialize:function(b,a){this.setOptions(a);this.element=$(b);this.droppables=$$(this.options.droppables);this.container=$(this.options.container);this.position={element:this.element.getStyle("position"),container:false};if(this.container){this.position.container=this.container.getStyle("position")}if(!["relative","absolute","fixed"].contains(this.position.element)){this.position.element="absolute"}var d=this.element.getStyle("top").toInt();var c=this.element.getStyle("left").toInt();if(this.position.element=="absolute"&&!["relative","absolute","fixed"].contains(this.position.container)){d=$chk(d)?d:this.element.getTop(this.options.overflown);c=$chk(c)?c:this.element.getLeft(this.options.overflown)}else{d=$chk(d)?d:0;c=$chk(c)?c:0}this.element.setStyles({top:d,left:c,position:this.position.element});this.parent(this.element)},start:function(c){this.overed=null;if(this.container){var a=this.container.getCoordinates();var b=this.element.getCoordinates();if(this.position.element=="absolute"&&!["relative","absolute","fixed"].contains(this.position.container)){this.options.limit={x:[a.left,a.right-b.width],y:[a.top,a.bottom-b.height]}}else{this.options.limit={y:[0,a.height-b.height],x:[0,a.width-b.width]}}}this.parent(c)},drag:function(a){this.parent(a);var b=this.out?false:this.droppables.filter(this.checkAgainst,this).getLast();if(this.overed!=b){if(this.overed){this.overed.fireEvent("leave",[this.element,this])}this.overed=b?b.fireEvent("over",[this.element,this]):null}return this},checkAgainst:function(b){b=b.getCoordinates(this.options.overflown);var a=this.mouse.now;return(a.x>b.left&&a.x<b.right&&a.y<b.bottom&&a.y>b.top)},stop:function(){if(this.overed&&!this.out){this.overed.fireEvent("drop",[this.element,this])}else{this.element.fireEvent("emptydrop",this)}this.parent();return this}});Element.extend({makeDraggable:function(a){return new Drag.Move(this,a)}});var XHR=new Class({options:{method:"post",async:true,onRequest:Class.empty,onSuccess:Class.empty,onFailure:Class.empty,urlEncoded:true,encoding:"utf-8",autoCancel:false,headers:{}},setTransport:function(){this.transport=(window.XMLHttpRequest)?new XMLHttpRequest():(window.ie?new ActiveXObject("Microsoft.XMLHTTP"):false);return this},initialize:function(a){this.setTransport().setOptions(a);this.options.isSuccess=this.options.isSuccess||this.isSuccess;this.headers={};if(this.options.urlEncoded&&this.options.method=="post"){var b=(this.options.encoding)?"; charset="+this.options.encoding:"";this.setHeader("Content-type","application/x-www-form-urlencoded"+b)}if(this.options.initialize){this.options.initialize.call(this)}},onStateChange:function(){if(this.transport.readyState!=4||!this.running){return}this.running=false;var a=0;try{a=this.transport.status}catch(b){}if(this.options.isSuccess.call(this,a)){this.onSuccess()}else{this.onFailure()}this.transport.onreadystatechange=Class.empty},isSuccess:function(a){return((a>=200)&&(a<300))},onSuccess:function(){this.response={text:this.transport.responseText,xml:this.transport.responseXML};this.fireEvent("onSuccess",[this.response.text,this.response.xml]);this.callChain()},onFailure:function(){this.fireEvent("onFailure",this.transport)},setHeader:function(a,b){this.headers[a]=b;return this},send:function(a,c){if(this.options.autoCancel){this.cancel()}else{if(this.running){return this}}this.running=true;if(c&&this.options.method=="get"){a=a+(a.contains("?")?"&":"?")+c;c=null}this.transport.open(this.options.method.toUpperCase(),a,this.options.async);this.transport.onreadystatechange=this.onStateChange.bind(this);if((this.options.method=="post")&&this.transport.overrideMimeType){this.setHeader("Connection","close")}$extend(this.headers,this.options.headers);for(var b in this.headers){try{this.transport.setRequestHeader(b,this.headers[b])}catch(d){}}this.fireEvent("onRequest");this.transport.send($pick(c,null));return this},cancel:function(){if(!this.running){return this}this.running=false;this.transport.abort();this.transport.onreadystatechange=Class.empty;this.setTransport();this.fireEvent("onCancel");return this}});XHR.implement(new Chain,new Events,new Options);var Ajax=XHR.extend({options:{data:null,update:null,onComplete:Class.empty,evalScripts:false,evalResponse:false},initialize:function(b,a){this.addEvent("onSuccess",this.onComplete);this.setOptions(a);this.options.data=this.options.data||this.options.postBody;if(!["post","get"].contains(this.options.method)){this._method="_method="+this.options.method;this.options.method="post"}this.parent();this.setHeader("X-Requested-With","XMLHttpRequest");this.setHeader("Accept","text/javascript, text/html, application/xml, text/xml, */*");this.url=b},onComplete:function(){if(this.options.update){$(this.options.update).empty().setHTML(this.response.text)}if(this.options.evalScripts||this.options.evalResponse){this.evalScripts()}this.fireEvent("onComplete",[this.response.text,this.response.xml],20)},request:function(a){a=a||this.options.data;switch($type(a)){case"element":a=$(a).toQueryString();break;case"object":a=Object.toQueryString(a)}if(this._method){a=(a)?[this._method,a].join("&"):this._method}return this.send(this.url,a)},evalScripts:function(){var b,a;if(this.options.evalResponse||(/(ecma|java)script/).test(this.getHeader("Content-type"))){a=this.response.text}else{a=[];var c=/<script[^>]*>([\s\S]*?)<\/script>/gi;while((b=c.exec(this.response.text))){a.push(b[1])}a=a.join("\n")}if(a){(window.execScript)?window.execScript(a):window.setTimeout(a,0)}},getHeader:function(a){try{return this.transport.getResponseHeader(a)}catch(b){}return null}});Object.toQueryString=function(b){var c=[];for(var a in b){c.push(encodeURIComponent(a)+"="+encodeURIComponent(b[a]))}return c.join("&")};Element.extend({send:function(a){return new Ajax(this.getProperty("action"),$merge({data:this.toQueryString()},a,{method:"post"})).request()}});var Cookie=new Abstract({options:{domain:false,path:false,duration:false,secure:false},set:function(c,d,b){b=$merge(this.options,b);d=encodeURIComponent(d);if(b.domain){d+="; domain="+b.domain}if(b.path){d+="; path="+b.path}if(b.duration){var a=new Date();a.setTime(a.getTime()+b.duration*24*60*60*1000);d+="; expires="+a.toGMTString()}if(b.secure){d+="; secure"}document.cookie=c+"="+d;return $extend(b,{key:c,value:d})},get:function(a){var b=document.cookie.match("(?:^|;)\\s*"+a.escapeRegExp()+"=([^;]*)");return b?decodeURIComponent(b[1]):false},remove:function(b,a){if($type(b)=="object"){this.set(b.key,"",$merge(b,{duration:-1}))}else{this.set(b,"",$merge(a,{duration:-1}))}}});var Json={toString:function(c){switch($type(c)){case"string":return'"'+c.replace(/(["\\])/g,"\\$1")+'"';case"array":return"["+c.map(Json.toString).join(",")+"]";case"object":var a=[];for(var b in c){a.push(Json.toString(b)+":"+Json.toString(c[b]))}return"{"+a.join(",")+"}";case"number":if(isFinite(c)){break}case false:return"null"}return String(c)},evaluate:function(str,secure){return(($type(str)!="string")||(secure&&!str.test(/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/)))?null:eval("("+str+")")}};Json.Remote=XHR.extend({initialize:function(b,a){this.url=b;this.addEvent("onSuccess",this.onComplete);this.parent(a);this.setHeader("X-Request","JSON")},send:function(a){return this.parent(this.url,"json="+Json.toString(a))},onComplete:function(){this.fireEvent("onComplete",[Json.evaluate(this.response.text,this.options.secure)])}});var Asset=new Abstract({javascript:function(c,b){b=$merge({onload:Class.empty},b);var a=new Element("script",{src:c}).addEvents({load:b.onload,readystatechange:function(){if(this.readyState=="complete"){this.fireEvent("load")}}});delete b.onload;return a.setProperties(b).inject(document.head)},css:function(b,a){return new Element("link",$merge({rel:"stylesheet",media:"screen",type:"text/css",href:b},a)).inject(document.head)},image:function(c,b){b=$merge({onload:Class.empty,onabort:Class.empty,onerror:Class.empty},b);var d=new Image();d.src=c;var a=new Element("img",{src:c});["load","abort","error"].each(function(f){var g=b["on"+f];delete b["on"+f];a.addEvent(f,function(){this.removeEvent(f,arguments.callee);g.call(this)})});if(d.width&&d.height){a.fireEvent("load",a,1)}return a.setProperties(b)},images:function(d,c){c=$merge({onComplete:Class.empty,onProgress:Class.empty},c);if(!d.push){d=[d]}var a=[];var b=0;d.each(function(g){var f=new Asset.image(g,{onload:function(){c.onProgress.call(this,b);b++;if(b==d.length){c.onComplete()}}});a.push(f)});return new Elements(a)}});var Hash=new Class({length:0,initialize:function(a){this.obj=a||{};this.setLength()},get:function(a){return(this.hasKey(a))?this.obj[a]:null},hasKey:function(a){return(a in this.obj)},set:function(a,b){if(!this.hasKey(a)){this.length++}this.obj[a]=b;return this},setLength:function(){this.length=0;for(var a in this.obj){this.length++}return this},remove:function(a){if(this.hasKey(a)){delete this.obj[a];this.length--}return this},each:function(a,b){$each(this.obj,a,b)},extend:function(a){$extend(this.obj,a);return this.setLength()},merge:function(){this.obj=$merge.apply(null,[this.obj].extend(arguments));return this.setLength()},empty:function(){this.obj={};this.length=0;return this},keys:function(){var a=[];for(var b in this.obj){a.push(b)}return a},values:function(){var a=[];for(var b in this.obj){a.push(this.obj[b])}return a}});function $H(a){return new Hash(a)}Hash.Cookie=Hash.extend({initialize:function(b,a){this.name=b;this.options=$extend({autoSave:true},a||{});this.load()},save:function(){if(this.length==0){Cookie.remove(this.name,this.options);return true}var a=Json.toString(this.obj);if(a.length>4096){return false}Cookie.set(this.name,a,this.options);return true},load:function(){this.obj=Json.evaluate(Cookie.get(this.name),true)||{};this.setLength()}});Hash.Cookie.Methods={};["extend","set","merge","empty","remove"].each(function(a){Hash.Cookie.Methods[a]=function(){Hash.prototype[a].apply(this,arguments);if(this.options.autoSave){this.save()}return this}});Hash.Cookie.implement(Hash.Cookie.Methods);var Color=new Class({initialize:function(b,d){d=d||(b.push?"rgb":"hex");var c,a;switch(d){case"rgb":c=b;a=c.rgbToHsb();break;case"hsb":c=b.hsbToRgb();a=b;break;default:c=b.hexToRgb(true);a=c.rgbToHsb()}c.hsb=a;c.hex=c.rgbToHex();return $extend(c,Color.prototype)},mix:function(){var a=$A(arguments);var c=($type(a[a.length-1])=="number")?a.pop():50;var b=this.copy();a.each(function(d){d=new Color(d);for(var f=0;f<3;f++){b[f]=Math.round((b[f]/100*(100-c))+(d[f]/100*c))}});return new Color(b,"rgb")},invert:function(){return new Color(this.map(function(a){return 255-a}))},setHue:function(a){return new Color([a,this.hsb[1],this.hsb[2]],"hsb")},setSaturation:function(a){return new Color([this.hsb[0],a,this.hsb[2]],"hsb")},setBrightness:function(a){return new Color([this.hsb[0],this.hsb[1],a],"hsb")}});function $RGB(d,c,a){return new Color([d,c,a],"rgb")}function $HSB(d,c,a){return new Color([d,c,a],"hsb")}Array.extend({rgbToHsb:function(){var b=this[0],c=this[1],k=this[2];var h,g,i;var j=Math.max(b,c,k),f=Math.min(b,c,k);var l=j-f;i=j/255;g=(j!=0)?l/j:0;if(g==0){h=0}else{var d=(j-b)/l;var a=(j-c)/l;var m=(j-k)/l;if(b==j){h=m-a}else{if(c==j){h=2+d-m}else{h=4+a-d}}h/=6;if(h<0){h++}}return[Math.round(h*360),Math.round(g*100),Math.round(i*100)]},hsbToRgb:function(){var c=Math.round(this[2]/100*255);if(this[1]==0){return[c,c,c]}else{var a=this[0]%360;var g=a%60;var h=Math.round((this[2]*(100-this[1]))/10000*255);var d=Math.round((this[2]*(6000-this[1]*g))/600000*255);var b=Math.round((this[2]*(6000-this[1]*(60-g)))/600000*255);switch(Math.floor(a/60)){case 0:return[c,b,h];case 1:return[d,c,h];case 2:return[h,c,b];case 3:return[h,d,c];case 4:return[b,h,c];case 5:return[c,h,d]}}return false}});var Scroller=new Class({options:{area:20,velocity:1,onChange:function(a,b){this.element.scrollTo(a,b)}},initialize:function(b,a){this.setOptions(a);this.element=$(b);this.mousemover=([window,document].contains(b))?$(document.body):this.element},start:function(){this.coord=this.getCoords.bindWithEvent(this);this.mousemover.addListener("mousemove",this.coord)},stop:function(){this.mousemover.removeListener("mousemove",this.coord);this.timer=$clear(this.timer)},getCoords:function(a){this.page=(this.element==window)?a.client:a.page;if(!this.timer){this.timer=this.scroll.periodical(50,this)}},scroll:function(){var a=this.element.getSize();var d=this.element.getPosition();var c={x:0,y:0};for(var b in this.page){if(this.page[b]<(this.options.area+d[b])&&a.scroll[b]!=0){c[b]=(this.page[b]-this.options.area-d[b])*this.options.velocity}else{if(this.page[b]+this.options.area>(a.size[b]+d[b])&&a.scroll[b]+a.size[b]!=a.scrollSize[b]){c[b]=(this.page[b]-a.size[b]+this.options.area-d[b])*this.options.velocity}}}if(c.y||c.x){this.fireEvent("onChange",[a.scroll.x+c.x,a.scroll.y+c.y])}}});Scroller.implement(new Events,new Options);var Slider=new Class({options:{onChange:Class.empty,onComplete:Class.empty,onTick:function(a){this.knob.setStyle(this.p,a)},mode:"horizontal",steps:100,offset:0},initialize:function(d,a,b){this.element=$(d);this.knob=$(a);this.setOptions(b);this.previousChange=-1;this.previousEnd=-1;this.step=-1;this.element.addEvent("mousedown",this.clickedElement.bindWithEvent(this));var c,g;switch(this.options.mode){case"horizontal":this.z="x";this.p="left";c={x:"left",y:false};g="offsetWidth";break;case"vertical":this.z="y";this.p="top";c={x:false,y:"top"};g="offsetHeight"}this.max=this.element[g]-this.knob[g]+(this.options.offset*2);this.half=this.knob[g]/2;this.getPos=this.element["get"+this.p.capitalize()].bind(this.element);this.knob.setStyle("position","relative").setStyle(this.p,-this.options.offset);var f={};f[this.z]=[-this.options.offset,this.max-this.options.offset];this.drag=new Drag.Base(this.knob,{limit:f,modifiers:c,snap:0,onStart:function(){this.draggedKnob()}.bind(this),onDrag:function(){this.draggedKnob()}.bind(this),onComplete:function(){this.draggedKnob();this.end()}.bind(this)});if(this.options.initialize){this.options.initialize.call(this)}},set:function(a){this.step=a.limit(0,this.options.steps);this.checkStep();this.end();this.fireEvent("onTick",this.toPosition(this.step));return this},clickedElement:function(b){var a=b.page[this.z]-this.getPos()-this.half;a=a.limit(-this.options.offset,this.max-this.options.offset);this.step=this.toStep(a);this.checkStep();this.end();this.fireEvent("onTick",a)},draggedKnob:function(){this.step=this.toStep(this.drag.value.now[this.z]);this.checkStep()},checkStep:function(){if(this.previousChange!=this.step){this.previousChange=this.step;this.fireEvent("onChange",this.step)}},end:function(){if(this.previousEnd!==this.step){this.previousEnd=this.step;this.fireEvent("onComplete",this.step+"")}},toStep:function(a){return Math.round((a+this.options.offset)/this.max*this.options.steps)},toPosition:function(a){return this.max*a/this.options.steps}});Slider.implement(new Events);Slider.implement(new Options);var SmoothScroll=Fx.Scroll.extend({initialize:function(b){this.parent(window,b);this.links=(this.options.links)?$$(this.options.links):$$(document.links);var a=window.location.href.match(/^[^#]*/)[0]+"#";this.links.each(function(d){if(d.href.indexOf(a)!=0){return}var c=d.href.substr(a.length);if(c&&$(c)){this.useLink(d,c)}},this);if(!window.webkit419){this.addEvent("onComplete",function(){window.location.hash=this.anchor})}},useLink:function(b,a){b.addEvent("click",function(c){this.anchor=a;this.toElement(a);c.stop()}.bindWithEvent(this))}});var Sortables=new Class({options:{handles:false,onStart:Class.empty,onComplete:Class.empty,ghost:true,snap:3,onDragStart:function(a,b){b.setStyle("opacity",0.7);a.setStyle("opacity",0.7)},onDragComplete:function(a,b){a.setStyle("opacity",1);b.remove();this.trash.remove()}},initialize:function(d,b){this.setOptions(b);this.list=$(d);this.elements=this.list.getChildren();this.handles=(this.options.handles)?$$(this.options.handles):this.elements;this.bound={start:[],moveGhost:this.moveGhost.bindWithEvent(this)};for(var c=0,a=this.handles.length;c<a;c++){this.bound.start[c]=this.start.bindWithEvent(this,this.elements[c])}this.attach();if(this.options.initialize){this.options.initialize.call(this)}this.bound.move=this.move.bindWithEvent(this);this.bound.end=this.end.bind(this)},attach:function(){this.handles.each(function(b,a){b.addEvent("mousedown",this.bound.start[a])},this)},detach:function(){this.handles.each(function(b,a){b.removeEvent("mousedown",this.bound.start[a])},this)},start:function(c,b){this.active=b;this.coordinates=this.list.getCoordinates();if(this.options.ghost){var a=b.getPosition();this.offset=c.page.y-a.y;this.trash=new Element("div").inject(document.body);this.ghost=b.clone().inject(this.trash).setStyles({position:"absolute",left:a.x,top:c.page.y-this.offset});document.addListener("mousemove",this.bound.moveGhost);this.fireEvent("onDragStart",[b,this.ghost])}document.addListener("mousemove",this.bound.move);document.addListener("mouseup",this.bound.end);this.fireEvent("onStart",b);c.stop()},moveGhost:function(a){var b=a.page.y-this.offset;b=b.limit(this.coordinates.top,this.coordinates.bottom-this.ghost.offsetHeight);this.ghost.setStyle("top",b);a.stop()},move:function(f){var b=f.page.y;this.previous=this.previous||b;var a=((this.previous-b)>0);var d=this.active.getPrevious();var c=this.active.getNext();if(d&&a&&b<d.getCoordinates().bottom){this.active.injectBefore(d)}if(c&&!a&&b>c.getCoordinates().top){this.active.injectAfter(c)}this.previous=b},serialize:function(a){return this.list.getChildren().map(a||function(b){return this.elements.indexOf(b)},this)},end:function(){this.previous=null;document.removeListener("mousemove",this.bound.move);document.removeListener("mouseup",this.bound.end);if(this.options.ghost){document.removeListener("mousemove",this.bound.moveGhost);this.fireEvent("onDragComplete",[this.active,this.ghost])}this.fireEvent("onComplete",this.active)}});Sortables.implement(new Events,new Options);var Tips=new Class({options:{onShow:function(a){a.setStyle("visibility","visible")},onHide:function(a){a.setStyle("visibility","hidden")},maxTitleChars:30,showDelay:100,hideDelay:100,className:"tool",offsets:{x:16,y:16},fixed:false},initialize:function(b,a){this.setOptions(a);this.toolTip=new Element("div",{"class":this.options.className+"-tip",styles:{position:"absolute",top:"0",left:"0",visibility:"hidden"}}).inject(document.body);this.wrapper=new Element("div").inject(this.toolTip);$$(b).each(this.build,this);if(this.options.initialize){this.options.initialize.call(this)}},build:function(b){b.$tmp.myTitle=(b.href&&b.getTag()=="a")?b.href.replace("http://",""):(b.rel||false);if(b.title){var c=b.title.split("::");if(c.length>1){b.$tmp.myTitle=c[0].trim();b.$tmp.myText=c[1].trim()}else{b.$tmp.myText=b.title}b.removeAttribute("title")}else{b.$tmp.myText=false}if(b.$tmp.myTitle&&b.$tmp.myTitle.length>this.options.maxTitleChars){b.$tmp.myTitle=b.$tmp.myTitle.substr(0,this.options.maxTitleChars-1)+"&hellip;"}b.addEvent("mouseenter",function(d){this.start(b);if(!this.options.fixed){this.locate(d)}else{this.position(b)}}.bind(this));if(!this.options.fixed){b.addEvent("mousemove",this.locate.bindWithEvent(this))}var a=this.end.bind(this);b.addEvent("mouseleave",a);b.addEvent("trash",a)},start:function(a){this.wrapper.empty();if(a.$tmp.myTitle){this.title=new Element("span").inject(new Element("div",{"class":this.options.className+"-title"}).inject(this.wrapper)).setHTML(a.$tmp.myTitle)}if(a.$tmp.myText){this.text=new Element("span").inject(new Element("div",{"class":this.options.className+"-text"}).inject(this.wrapper)).setHTML(a.$tmp.myText)}$clear(this.timer);this.timer=this.show.delay(this.options.showDelay,this)},end:function(a){$clear(this.timer);this.timer=this.hide.delay(this.options.hideDelay,this)},position:function(a){var b=a.getPosition();this.toolTip.setStyles({left:b.x+this.options.offsets.x,top:b.y+this.options.offsets.y})},locate:function(b){var d={x:window.getWidth(),y:window.getHeight()};var a={x:window.getScrollLeft(),y:window.getScrollTop()};var c={x:this.toolTip.offsetWidth,y:this.toolTip.offsetHeight};var h={x:"left",y:"top"};for(var f in h){var g=b.page[f]+this.options.offsets[f];if((g+c[f]-a[f])>d[f]){g=b.page[f]-this.options.offsets[f]-c[f]}this.toolTip.setStyle(h[f],g)}},show:function(){if(this.options.timeout){this.timer=this.hide.delay(this.options.timeout,this)}this.fireEvent("onShow",[this.toolTip])},hide:function(){this.fireEvent("onHide",[this.toolTip])}});Tips.implement(new Events,new Options);var Group=new Class({initialize:function(){this.instances=$A(arguments);this.events={};this.checker={}},addEvent:function(b,a){this.checker[b]=this.checker[b]||{};this.events[b]=this.events[b]||[];if(this.events[b].contains(a)){return false}else{this.events[b].push(a)}this.instances.each(function(c,d){c.addEvent(b,this.check.bind(this,[b,c,d]))},this);return this},check:function(c,a,b){this.checker[c][b]=true;var d=this.instances.every(function(g,f){return this.checker[c][f]||false},this);if(!d){return}this.checker[c]={};this.events[c].each(function(f){f.call(this,this.instances,a)},this)}});var Accordion=Fx.Elements.extend({options:{onActive:Class.empty,onBackground:Class.empty,display:0,show:false,height:true,width:false,opacity:true,fixedHeight:false,fixedWidth:false,wait:false,alwaysHide:false},initialize:function(){var c,f,g,b;$each(arguments,function(k,j){switch($type(k)){case"object":c=k;break;case"element":b=$(k);break;default:var h=$$(k);if(!f){f=h}else{g=h}}});this.togglers=f||[];this.elements=g||[];this.container=$(b);this.setOptions(c);this.previous=-1;if(this.options.alwaysHide){this.options.wait=true}if($chk(this.options.show)){this.options.display=false;this.previous=this.options.show}if(this.options.start){this.options.display=false;this.options.show=false}this.effects={};if(this.options.opacity){this.effects.opacity="fullOpacity"}if(this.options.width){this.effects.width=this.options.fixedWidth?"fullWidth":"offsetWidth"}if(this.options.height){this.effects.height=this.options.fixedHeight?"fullHeight":"scrollHeight"}for(var d=0,a=this.togglers.length;d<a;d++){this.addSection(this.togglers[d],this.elements[d])}this.elements.each(function(j,h){if(this.options.show===h){this.fireEvent("onActive",[this.togglers[h],j])}else{for(var k in this.effects){j.setStyle(k,0)}}},this);this.parent(this.elements);if($chk(this.options.display)){this.display(this.options.display)}},addSection:function(f,c,h){f=$(f);c=$(c);var g=this.togglers.contains(f);var b=this.togglers.length;this.togglers.include(f);this.elements.include(c);if(b&&(!g||h)){h=$pick(h,b-1);f.injectBefore(this.togglers[h]);c.injectAfter(f)}else{if(this.container&&!g){f.inject(this.container);c.inject(this.container)}}var a=this.togglers.indexOf(f);f.addEvent("click",this.display.bind(this,a));if(this.options.height){c.setStyles({"padding-top":0,"border-top":"none","padding-bottom":0,"border-bottom":"none"})}if(this.options.width){c.setStyles({"padding-left":0,"border-left":"none","padding-right":0,"border-right":"none"})}c.fullOpacity=1;if(this.options.fixedWidth){c.fullWidth=this.options.fixedWidth}if(this.options.fixedHeight){c.fullHeight=this.options.fixedHeight}c.setStyle("overflow","hidden");if(!g){for(var d in this.effects){c.setStyle(d,0)}}return this},display:function(a){a=($type(a)=="element")?this.elements.indexOf(a):a;if((this.timer&&this.options.wait)||(a===this.previous&&!this.options.alwaysHide)){return this}this.previous=a;var b={};this.elements.each(function(f,d){b[d]={};var c=(d!=a)||(this.options.alwaysHide&&(f.offsetHeight>0));this.fireEvent(c?"onBackground":"onActive",[this.togglers[d],f]);for(var g in this.effects){b[d][g]=c?0:f[this.effects[g]]}},this);return this.start(b)},showThisHideOpen:function(a){return this.display(a)}});Fx.Accordion=Accordion;
/**
* This is a small fix to correct the png transparency problem under IE under version 7
*/
window.addEvent('load', function(e) {
var arVersion = navigator.appVersion.split("MSIE");
var version = parseFloat(arVersion[1]);
if ((version >= 5.5) && (version < 7) && (document.body.filters)) {
for(var i=0; i<document.images.length; i++) {
var img = document.images[i];
var imgName = img.src.toUpperCase();
if ((imgName.substring(imgName.length-3, imgName.length) == "PNG" || imgName.indexOf('FILETYPE=PNG') != -1) && (img.height && img.width)) {
var imgID = (img.id) ? "id='" + img.id + "' " : "";
var imgClass = (img.className) ? "class='" + img.className + "' " : "";
var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' ";
var imgStyle = "display:inline-block;" + img.style.cssText;
if (img.align == "left") imgStyle = "float:left;" + imgStyle;
if (img.align == "right") imgStyle = "float:right;" + imgStyle;
if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle;
var strNewHTML = "<span " + imgID + imgClass + imgTitle
+ " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"
+ "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
+ "(src=\'" + img.src + "\', sizingMethod='scale');\"></span>";
img.outerHTML = strNewHTML;
i = i-1;
}
}
}
});
var PrintingWindow = new Class({
options: {
container: document.getElement('body'),
containerClass : 'Synergee-Web-Page-Component-PrintingWindow',
outputId: 'printingWindowFrame',
width : 750,
height : 370,
button : null
},
initialize: function(options) {
this.setOptions(options);
this.output =  new Element('iframe').injectInside(document.getElement('body'));
this.output.setStyle('display','none');
this.output.setAttribute('id', this.options.outputId);
if(this.options.button)this.options.button.addEvent('click', this.displayPrintWindow.bind(this));
},
displayPrintWindow : function(){
Lightbox.show('{hiddenId|' + this.output.id + '}', '', 'width=' + this.options.width + ', height=' + this.options.height);
if (/msie/i.test(navigator.userAgent)) {
// IE
// seems to be a bug in IE that makes contentWindow raise an error in some cases
try {
var w = this.output.contentWindow;
} catch(ex) {
}
var d = w ? w.document : null;
} else {
try {
var d = this.output.contentDocument;
}
catch (ex) {
}	// in case of cross domain scripting
var w = d ? d.defaultView : null;
}
if (d) {
try {
var tempContainer = new Element('div');
var child = this.options.container.clone();
child.injectInside(tempContainer);
child.getElements('script').each(function(item, index){
item.innerHTML = '';
}.bind(this));
d.open();
d.write('<html><head/><body >'+ tempContainer.innerHTML +'</body></html>');
d.close();
var body = d.getElementsByTagName("body")[0];
body.style.textAlign = 'left';
body.setAttribute('class', this.options.containerClass);
//                    if (this.options.button && this.options.button.id && d.getElementById(this.options.button.id)) {
//                        d.getElementById(this.options.button.id).removeChild(d.getElementById(this.options.button.id).childNodes[0]);
//                    }
var styleSheets = document.getElementsByTagName("LINK");
var head = d.getElementsByTagName("HEAD")[0];
if (!head) {
head = d.createElement("HEAD");
d.getElementsByTagName("HTML")[0].insertBefore(head, d.getElementsByTagName("BODY")[0]);
}
for (var i = 0; i < styleSheets.length; i++) {
if (styleSheets[i].getAttribute("rel") == 'stylesheet') {
var linkElement = d.createElement('LINK');
linkElement.setAttribute('href', styleSheets[i].getAttribute("href"));
linkElement.setAttribute('rel', 'stylesheet');
linkElement.setAttribute('type', 'text/css');
head.appendChild(linkElement);
}
}
w.focus();
w.print();
} catch (ex) {
}
}
}
});
PrintingWindow.implement(new Events);
PrintingWindow.implement(new Options);
var ResultHelper = Events.extend( {
initialize: function (resultsPerPage, countResults) {
this.resultsPerPage = resultsPerPage;
this.countResults = countResults;
if (this.resultsPerPage == 0)
this.resultsPerPage = 1;
this.countPages = Math.ceil(this.countResults / this.resultsPerPage);
this.currentPage = 0;
},
getCountPages : function () {
return this.countPages;
},
getCurrentPage : function () {
return this.currentPage;
},
injectNavBar : function(toInjectNavBarClass, tagName, navClassBaseName, separator) {
var s = "";
for (var i=0; i<this.countPages; i++) {
var className = navClassBaseName + i;
s += "<" + (tagName == 'button' ? tagName + ' type="button"' : tagName) + " class='" + className + "'>" + (i+1) + "</" + tagName + ">";
if (i != this.countPages - 1) {
s += separator;
}
}
$$('.'+toInjectNavBarClass).setHTML(s);
},
nextPage : function () {
if (this.currentPage < this.countPages - 1) {
this.fireEvent('onPageChangeBefore');
this.currentPage++;
this.fireEvent('onPageChangeAfter');
if (this.currentPage == this.countPages - 1) {
this.fireEvent('onPageChangeUpperLimit');
}
}
},
previousPage : function () {
if (this.currentPage > 0) {
this.fireEvent('onPageChangeBefore');
this.currentPage--;
this.fireEvent('onPageChangeAfter');
if (this.currentPage == 0) {
this.fireEvent('onPageChangeLowerLimit');
}
}
},
selectPage : function (page) {
if (page >=0 && page < this.countPages) {
this.fireEvent('onPageChangeBefore');
this.currentPage = page;
this.fireEvent('onPageChangeAfter');
if (this.currentPage == 0) {
this.fireEvent('onPageChangeLowerLimit');
}
if (this.currentPage == this.countPages - 1) {
this.fireEvent('onPageChangeUpperLimit');
}
}
},
firstPage : function () {
this.selectPage(0);
},
lastPage : function () {
this.selectPage(this.countPages - 1);
}
});
/****************************************************************
*                                                              *
*  curvyCorners                                                *
*  ------------                                                *
*                                                              *
*  This script generates rounded corners for your divs.        *
*                                                              *
*  Version 1.2.9                                               *
*  Copyright (c) 2006 Cameron Cooke                            *
*  By: Cameron Cooke and Tim Hutchison.                        *
*                                                              *
*                                                              *
*  Website: http://www.curvycorners.net                        *
*  Email:   info@totalinfinity.com                             *
*  Forum:   http://www.curvycorners.net/forum/                 *
*                                                              *
*                                                              *
*  This library is free software; you can redistribute         *
*  it and/or modify it under the terms of the GNU              *
*  Lesser General Public License as published by the           *
*  Free Software Foundation; either version 2.1 of the         *
*  License, or (at your option) any later version.             *
*                                                              *
*  This library is distributed in the hope that it will        *
*  be useful, but WITHOUT ANY WARRANTY; without even the       *
*  implied warranty of MERCHANTABILITY or FITNESS FOR A        *
*  PARTICULAR PURPOSE. See the GNU Lesser General Public       *
*  License for more details.                                   *
*                                                              *
*  You should have received a copy of the GNU Lesser           *
*  General Public License along with this library;             *
*  Inc., 59 Temple Place, Suite 330, Boston,                   *
*  MA 02111-1307 USA                                           *
*                                                              *
****************************************************************/
var isIE = navigator.userAgent.toLowerCase().indexOf("msie") > -1; var isMoz = document.implementation && document.implementation.createDocument; var isSafari = ((navigator.userAgent.toLowerCase().indexOf('safari')!=-1)&&(navigator.userAgent.toLowerCase().indexOf('mac')!=-1))?true:false; function curvyCorners()
{ if(typeof(arguments[0]) != "object") throw newCurvyError("First parameter of curvyCorners() must be an object."); if(typeof(arguments[1]) != "object" && typeof(arguments[1]) != "string") throw newCurvyError("Second parameter of curvyCorners() must be an object or a class name."); if(typeof(arguments[1]) == "string")
{ var startIndex = 0; var boxCol = getElementsByClass(arguments[1]);}
else
{ var startIndex = 1; var boxCol = arguments;}
var curvyCornersCol = new Array(); if(arguments[0].validTags)
var validElements = arguments[0].validTags; else
var validElements = ["div"]; for(var i = startIndex, j = boxCol.length; i < j; i++)
{ var currentTag = boxCol[i].tagName.toLowerCase(); if(inArray(validElements, currentTag) !== false)
{ curvyCornersCol[curvyCornersCol.length] = new curvyObject(arguments[0], boxCol[i]);}
}
this.objects = curvyCornersCol; this.applyCornersToAll = function()
{ for(var x = 0, k = this.objects.length; x < k; x++)
{ this.objects[x].applyCorners();}
}
}
function curvyObject()
{ this.box = arguments[1]; this.settings = arguments[0]; this.topContainer = null; this.bottomContainer = null; this.masterCorners = new Array(); this.contentDIV = null; var boxHeight = get_style(this.box, "height", "height"); var boxWidth = get_style(this.box, "width", "width"); var borderWidth = get_style(this.box, "borderBottomWidth", "border-bottom-width"); var borderColour = get_style(this.box, "borderBottomColor", "border-bottom-color"); var boxColour = get_style(this.box, "backgroundColor", "background-color"); var backgroundImage = get_style(this.box, "backgroundImage", "background-image"); var boxPosition = get_style(this.box, "position", "position"); var boxPadding = get_style(this.box, "paddingBottom", "padding-bottom"); this.boxHeight = parseInt(((boxHeight != "" && boxHeight != "auto" && boxHeight.indexOf("%") == -1)? boxHeight.substring(0, boxHeight.indexOf("px")) : this.box.scrollHeight)); this.boxWidth = parseInt(((boxWidth != "" && boxWidth != "auto" && boxWidth.indexOf("%") == -1)? boxWidth.substring(0, boxWidth.indexOf("px")) : this.box.scrollWidth)); this.borderWidth = parseInt(((borderWidth != "" && borderWidth.indexOf("px") !== -1)? borderWidth.slice(0, borderWidth.indexOf("px")) : 0)); this.boxColour = format_colour(boxColour); this.boxPadding = parseInt(((boxPadding != "" && boxPadding.indexOf("px") !== -1)? boxPadding.slice(0, boxPadding.indexOf("px")) : 0)); this.borderColour = format_colour(borderColour); this.borderString = this.borderWidth + "px" + " solid " + this.borderColour; this.backgroundImage = ((backgroundImage != "none")? backgroundImage : ""); this.boxContent = this.box.innerHTML; if(boxPosition != "absolute") this.box.style.position = "relative"; this.box.style.padding = "0px"; if(isIE && boxWidth == "auto" && boxHeight == "auto") this.box.style.width = "100%"; if(this.settings.autoPad == true && this.boxPadding > 0)
this.box.innerHTML = ""; this.applyCorners = function()
{ for(var t = 0; t < 2; t++)
{ switch(t)
{ case 0:
if(this.settings.tl || this.settings.tr)
{ var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var topMaxRadius = Math.max(this.settings.tl ? this.settings.tl.radius : 0, this.settings.tr ? this.settings.tr.radius : 0); newMainContainer.style.height = topMaxRadius + "px"; newMainContainer.style.top = 0 - topMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.topContainer = this.box.appendChild(newMainContainer);}
break; case 1:
if(this.settings.bl || this.settings.br)
{ var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var botMaxRadius = Math.max(this.settings.bl ? this.settings.bl.radius : 0, this.settings.br ? this.settings.br.radius : 0); newMainContainer.style.height = botMaxRadius + "px"; newMainContainer.style.bottom = 0 - botMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.bottomContainer = this.box.appendChild(newMainContainer);}
break;}
}
if(this.topContainer) this.box.style.borderTopWidth = "0px"; if(this.bottomContainer) this.box.style.borderBottomWidth = "0px"; var corners = ["tr", "tl", "br", "bl"]; for(var i in corners)
{ if(i > -1 < 4)
{ var cc = corners[i]; if(!this.settings[cc])
{ if(((cc == "tr" || cc == "tl") && this.topContainer != null) || ((cc == "br" || cc == "bl") && this.bottomContainer != null))
{ var newCorner = document.createElement("DIV"); newCorner.style.position = "relative"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; if(this.backgroundImage == "")
newCorner.style.backgroundColor = this.boxColour; else
newCorner.style.backgroundImage = this.backgroundImage; switch(cc)
{ case "tl":
newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.tr.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.left = -this.borderWidth + "px"; break; case "tr":
newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.tl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; newCorner.style.left = this.borderWidth + "px"; break; case "bl":
newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.br.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = -this.borderWidth + "px"; newCorner.style.backgroundPosition = "-" + (this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break; case "br":
newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.bl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = this.borderWidth + "px"
newCorner.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break;}
}
}
else
{ if(this.masterCorners[this.settings[cc].radius])
{ var newCorner = this.masterCorners[this.settings[cc].radius].cloneNode(true);}
else
{ var newCorner = document.createElement("DIV"); newCorner.style.height = this.settings[cc].radius + "px"; newCorner.style.width = this.settings[cc].radius + "px"; newCorner.style.position = "absolute"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; var borderRadius = parseInt(this.settings[cc].radius - this.borderWidth); for(var intx = 0, j = this.settings[cc].radius; intx < j; intx++)
{ if((intx +1) >= borderRadius)
var y1 = -1; else
var y1 = (Math.floor(Math.sqrt(Math.pow(borderRadius, 2) - Math.pow((intx+1), 2))) - 1); if(borderRadius != j)
{ if((intx) >= borderRadius)
var y2 = -1; else
var y2 = Math.ceil(Math.sqrt(Math.pow(borderRadius,2) - Math.pow(intx, 2))); if((intx+1) >= j)
var y3 = -1; else
var y3 = (Math.floor(Math.sqrt(Math.pow(j ,2) - Math.pow((intx+1), 2))) - 1);}
if((intx) >= j)
var y4 = -1; else
var y4 = Math.ceil(Math.sqrt(Math.pow(j ,2) - Math.pow(intx, 2))); if(y1 > -1) this.drawPixel(intx, 0, this.boxColour, 100, (y1+1), newCorner, -1, this.settings[cc].radius); if(borderRadius != j)
{ for(var inty = (y1 + 1); inty < y2; inty++)
{ if(this.settings.antiAlias)
{ if(this.backgroundImage != "")
{ var borderFract = (pixelFraction(intx, inty, borderRadius) * 100); if(borderFract < 30)
{ this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, 0, this.settings[cc].radius);}
else
{ this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, -1, this.settings[cc].radius);}
}
else
{ var pixelcolour = BlendColour(this.boxColour, this.borderColour, pixelFraction(intx, inty, borderRadius)); this.drawPixel(intx, inty, pixelcolour, 100, 1, newCorner, 0, this.settings[cc].radius, cc);}
}
}
if(this.settings.antiAlias)
{ if(y3 >= y2)
{ if (y2 == -1) y2 = 0; this.drawPixel(intx, y2, this.borderColour, 100, (y3 - y2 + 1), newCorner, 0, 0);}
}
else
{ if(y3 >= y1)
{ this.drawPixel(intx, (y1 + 1), this.borderColour, 100, (y3 - y1), newCorner, 0, 0);}
}
var outsideColour = this.borderColour;}
else
{ var outsideColour = this.boxColour; var y3 = y1;}
if(this.settings.antiAlias)
{ for(var inty = (y3 + 1); inty < y4; inty++)
{ this.drawPixel(intx, inty, outsideColour, (pixelFraction(intx, inty , j) * 100), 1, newCorner, ((this.borderWidth > 0)? 0 : -1), this.settings[cc].radius);}
}
}
this.masterCorners[this.settings[cc].radius] = newCorner.cloneNode(true);}
if(cc != "br")
{ for(var t = 0, k = newCorner.childNodes.length; t < k; t++)
{ var pixelBar = newCorner.childNodes[t]; var pixelBarTop = parseInt(pixelBar.style.top.substring(0, pixelBar.style.top.indexOf("px"))); var pixelBarLeft = parseInt(pixelBar.style.left.substring(0, pixelBar.style.left.indexOf("px"))); var pixelBarHeight = parseInt(pixelBar.style.height.substring(0, pixelBar.style.height.indexOf("px"))); if(cc == "tl" || cc == "bl"){ pixelBar.style.left = this.settings[cc].radius -pixelBarLeft -1 + "px";}
if(cc == "tr" || cc == "tl"){ pixelBar.style.top = this.settings[cc].radius -pixelBarHeight -pixelBarTop + "px";}
switch(cc)
{ case "tr":
pixelBar.style.backgroundPosition = "-" + Math.abs((this.boxWidth - this.settings[cc].radius + this.borderWidth) + pixelBarLeft) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "tl":
pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "bl":
pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs((this.boxHeight + this.settings[cc].radius + pixelBarTop) -this.borderWidth) + "px"; break;}
}
}
}
if(newCorner)
{ switch(cc)
{ case "tl":
if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "tr":
if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "bl":
if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break; case "br":
if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break;}
}
}
}
var radiusDiff = new Array(); radiusDiff["t"] = Math.abs(this.settings.tl.radius - this.settings.tr.radius)
radiusDiff["b"] = Math.abs(this.settings.bl.radius - this.settings.br.radius); for(z in radiusDiff)
{ if(z == "t" || z == "b")
{ if(radiusDiff[z])
{ var smallerCornerType = ((this.settings[z + "l"].radius < this.settings[z + "r"].radius)? z +"l" : z +"r"); var newFiller = document.createElement("DIV"); newFiller.style.height = radiusDiff[z] + "px"; newFiller.style.width = this.settings[smallerCornerType].radius+ "px"
newFiller.style.position = "absolute"; newFiller.style.fontSize = "1px"; newFiller.style.overflow = "hidden"; newFiller.style.backgroundColor = this.boxColour; switch(smallerCornerType)
{ case "tl":
newFiller.style.bottom = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.topContainer.appendChild(newFiller); break; case "tr":
newFiller.style.bottom = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.topContainer.appendChild(newFiller); break; case "bl":
newFiller.style.top = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.bottomContainer.appendChild(newFiller); break; case "br":
newFiller.style.top = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.bottomContainer.appendChild(newFiller); break;}
}
var newFillerBar = document.createElement("DIV"); newFillerBar.style.position = "relative"; newFillerBar.style.fontSize = "1px"; newFillerBar.style.overflow = "hidden"; newFillerBar.style.backgroundColor = this.boxColour; newFillerBar.style.backgroundImage = this.backgroundImage; switch(z)
{ case "t":
if(this.topContainer)
{ if(this.settings.tl.radius && this.settings.tr.radius)
{ newFillerBar.style.height = topMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.tl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.tr.radius - this.borderWidth + "px"; newFillerBar.style.borderTop = this.borderString; if(this.backgroundImage != "")
newFillerBar.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; this.topContainer.appendChild(newFillerBar);}
this.box.style.backgroundPosition = "0px -" + (topMaxRadius - this.borderWidth) + "px";}
break; case "b":
if(this.bottomContainer)
{ if(this.settings.bl.radius && this.settings.br.radius)
{ newFillerBar.style.height = botMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.bl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.br.radius - this.borderWidth + "px"; newFillerBar.style.borderBottom = this.borderString; if(this.backgroundImage != "")
newFillerBar.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (topMaxRadius + this.borderWidth)) + "px"; this.bottomContainer.appendChild(newFillerBar);}
}
break;}
}
}
if(this.settings.autoPad == true && this.boxPadding > 0)
{ var contentContainer = document.createElement("DIV"); contentContainer.style.position = "relative"; contentContainer.innerHTML = this.boxContent; contentContainer.className = "autoPadDiv"; var topPadding = Math.abs(topMaxRadius - this.boxPadding); var botPadding = Math.abs(botMaxRadius - this.boxPadding); if(topMaxRadius < this.boxPadding)
contentContainer.style.paddingTop = topPadding + "px"; if(botMaxRadius < this.boxPadding)
contentContainer.style.paddingBottom = botMaxRadius + "px"; contentContainer.style.paddingLeft = this.boxPadding + "px"; contentContainer.style.paddingRight = this.boxPadding + "px"; this.contentDIV = this.box.appendChild(contentContainer);}
}
this.drawPixel = function(intx, inty, colour, transAmount, height, newCorner, image, cornerRadius)
{ var pixel = document.createElement("DIV"); pixel.style.height = height + "px"; pixel.style.width = "1px"; pixel.style.position = "absolute"; pixel.style.fontSize = "1px"; pixel.style.overflow = "hidden"; var topMaxRadius = Math.max(this.settings["tr"].radius, this.settings["tl"].radius); if(image == -1 && this.backgroundImage != "")
{ pixel.style.backgroundImage = this.backgroundImage; pixel.style.backgroundPosition = "-" + (this.boxWidth - (cornerRadius - intx) + this.borderWidth) + "px -" + ((this.boxHeight + topMaxRadius + inty) -this.borderWidth) + "px";}
else
{ pixel.style.backgroundColor = colour;}
if (transAmount != 100)
setOpacity(pixel, transAmount); pixel.style.top = inty + "px"; pixel.style.left = intx + "px"; newCorner.appendChild(pixel);}
}
function insertAfter(parent, node, referenceNode)
{ parent.insertBefore(node, referenceNode.nextSibling);}
function BlendColour(Col1, Col2, Col1Fraction)
{ var red1 = parseInt(Col1.substr(1,2),16); var green1 = parseInt(Col1.substr(3,2),16); var blue1 = parseInt(Col1.substr(5,2),16); var red2 = parseInt(Col2.substr(1,2),16); var green2 = parseInt(Col2.substr(3,2),16); var blue2 = parseInt(Col2.substr(5,2),16); if(Col1Fraction > 1 || Col1Fraction < 0) Col1Fraction = 1; var endRed = Math.round((red1 * Col1Fraction) + (red2 * (1 - Col1Fraction))); if(endRed > 255) endRed = 255; if(endRed < 0) endRed = 0; var endGreen = Math.round((green1 * Col1Fraction) + (green2 * (1 - Col1Fraction))); if(endGreen > 255) endGreen = 255; if(endGreen < 0) endGreen = 0; var endBlue = Math.round((blue1 * Col1Fraction) + (blue2 * (1 - Col1Fraction))); if(endBlue > 255) endBlue = 255; if(endBlue < 0) endBlue = 0; return "#" + IntToHex(endRed)+ IntToHex(endGreen)+ IntToHex(endBlue);}
function IntToHex(strNum)
{ base = strNum / 16; rem = strNum % 16; base = base - (rem / 16); baseS = MakeHex(base); remS = MakeHex(rem); return baseS + '' + remS;}
function MakeHex(x)
{ if((x >= 0) && (x <= 9))
{ return x;}
else
{ switch(x)
{ case 10: return "A"; case 11: return "B"; case 12: return "C"; case 13: return "D"; case 14: return "E"; case 15: return "F";}
}
}
function pixelFraction(x, y, r)
{ var pixelfraction = 0; var xvalues = new Array(1); var yvalues = new Array(1); var point = 0; var whatsides = ""; var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x,2))); if ((intersect >= y) && (intersect < (y+1)))
{ whatsides = "Left"; xvalues[point] = 0; yvalues[point] = intersect - y; point = point + 1;}
var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y+1,2))); if ((intersect >= x) && (intersect < (x+1)))
{ whatsides = whatsides + "Top"; xvalues[point] = intersect - x; yvalues[point] = 1; point = point + 1;}
var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x+1,2))); if ((intersect >= y) && (intersect < (y+1)))
{ whatsides = whatsides + "Right"; xvalues[point] = 1; yvalues[point] = intersect - y; point = point + 1;}
var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y,2))); if ((intersect >= x) && (intersect < (x+1)))
{ whatsides = whatsides + "Bottom"; xvalues[point] = intersect - x; yvalues[point] = 0;}
switch (whatsides)
{ case "LeftRight":
pixelfraction = Math.min(yvalues[0],yvalues[1]) + ((Math.max(yvalues[0],yvalues[1]) - Math.min(yvalues[0],yvalues[1]))/2); break; case "TopRight":
pixelfraction = 1-(((1-xvalues[0])*(1-yvalues[1]))/2); break; case "TopBottom":
pixelfraction = Math.min(xvalues[0],xvalues[1]) + ((Math.max(xvalues[0],xvalues[1]) - Math.min(xvalues[0],xvalues[1]))/2); break; case "LeftBottom":
pixelfraction = (yvalues[0]*xvalues[1])/2; break; default:
pixelfraction = 1;}
return pixelfraction;}
function rgb2Hex(rgbColour)
{ try{ var rgbArray = rgb2Array(rgbColour); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); var hexColour = "#" + IntToHex(red) + IntToHex(green) + IntToHex(blue);}
catch(e){ alert("There was an error converting the RGB value to Hexadecimal in function rgb2Hex");}
return hexColour;}
function rgb2Array(rgbColour)
{ var rgbValues = rgbColour.substring(4, rgbColour.indexOf(")")); var rgbArray = rgbValues.split(", "); return rgbArray;}
function setOpacity(obj, opacity)
{ opacity = (opacity == 100)?99.999:opacity; if(isSafari && obj.tagName != "IFRAME")
{ var rgbArray = rgb2Array(obj.style.backgroundColor); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); obj.style.backgroundColor = "rgba(" + red + ", " + green + ", " + blue + ", " + opacity/100 + ")";}
else if(typeof(obj.style.opacity) != "undefined")
{ obj.style.opacity = opacity/100;}
else if(typeof(obj.style.MozOpacity) != "undefined")
{ obj.style.MozOpacity = opacity/100;}
else if(typeof(obj.style.filter) != "undefined")
{ obj.style.filter = "alpha(opacity:" + opacity + ")";}
else if(typeof(obj.style.KHTMLOpacity) != "undefined")
{ obj.style.KHTMLOpacity = opacity/100;}
}
function inArray(array, value)
{ for(var i = 0; i < array.length; i++){ if (array[i] === value) return i;}
return false;}
function inArrayKey(array, value)
{ for(key in array){ if(key === value) return true;}
return false;}
function addEvent(elm, evType, fn, useCapture) { if (elm.addEventListener) { elm.addEventListener(evType, fn, useCapture); return true;}
else if (elm.attachEvent) { var r = elm.attachEvent('on' + evType, fn); return r;}
else { elm['on' + evType] = fn;}
}
function removeEvent(obj, evType, fn, useCapture){ if (obj.removeEventListener){ obj.removeEventListener(evType, fn, useCapture); return true;} else if (obj.detachEvent){ var r = obj.detachEvent("on"+evType, fn); return r;} else { alert("Handler could not be removed");}
}
function format_colour(colour)
{ var returnColour = "#ffffff"; if(colour != "" && colour != "transparent")
{ if(colour.substr(0, 3) == "rgb")
{ returnColour = rgb2Hex(colour);}
else if(colour.length == 4)
{ returnColour = "#" + colour.substring(1, 2) + colour.substring(1, 2) + colour.substring(2, 3) + colour.substring(2, 3) + colour.substring(3, 4) + colour.substring(3, 4);}
else
{ returnColour = colour;}
}
return returnColour;}
function get_style(obj, property, propertyNS)
{ try
{ if(obj.currentStyle)
{ var returnVal = eval("obj.currentStyle." + property);}
else
{ if(isSafari && obj.style.display == "none")
{ obj.style.display = ""; var wasHidden = true;}
var returnVal = document.defaultView.getComputedStyle(obj, '').getPropertyValue(propertyNS); if(isSafari && wasHidden)
{ obj.style.display = "none";}
}
}
catch(e)
{ }
return returnVal;}
function getElementsByClass(searchClass, node, tag)
{ var classElements = new Array(); if(node == null)
node = document; if(tag == null)
tag = '*'; var els = node.getElementsByTagName(tag); var elsLen = els.length; var pattern = new RegExp("(^|\s)"+searchClass+"(\s|$)"); for (i = 0, j = 0; i < elsLen; i++)
{ if(pattern.test(els[i].className))
{ classElements[j] = els[i]; j++;}
}
return classElements;}
function newCurvyError(errorMessage)
{ return new Error("curvyCorners Error:\n" + errorMessage)
}
/**
* This class is used for the price estimation functionnalities
*
* @event Event heightModified this event is fired when the price estimation is displayed
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param Element input the input div
* @param Element output the output div
**/
var School = Events.extend({
/**
* This is the initialization function
*/
initialize : function(schoolPriceDTO, translationsDTO, schoolContainer, listContainer, parent) {
this._parent = parent;
this._schoolContainer = schoolContainer;
this._listContainer = listContainer;
this._classNameBase = this._parent.getClassNameBase();
this._schoolPriceCalculatorDTO = schoolPriceDTO;
this._translateDTO = translationsDTO;
this.courses = new SchoolCourses(this._schoolPriceCalculatorDTO.schoolFixedDatesCourses, this._schoolPriceCalculatorDTO.schoolVariableDatesCourses, this._schoolPriceCalculatorDTO.schoolOptionalCourses,  this._translateDTO.courses, this._listContainer, this);
this.courses.getHtml().injectInside(this._schoolContainer);
this.accommodations = new SchoolAccommodations(this._schoolPriceCalculatorDTO.schoolAccommodations, this._translateDTO.accommodations, this._listContainer, this);
this.accommodations.getHtml().injectInside(this._schoolContainer);
this.transfers = new SchoolTransfers(this._schoolPriceCalculatorDTO.schoolTransfers, this._translateDTO.transfers, this);
this.transfers.getHtml().injectInside(this._schoolContainer);
this.courses.addEvent('refreshPrice', function() {
this.transfers.refreshTransfers();
this.fireEvent('refreshPrice');
}.bind(this));
this.accommodations.addEvent('refreshAccommodations', function() {
this.transfers.refreshTransfers();
this.fireEvent('refreshPrice');
}.bind(this));
this.accommodations.addEvent('refreshPrice', function() {
this.transfers.refreshTransfers();
this.fireEvent('refreshPrice');
}.bind(this));
this.transfers.addEvent('refreshPrice', function() {
this.fireEvent('refreshPrice');
}.bind(this));
this.addEvent('heightModified', function() {
this.getParent().fireEvent('heightModified');
}.bind(this));
this.addEvent('refreshAccommodations', function() {
this.accommodations.refreshAccommodations('lists');
this.transfers.refreshTransfers();
this.checkMandatoryCourseAccommodations();
});
},
getSchoolContainer : function(){
return this._schoolContainer;
},
/**
*  Return the classNameBase
*/
getClassNameBase : function() {
return this._classNameBase;
},
/**
* Returns an object containing the informations for the calculation price
*
* @return Object The informations needed to calculate the price
*/
getDTO : function() {
var priceEstimationDTO = new Object();
priceEstimationDTO.variableDatesCourses = this.courses.getVariableCoursesDTO();
priceEstimationDTO.fixedDatesCourses = this.courses.getFixedCoursesDTO();
priceEstimationDTO.optionalCourses = this.courses.getOptionalCoursesDTO();
priceEstimationDTO.accommodations = this.accommodations.getDTO();
priceEstimationDTO.transfers = this.transfers.getDTO();
return priceEstimationDTO;
},
/**
* populate the price calculator with the DTO given in parameter
*
* @param DTO toPopulateDTO the DTO to populate from
*/
populateFromDTO : function(toPopulateDTO) {
this.courses.populateCoursesFromDTO(toPopulateDTO.fixedDatesCourses, toPopulateDTO.variableDatesCourses, toPopulateDTO.optionalCourses);
this.accommodations.populateFromDTO(toPopulateDTO.accommodations);
this.transfers.populateFromDTO(toPopulateDTO.transfers);
this.courses.fireEvent("refreshCourses");
},
checkMandatoryCourseAccommodations : function(){
var validCourses = this.courses.getValidAddedCourses();
if(validCourses.length){
var mandatoryAccommodations = this.courses.getMandatoryAccommodations();
if(mandatoryAccommodations.length){
var courseToCheck = new Array();
// find which course have a problem
var accommodations = this.accommodations.getCompletedAccommodations();
for (var i = 0; i < validCourses.length; i++) {
if (validCourses[i].getCourseDetails().type != 'optional' && validCourses[i].getCourseDetails().accommodationMandatory == true) {
var courseDetails = validCourses[i].getCourseDetails();
var isOk = false;
for(var j = 0; j < accommodations.length; j++){
if(accommodations[j].getIsAttachedToCourse() && accommodations[j].getAttachedToCourse().courseId == courseDetails.id){
isOk = true;
}
}
if(!isOk){
courseToCheck.push(validCourses[i]);
}
}
}
if(courseToCheck.length){
if(courseToCheck[0].getCourseDetails().type == "variableDate"){
var durations = courseToCheck[0]._schoolDurationList.getValidListItems();
for(var i = 0; i < durations.length; i++){
if(parseInt(durations[i].getValue()) > courseToCheck[0].getCourseDuration()){
durations[i].getHtml().fireEvent('click');
break;
}
}
if(i == durations.length){
courseToCheck[0]._deleteButton.fireEvent('click');
}
}else{
courseToCheck[0]._deleteButton.fireEvent('click');
}
}
}
}
},
/**
* Return the school accommodations object
*
* @return SchoolAccommodations the school accommodations object
*/
getAccommodations : function() {
return this.accommodations;
},
/**
* Return the school course object
*
* @return SchoolCourses the school courses object
*/
getCourses : function() {
return this.courses;
},
/**
* Returns the accommodation base start date
*
* @return Date The accommodations start date
*/
getAccommodationStartDate : function() {
return this.courses.getAccommodationStartDate();
},
/**
* Returns the end date of the accommodation
*
* @return Date The end date of the accommodation
*/
getAccommodationEndDate : function() {
return this.courses.getAccommodationEndDate();
},
/**
* Return the max accommodation end date for a course
*
* @param integer courseId The Course ID
* @param Date startDate the course start date
* @param SchoolAccommodationObject accommodation The accommodation
*
* @return Date The course accommodation end date
*/
getCourseAccommodationEndDate : function(courseId, startDate, accommodation) {
var course = this.courses.getAddedCourses().filter(function(item) {
return item.getCourseDetails().id == courseId && item.getCourseStartDate().getTime() == startDate.getTime();
});
if (course.length) {
var endDate = (new Date()).fromIso(course[0].getDTO().endDate);
var endDateDay = endDate.getDay();
if (endDateDay == 0) endDateDay = 7;
while (endDateDay != accommodation.getAccommodationOptionDetails().accommodationEndDay) {
endDate.setDate(endDate.getDate() + 1);
endDateDay = endDate.getDay();
if (endDateDay == 0) endDateDay = 7;
}
return endDate;
}
return false;
},
/**
* return true if the course is a fixed one type
*
* @param String coursePosition The position of the course -1 for the last one
*/
getIsFixedDateCourse : function(coursePosition) {
var courses = this.courses.getCompletedCourses();
if (courses.length) {
switch (coursePosition) {
case -1 :
return courses.getLast().getIsFixedCourse();
break;
default :
if (courses[coursePosition]) {
return courses[coursePosition].getIsFixedCourse();
} else {
return null;
}
break;
}
}
},
/**
*  Return the courses end date
*
* @return Date the courses end date
*
*/
getCoursesEndDate : function() {
var completedCourses = this.courses.getCompletedCourses();
if (completedCourses.length) {
var endDate = completedCourses[0].getDTO().endDate;
for (var i = 0; i < completedCourses.length; i++) {
if (completedCourses[i].getDTO().endDate > endDate) {
endDate = completedCourses[0].getDTO().endDate;
}
}
return endDate;
}
return null;
},
/**
* This method returns the number of completed courses
*
* @return Number The number of courses completed
*
*/
getCompletedCourses : function() {
return this.courses.getCompletedCourses();
},
/**
*  Returns the available accommodations
*
* @return Array of integer The Accommodation IDs
*/
getAvailableAccommodations : function() {
return this.courses.getAvailableAccommodations();
},
/**
* This method returns the completed accommodations
*
* @return SchoolAccommodationObject[] The completed accommodations
*
*/
getCompletedAccommodations : function() {
return this.accommodations.getCompletedAccommodations();
},
/**
* This method returns the number of completed transfers
*
* @return Number The number of transfers completed
*
*/
getCompletedTransfers : function() {
return this.transfers.getCompletedTransfers();
},
/**
* Returns the number of participant
*
* @return Number The number of participants
*
*/
getParticipants : function() {
return this.getParent().getParticipants();
},
/**
* Return an array containing the mandatory accommodations with their start and end date
*
* @return Array of MandatoryAccommodationsDTO
*/
getMandatoryAccommodations : function() {
return this.courses.getMandatoryAccommodations();
},
/**
* Return true if the transfer is mandatory
*
* @return boolean true if the transfers are mandatory
*/
getIsTransferMandatory : function() {
return this.courses.getIsTransferMandatory();
},
/**
* Return an array containing the available transfers
*
* @return Array of transfers ID
*/
getAvailableTransfers : function() {
return this.accommodations.getAvailableTransfers();
},
/**
* This method return the list container
*
* @return Element The element containing the lists
*/
getListContainer : function() {
return this.getParent()._listContainer;
},
/**
* This function set the same height for the column
*
* @param Element column1 The first column
* @param Element column2 The second column
*/
setSameColumnSize : function(column1, column2) {
this.getParent().setSameColumnSize(column1, column2);
},
/**
* Returns the  parent
*
* @return Object the parent
*
*/
getParent : function() {
return this._parent;
},
/**
*  This method return the localized dateFormat
*
*  @return String The localized date format
*/
getDateFormat : function() {
return this.getParent().getDateFormat();
},
/**
*  This method return the localized month translations
*
*  @return String[] The localized month translations
*/
getMonthTranslations : function() {
return this._translateDTO.months;
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @event Event deleteAccommodation This event is fired when a course is deleted
*
* @param AccommodationListItemDTO accommodationDetails The object containing the accommodation informations
* @param AccommodationListItemDTO accommodationOptionDetails The object containing the accommodation options informations
* @param Object translateDTO The object containing all the translations for this class
* @param SchoolCourses parent The parent
*
**/
var SchoolAccommodationObject = Events.extend({
/**
* This is the initialization function
*/
initialize : function(accommodationDetails, accommodationOptionDetails, translateDTO, classNamePrefix, oSchoolAccommodationsContainer) {
this._created = false;
this._translateDTO = translateDTO;
this._accommodationDetails = accommodationDetails;
this._accommodationOptionDetails = accommodationOptionDetails;
this._schoolAccommodationsContainer = oSchoolAccommodationsContainer;
this._classNameBase = classNamePrefix;
this._listContainer = this._schoolAccommodationsContainer.getSchool().getListContainer();
this._dateFormat = this._schoolAccommodationsContainer.getSchool().getDateFormat();
this._monthsTranslations = this._schoolAccommodationsContainer.getSchool().getMonthTranslations();
this._validDurations = new Array();
this._additionalNightsBefore = 0;
this._additionalNightsAfter = 0;
this._accommodationStartDate = null;
this._accommodationEndDate = null;
this._accommodationDuration = null;
this._accommodationAttachedToCourse = null;
this._validStartDates = new Array();
this._calculatedStartDate = new Date();
this._calculatedEndDate = new Date();
this._manager = this._schoolAccommodationsContainer.getSchool().getParent();
this._manager.addEvent('descriptionsUpdated', function() {
this.updateDescriptions();
}.bind(this));
},
/**
* Returns an object containing the informations for the calculation price
*
* @return Object The informations needed to calculate the price
*/
getDTO : function() {
var accommodationDTO = new Object();
accommodationDTO.id = this._accommodationOptionDetails.id;
accommodationDTO.startDate = this._accommodationStartDate.toIso();
accommodationDTO.endDate = this._accommodationEndDate.toIso();
accommodationDTO.additionalNightsBefore = this._additionalNightsBefore;
accommodationDTO.additionalNightsAfter = this._additionalNightsAfter;
return accommodationDTO;
},
/**
* Return the accommodation details DTO
*
* @return AccommodationDetailsDTO The Accommodation details
*/
getAccommodationDetails : function() {
return this._accommodationDetails;
},
/**
* Populate the accommodation from the given DTO
*
*
* @param AccommodationDTO toPopulateDTO The DTO to populate from
*/
populateFromDTO : function(toPopulateDTO) {
this._accommodationEndDate = (new Date()).fromIso(toPopulateDTO.endDate);
this._accommodationStartDate = (new Date()).fromIso(toPopulateDTO.startDate);
this._additionalNightsBefore = toPopulateDTO.additionalNightsBefore ? parseInt(toPopulateDTO.additionalNightsBefore) : 0;
this._additionalNightsAfter = toPopulateDTO.additionalNightsAfter ? parseInt(toPopulateDTO.additionalNightsAfter) : 0;
this.updateStartDateLabel();
this._accommodationDuration = Math.round((this._accommodationEndDate - this._accommodationStartDate) / (1000 * 60 * 60 * 24 * 7));
if (this._accommodationDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace('%0', this._accommodationDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._accommodationDuration));
}
this._accommodationEndDate = this.getCalculatedEndDate();
this.updateEndDateLabel();
},
getAvailableDaysBefore : function() {
if(this._accommodationOptionDetails.additionalNightsOnBounds){
var accommodations = this._schoolAccommodationsContainer.getAccommodations();
if(accommodations.length > 1 && accommodations.indexOf(this) != 0){
return 0;
}
}
return this._accommodationOptionDetails.additionalNightsBefore;
},
getAvailableDaysAfter : function() {
if(this._accommodationOptionDetails.additionalNightsOnBounds){
var accommodations = this._schoolAccommodationsContainer.getAccommodations();
if(accommodations.length > 1 && accommodations.getLast() != this){
return 0;
}
}
return this._accommodationOptionDetails.additionalNightsAfter;
},
/**
* set The accommodations start date for the given accommodation
*
* @param Date startDate The Start date
*/
setAttachedAccommodationStartDate : function(startDate) {
this._accommodationStartDate = startDate;
this.updateStartDateLabel();
},
/**
* set The accommodations duration for the given accommodation
*
* @param integer duration The duration
*/
setAttachedAccommodationDuration : function(duration) {
this._accommodationDuration = duration;
if (this._accommodationDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace('%0', this._accommodationDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._accommodationDuration));
}
this._accommodationEndDate = this.getCalculatedEndDate();
this.updateEndDateLabel();
},
/**
* Generate the html structure of the accommodation
*/
createVisualAccommodation : function(attachedAccommodation) {
if(!this._created){
this._container = new Element('div', {'class': this._classNameBase + 'ItemAdded'});
this._title = new Element('div', {'class': this._classNameBase + 'Section-Item-Title'});
this._subTitle = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle'});
this._moreInfo = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle MoreInfos'});
this._moreInfo.setStyle('display','none');
this._startDateContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-StartDate-Container'});
this._endDateContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-EndDate-Container'});
this._startDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._startDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value ' + this._classNameBase + 'Section-Item-ToUpdate'});
this._endDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._endDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value'});
this._durationContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-Duration-Container'});
this._duration = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._durationValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value ' + this._classNameBase + 'Section-Item-ToUpdate'});
this._deleteButton = new Element('div', {'class': this._classNameBase + 'Section-Item-DeleteButton'});
this._duration.injectInside(this._durationContainer);
this._durationValue.injectInside(this._durationContainer);
this._startDate.injectInside(this._startDateContainer);
this._startDateValue.injectInside(this._startDateContainer);
this._endDate.injectInside(this._endDateContainer);
this._endDateValue.injectInside(this._endDateContainer);
this._title.injectInside(this._container);
this._moreInfo.injectInside(this._container);
this._subTitle.injectInside(this._container);
var element = new Element('div').injectInside(this._container);
element.setStyle('clear','both');
this._startDateContainer.injectInside(this._container);
this._endDateContainer.injectInside(this._container);
this._durationContainer.injectInside(this._container);
this._deleteButton.injectInside(this._container);
var element = new Element('div',{'style':'clear:both'}).injectInside(this._container);
element.setStyle('clear','both');
this._title.setHTML(this._accommodationDetails.name);
if(this._accommodationOptionDetails.noAccommodation){
this._subTitle.setStyle('display','none');
}else{
this._subTitle.removeAttribute('style');
}
this._subTitle.setHTML(this._accommodationOptionDetails.name);
this._moreInfo.setHTML(this._translateDTO.moreInfos);
this._startDate.setHTML(this._translateDTO.startDate);
this.updateStartDateLabel();
this._endDate.setHTML(this._translateDTO.endDate);
this.updateEndDateLabel();
this._duration.setHTML(this._translateDTO.duration);
this._durationValue.setHTML(this._translateDTO.durationSelect);
this._deleteButton.setHTML(this._translateDTO.deleteButton);
// add event listener
this._deleteButton.addEvent('click', function(e) {
this.removeAccommodation();
this.fireEvent('deleteAccommodation');
}.bind(this));
this.updateDescriptions();
this._accommodationOptionsList = new SchoolList(this._title, this._classNameBase);
this._accommodationDurationsList = new SchoolList(this._durationValue, this._classNameBase);
this.getVisualAccommodation(this._accommodationOptionsList);
this._accommodationOptionsList.getHtml().injectInside(this._listContainer);
this._accommodationOptionsList.initializeEvents();
this._startDateValue.addEvent('click', function(){
if(!this._startDateValue.hasClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable')){
this._schoolAccommodationsContainer.getCalendar().setValidDates(this.getValidStartDates(), this.getAvailableDaysBefore() , 0, this._accommodationOptionDetails.additionalNightsOnBounds);
if (this._accommodationStartDate) {
this._schoolAccommodationsContainer.getCalendar().setSelectedDate(this._accommodationStartDate, this._additionalNightsBefore, 0);
}
else {
if (this.getValidStartDates().length)
this._schoolAccommodationsContainer.getCalendar().displayMonths(this.getValidStartDates()[0].getMonth(), this.getValidStartDates()[0].getFullYear());
}
this._schoolAccommodationsContainer.getCalendar().show(this._startDateValue);
}
}.bind(this));
this._startDateValue.addEvent('dateselected', function(date){
this._additionalNightsBefore = date.additionalNightsBefore;
if(date.relativeDate < this._accommodationEndDate){
this.refreshAccommodationData(date.relativeDate, null, this._accommodationEndDate);
}else {
this.refreshAccommodationData(date.relativeDate, this._accommodationDuration, null);
}
}.bind(this));
this._endDateValue.addEvent('click', function(){
this._schoolAccommodationsContainer.getCalendar().setValidDates(this.getValidEndDates(),0, this.getAvailableDaysAfter(), this._accommodationOptionDetails.additionalNightsOnBounds);
if(this._accommodationEndDate){
this._schoolAccommodationsContainer.getCalendar().setSelectedDate(this._accommodationEndDate, 0, this._additionalNightsAfter);
}else {
if(this.getValidEndDates().length)
this._schoolAccommodationsContainer.getCalendar().displayMonths(this.getValidEndDates()[0].getMonth(), this.getValidEndDates()[0].getFullYear());
}
this._schoolAccommodationsContainer.getCalendar().show(this._endDateValue);
}.bind(this));
this._endDateValue.addEvent('dateselected', function(date){
this._additionalNightsAfter = date.additionalNightsAfter;
this.refreshAccommodationData(this._accommodationStartDate, null , date.relativeDate);
}.bind(this));
this.refreshValidStartDates();
this.getVisualDurations(this._accommodationDurationsList);
this._accommodationDurationsList.getHtml().injectInside(this._listContainer);
this._accommodationDurationsList.initializeEvents();
this._created = true;
// if it is the first to be added, set the right date
if (this._schoolAccommodationsContainer.getAccommodations().length == 1 && !attachedAccommodation) {
// find the earliest start date
var startDate;
if(this._validStartDates.length){
startDate = this._validStartDates[0];
}
if (startDate) {
this._accommodationStartDate = startDate;
this.refreshVisualDurations(this._accommodationDurationsList);
// find the longest duration
var duration;
for (var i = this._accommodationDurationsList.getListItems().length - 1; i >= 0; i--) {
var listItem = this._accommodationDurationsList.getListItems()[i];
if (listItem.getIsSelectionnable()) {
duration = parseInt(listItem.getValue());
break;
}
}
if (duration) {
this._accommodationStartDate = null;
this.refreshAccommodationData(startDate, duration, null);
}
}
}
}
},
/**
* Update the descriptions
*/
updateDescriptions : function(){
if (this._manager.getDescription && this._manager.getDescription('accommodation', this._accommodationDetails.accommodationType) && this._manager.getDescription('accommodation', this._accommodationDetails.accommodationType) != '') {
this._moreInfo.setAttribute('title', this._accommodationDetails.name + ' :: ' + this._manager.getDescription('accommodation', this._accommodationDetails.accommodationType));
this._moreInfo.setStyle('display','');
if(!this._descriptionToolTip ){
this._descriptionToolTip = new SynergeeTips(this._moreInfo, {'className':'PriceEstimationToolTip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
}else {
this._descriptionToolTip.build(this._moreInfo);
}
}else {
if(this._moreInfo)
this._moreInfo.setStyle('display','none');
}
},
/**
* Returns the html view of this accommodation
*
* @return Element the html view of this accommodation
*/
getHtml : function() {
return this._container;
},
/**
* Generate the list for the possible durations of this accommodation
*
* @param SchoolList The duration list
*/
getVisualDurations : function(list) {
list.clear();
var index = 0;
var durations = this.getDurations();
durations.each(function(item, index) {
list.addItem(item, this._translateDTO.weeks.replace('%0', item));
index = list.getListItems().indexOf(list.getListItems().getLast());
list.getListItems().getLast().getHtml().addEvent('click', function(e) {
if (list.getListItems()[index].getIsSelectionnable())this.refreshAccommodationData(this._accommodationStartDate, item, this._accommodationEndDate);
}.bind(this));
}.bind(this));
this.refreshVisualDurations(list);
},
/**
* Refresh the list for the possible durations of this accommodation
*
* @param SchoolList The duration list
*/
refreshVisualDurations : function(list) {
var firstValid = true;
this._validDurations = this._schoolAccommodationsContainer.getAccommodationValidDuration(this, list);
list.getListItems().each(function(item, index) {
if (this._validDurations.contains(parseInt(item.getValue()))) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (firstValid)list.setSelectedItem(item);
if (this._accommodationDuration == item.getValue()) {
list.setSelectedItem(item);
}
firstValid = false;
} else {
if (item.getValue == 'error')item.setIsValid(false);
item.setIsSelectionnable(false);
}
}.bind(this));
},
/**
* Refresh the list of possible startdates
*
* @param Array list The list of possible startdates
*/
refreshValidStartDates :  function(){
this._validStartDates = this._schoolAccommodationsContainer.getAccommodationValidStartDates(this);
},
/**
* Generate the accommodations list
*
* @param SchoolList list The list we want to refresh
*
*/
getVisualAccommodation : function(list) {
list.clear();
// Get the school accommodations informations to create the list
this._schoolAccommodationsContainer.getSchoolAccommodationsDTO().each(function(SectionItem, index) {
var section = SectionItem;
var sectionId = parseInt(SectionItem.id);
var value = new Object();
value.type = 'category';
value.sectionId = sectionId;
list.addItem(value, SectionItem.name);
list.getListItems().getLast().getHtml().addClass(this._classNameBase + 'List-Item-Category');
// for each accommodation options in the accommodation section
SectionItem.option.each(function(item, index) {
item.parentId = sectionId;
list.addItem(item, item.name);
list.getListItems().getLast().getHtml().addClass(this._classNameBase + 'List-Item-Accommodation');
// add the event on the option button
list.getListItems().getLast().getHtml().addEvent('click', function(e) {
this.setAccommodation(section, item);
}.bind(this));
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.notAvailable);
if (this._schoolAccommodationsContainer.getSchool().getCompletedCourses().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
this.refreshVisualAccommodation(list);
},
/**
* Refresh the accommodations list
*
* @param SchoolList list The list we want to refresh
*
*/
refreshVisualAccommodation : function(list) {
var availableAccommodations = this._schoolAccommodationsContainer.getAvailableAccommodations();
var accommodationStartDates = this.createStartDatesList();
var accommodationEndDate = this._schoolAccommodationsContainer.getAccommodationEndDate();
list.getListItems().each(function(item, index) {
var available =  true;
// check the availability for this accommodation
if(accommodationStartDates[0] && accommodationEndDate && item.getValue().availabilities && item.getValue().availabilities.length){
var availabilities = item.getValue().availabilities;
var startDateVar = new Date(accommodationStartDates[0].getTime() + 86400 * 2 * 1000);
var endDateVar = new Date(accommodationEndDate.getTime() - 86400 *  2 * 1000);
var startWeek = startDateVar.getWeek();
var startYear = startDateVar.getFullYear();
var endWeek = endDateVar.getWeek();
var duration  = this._schoolAccommodationsContainer.getDurationInWeeks(accommodationEndDate, accommodationStartDates[0]);
available = false;
if (startWeek == endWeek) {
if (availabilities[startYear + '' + startWeek] == undefined) {
available = true;
}
} else {
var i = 0;
while (duration > 0 && startWeek != endWeek && !available) {
if (availabilities[startYear + '' + startWeek] == undefined) {
available = true;
}
if (startWeek == 52) {
startWeek = 1;
startYear++;
} else {
startWeek++;
}
duration--;
}
}
}
if (availableAccommodations.contains(item.getValue().parentId) && this._schoolAccommodationsContainer.getDurationInWeeks(accommodationEndDate, accommodationStartDates[0]) >= item.getValue().minimumDurationInWeeks
&& this._schoolAccommodationsContainer.getSchool().getParticipants() >= item.getValue().minimumNumberOfPeople) {
item.setIsValid(true);
item.setIsSelectionnable(available);
} else {
if (!availableAccommodations.contains(item.getValue().sectionId) || item.getValue().type != 'category' || this._schoolAccommodationsContainer.getSchool().getCompletedCourses().length == 0) {
item.setIsValid(false);
} else {
item.setIsValid(true);
}
}
}.bind(this));
if (this._schoolAccommodationsContainer.getSchool().getCompletedCourses().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Replace an accommodation with another one
*
* @param Object accommodation The new accommodation DTO
* @param Object accommodationOption The new accommodation options DTO
*/
setAccommodation : function(accommodationSection, accommodationOption) {
// set the new accommodation informations
this._accommodationDetails = accommodationSection;
this._accommodationOptionDetails = accommodationOption;
if(this._additionalNightsBefore >  this._accommodationOptionDetails.additionalNightsBefore){
this._additionalNightsBefore = this._accommodationOptionDetails.additionalNightsBefore;
}
if(this._additionalNightsAfter >  this._accommodationOptionDetails._additionalNightsAfter){
this._additionalNightsAfter = this._accommodationOptionDetails._additionalNightsAfter;
}
// set the new title and subtitle
this._title.setHTML(this._accommodationDetails.name);
this._subTitle.setHTML(this._accommodationOptionDetails.name);
if(this._accommodationOptionDetails.noAccommodation){
this._subTitle.setStyle('display','none');
}else{
this._subTitle.removeAttribute('style');
}
this._title.removeEvents('click');
this._durationValue.removeEvents('click');
this._accommodationOptionsList.deleteList();
this._accommodationDurationsList.deleteList();
this.updateDescriptions();
this.updateStartDateLabel();
this._title.removeEvents();
this._durationValue.removeEvents();
this._accommodationOptionsList = new SchoolList(this._title, this._classNameBase);
this._accommodationDurationsList = new SchoolList(this._durationValue, this._classNameBase);
this.getVisualAccommodation(this._accommodationOptionsList);
this._accommodationOptionsList.getHtml().injectInside(this._listContainer);
this._accommodationOptionsList.initializeEvents();
this.refreshValidStartDates();
if(!this._accommodationOptionDetails.additionalNightsOnBounds && this._accommodationStartDate.getTime() != this._validStartDates[0].getTime()){
this._additionalNightsBefore = 0;
}
this.getVisualDurations(this._accommodationDurationsList);
this._accommodationDurationsList.getHtml().injectInside(this._listContainer);
this._accommodationDurationsList.initializeEvents();
if(!this._accommodationOptionDetails.additionalNightsOnBounds && this._accommodationDuration != this._validDurations.getLast()){
this._additionalNightsAfter = 0;
}
this.refreshAccommodationLists();
this.updateStartDateLabel();
this.updateEndDateLabel();
// we ask the parent to check if the other accommodations are ok
this._schoolAccommodationsContainer.checkAccommodations(this);
// and the fireAnEvent to the parent to refresh the accommodations
this._schoolAccommodationsContainer.fireEvent('refreshAccommodations');
},
/**
* Refresh the accommodation data and the visual of the accommodation
*
* @param Date startDate The new StartDate
* @param Number duration The new Duration
* @param Date endDate The new endDate
*
*/
refreshAccommodationData : function(startDate, duration, endDate) {
if(startDate && endDate && !duration){
this._accommodationStartDate = startDate;
this._accommodationEndDate = endDate;
this._accommodationDuration = this._schoolAccommodationsContainer.getDurationInWeeks( endDate , startDate);
} else {
// if the endDate is modified and the startDate has to be calculated
if (startDate == this._accommodationStartDate && endDate != this._accommodationEndDate) {
this._accommodationDuration = duration;
this._accommodationEndDate = endDate;
// calculation of the new startDate
var startDateIndex = 0;
var startDates = this.getStartDates();
startDates.filter(function(item, index) {
if (item.toString() == this._accommodationEndDate.toString()) {
startDateIndex = index;
return index;
}
}.bind(this));
startDateIndex = startDateIndex - this._accommodationDuration;
if (startDateIndex < 0) startDateIndex = 0;
this._accommodationStartDate = startDates[startDateIndex];
} else {
// If the startDate and the duration are modified, the endDate has to be calculated
if (startDate != this._accommodationStartDate && duration != this._accommodationDuration) {
this._accommodationStartDate = startDate;
this._accommodationDuration = duration;
this._accommodationEndDate = this.getCalculatedEndDate();
// else if there is only the startDate modified
} else {
if (startDate != this._accommodationStartDate) {
this._accommodationStartDate = startDate;
// if it is a new accommodation with no data, these are set based on the previous accommodation
if (this._accommodationDuration == null) {
var startDate = new Date(this._accommodationStartDate).setDate(this._accommodationStartDate.getDate() + this._accommodationOptionDetails.minimumDurationInWeeks * 7);
// if the accommodationstart + minimum weeks date is before the previous end date
if (startDate < this._schoolAccommodationsContainer.getPreviousEndDate(this)) {
this._accommodationEndDate = this._schoolAccommodationsContainer.getPreviousEndDate(this);
} else {
this._accommodationEndDate = this.getEndDate();
}
// the duration is calculated
this._accommodationDuration = this._schoolAccommodationsContainer.getDurationInWeeks(this._accommodationEndDate, this._accommodationStartDate);
} else {
// else (the course is already complete) the end date is calculated normally
this._accommodationEndDate = this.getCalculatedEndDate();
}
} else {
// or only the duration
if (duration != this._accommodationDuration) {
this._accommodationDuration = duration;
this._accommodationEndDate = this.getCalculatedEndDate();
}
}
}
}
}
if(this._accommodationStartDate){
this.updateStartDateLabel();
}
if (this._accommodationDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace('%0', this._accommodationDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._accommodationDuration));
}
if(this._accommodationEndDate){
this.updateEndDateLabel();
}
// the parent is asked to check if the other accommodations are ok
this._schoolAccommodationsContainer.checkAccommodations(this);
if(this._startDate)  this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
if(this._duration)  this._durationValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
// and the fireAnEvent to the parent to refresh the accommodations
if(this._created)this._schoolAccommodationsContainer.fireEvent('refreshAccommodations');
},
/**
* Update the start date label
*/
updateStartDateLabel : function () {
if (this._additionalNightsBefore && !this.getAvailableDaysBefore()) {
this._additionalNightsBefore = 0;
}
if (this._accommodationStartDate) {
this._calculatedStartDate.setYear(this._accommodationStartDate.getFullYear());
this._calculatedStartDate.setMonth(this._accommodationStartDate.getMonth());
this._calculatedStartDate.setDate(this._accommodationStartDate.getDate());
this._calculatedStartDate.setDate(this._calculatedStartDate.getDate() - this._additionalNightsBefore);
this._startDateValue.setHTML(this._calculatedStartDate.format(this._dateFormat, this._monthsTranslations));
} else {
this._startDateValue.setHTML(this._translateDTO.dateSelect);
}
},
/**
* Update the end date label
*/
updateEndDateLabel : function () {
if (this._additionalNightsAfter && !this.getAvailableDaysAfter()) {
this._additionalNightsAfter = 0;
}
if (this._accommodationEndDate) {
this._calculatedEndDate.setYear(this._accommodationEndDate.getFullYear());
this._calculatedEndDate.setMonth(this._accommodationEndDate.getMonth());
this._calculatedEndDate.setDate(this._accommodationEndDate.getDate());
this._calculatedEndDate.setDate(this._accommodationEndDate.getDate() + this._additionalNightsAfter);
this._endDateValue.setHTML(this._calculatedEndDate.format(this._dateFormat, this._monthsTranslations));
}   else {
this._endDateValue.setHTML(this._translateDTO.endDateValue);
}
},
/**
* Refresh the lists for this accommodation
*/
refreshAccommodationLists : function() {
this.refreshVisualAccommodation(this._accommodationOptionsList);
this.refreshValidStartDates();
this.refreshVisualDurations(this._accommodationDurationsList);
if (this.getValidStartDates().length) {
// check if the buttons must be activated or not
if (this.getValidStartDates().length == 1 && this.getIsAttachedToCourse()) {
this._startDateValue.addClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-Info-Value');
if (this._accommodationStartDate != this.getValidStartDates()[0]){
this.refreshAccommodationData(this.getValidStartDates()[0], null, this._accommodationEndDate);
}
} else {
this._startDateValue.addClass(this._classNameBase + 'Section-Item-Info-Value');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
}
if (this._accommodationDurationsList.getValidListItems().length == 1) {
this._durationValue.addClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._durationValue.removeClass(this._classNameBase + 'Section-Item-Info-Value');
this._accommodationDurationsList.removeButtonEvent();
if (parseInt(this._accommodationDuration) != parseInt(this._accommodationDurationsList.getValidListItems()[0].getValue()))this._accommodationDurationsList.getValidListItems()[0].getHtml().fireEvent('click');
} else {
this._durationValue.addClass(this._classNameBase + 'Section-Item-Info-Value');
this._durationValue.removeClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._accommodationDurationsList.addButtonEvent();
}
}else {
// there is no valid start date
this.removeAccommodation();
this.fireEvent('deleteAccommodation');
}
},
/**
* Delete and generate the lists for this accommodation
*
*/
reGenerateAccommodationLists : function() {
if (this._accommodationDurationsList._listItems.length) {
this._accommodationDurationsList.getHtml().remove();
this._accommodationDurationsList.clear();
}
if (this._accommodationOptionsList._listItems.length) {
this._accommodationOptionsList.getHtml().remove();
this._accommodationOptionsList.clear();
}
this.getVisualAccommodation(this._accommodationOptionsList);
this._accommodationOptionsList.getHtml().injectInside(this._listContainer);
this._accommodationOptionsList.initializeEvents();
this.refreshValidStartDates();
this.getVisualDurations(this._accommodationDurationsList);
this._accommodationDurationsList.getHtml().injectInside(this._listContainer);
if (!this.getIsAttachedToCourse()) {
this._accommodationDurationsList.initializeEvents();
}
},
/**
* Returns an array of startDates
*
* @return Array An array of Dates
*/
getStartDates : function() {
var startDates = this.createStartDatesList();
return startDates;
},
/**
* Generate the start dates list
*/
createStartDatesList : function() {
var startDatesList = new Array();
var startDate = this._schoolAccommodationsContainer.getSchool().getAccommodationStartDate();
var endDate = this._schoolAccommodationsContainer.getSchool().getAccommodationEndDate();
if(!startDate) return startDatesList;
// if the first course is not a fixed one
if (!this._schoolAccommodationsContainer.getSchool().getIsFixedDateCourse(0)) {
var day = startDate.getDay();
if (day == 0)day = 7;
if (this.getAccommodationOptionDetails().accommodationStartDay > 0) {
while (this.getAccommodationOptionDetails().accommodationStartDay != day) {
startDate.setDate(startDate.getDate() - 1);
day = startDate.getDay();
if (day == 0)day = 7;
}
}
}
// if the last course is not a fixed one
if (!this._schoolAccommodationsContainer.getSchool().getIsFixedDateCourse(-1)) {
var endDateDay = endDate.getDay();
if (endDateDay == 0) endDateDay = 7;
if (this.getAccommodationOptionDetails().accommodationEndDay > 0) {
while (endDateDay != this.getAccommodationOptionDetails().accommodationEndDay) {
endDate.setDate(endDate.getDate() + 1);
endDateDay = endDate.getDay();
if (endDateDay == 0) endDateDay = 7;
}
}
endDate.setDate(endDate.getDate() - 7* this.getAccommodationOptionDetails().minimumDurationInWeeks + 3);
}
while (startDate < endDate) {
startDatesList.push(new Date(startDate));
startDate.setDate(startDate.getDate() + 7);
}
return startDatesList;
},
/**
* Returns the endDate
*
* @return Date The end date
*/
getEndDate : function() {
var endDate = this._schoolAccommodationsContainer.getAccommodationEndDate(this);
var endDay = parseInt(this.getAccommodationOptionDetails().accommodationEndDay);
if(endDay == 7)endDay = 0;
while(endDay != endDate.getDay()){
endDate.setDate(endDate.getDate() + 1);
}
return endDate;
},
/**
* Returns the possible durations
*
* @return Array An array of possible durations
*/
getDurations : function() {
var durations = new Array();
var minDuration = parseInt(this.getAccommodationOptionDetails().minimumDurationInWeeks);
var maxDuration = this._schoolAccommodationsContainer.getDurationInWeeks(this.getEndDate(), this.getValidStartDates()[0]);
for (var i = minDuration; i <= maxDuration; i++) {
durations.push(i);
}
return durations;
},
/**
* Return the endDate for an accommodation with its startDate and duration
*
* @return Date The accommodation end date.
*/
getCalculatedEndDate : function() {
var endDate = new Date(this._accommodationStartDate);
endDate.setDate(endDate.getDate() - 3 + this._accommodationDuration * 7);
var endDay = parseInt(this.getAccommodationOptionDetails().accommodationEndDay);
if(endDay == 7)endDay = 0;
while(endDay != endDate.getDay()){
endDate.setDate(endDate.getDate() + 1);
}
if (endDate > this.getEndDate()) {
endDate = this.getEndDate();
this._accommodationEndDate = endDate;
this._accommodationDuration = this._schoolAccommodationsContainer.getDurationInWeeks(this._accommodationEndDate, this._accommodationStartDate);
if (this._accommodationDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace('%0', this._accommodationDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._accommodationDuration));
}
}
if(this._additionalNightsAfter && !this.getAvailableDaysAfter()){
this._additionalNightsAfter = 0;
}
return endDate;
},
/**
* Returns true if all the accommodation informations are complete
*
* @return Boolean Return true if all the accommodation informations are completed
*/
isComplete : function() {
if (this._accommodationDuration && this._accommodationStartDate && this._accommodationEndDate) {
return true;
} else {
return false;
}
},
/**
* Returns the accommodation Start date
*
* @return Date The accommodation start date
*/
getAccommodationStartDate : function() {
return this._accommodationStartDate;
},
/**
* Returns the accommodation end date
*
* @return Date The accommodation end date
*/
getAccommodationEndDate : function() {
return this._accommodationEndDate;
},
/**
* Returns the accommodation duration
*
* @return Number The accommodation duration
*/
getAccommodationDuration : function() {
return this._accommodationDuration;
},
/**
* Returns an object containing the accommodation option details
*
* @return object The accommodation option details
*/
getAccommodationOptionDetails : function() {
return this._accommodationOptionDetails;
},
/**
* set the accommodations attached to a course
*
* @param isAttached CourseDetailDTO The course to attach to
*/
setIsAttachedToCourse : function(isAttached) {
this._accommodationAttached = isAttached;
if (this._accommodationAttached) {
this._deleteButton.setStyle('display', 'none');
//            if (this._accommodationStartDatesList.getButtonEventInitialized()) {
//                this._accommodationStartDatesList.removeButtonEvent();
//            }
if (this._accommodationDurationsList.getButtonEventInitialized()) {
this._accommodationDurationsList.removeButtonEvent();
}
this._startDateValue.setAttribute('class', this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._durationValue.setAttribute('class', this._classNameBase + 'Section-Item-Info-ValueNotEditable');
} else {
this._deleteButton.setStyle('display', 'block');
//            if (!this._accommodationStartDatesList.getButtonEventInitialized()) {
//                this._accommodationStartDatesList.addButtonEvent();
//            }
if (!this._accommodationDurationsList.getButtonEventInitialized()) {
this._accommodationDurationsList.addButtonEvent();
}
this._startDateValue.setAttribute('class', this._classNameBase + 'Section-Item-Info-Value');
this._durationValue.setAttribute('class', this._classNameBase + 'Section-Item-Info-Value');
}
},
/**
* set the accommodations attached to a course
*
* @param course CourseDetailDTO The course to attach to
*/
setAttachedToCourse : function(course) {
this._accommodationAttachedToCourse = course;
},
/**
* set the accommodations attached to a course
*
* @return CourseDetailDTO The course details attached to this accommodation
*/
getAttachedToCourse : function() {
return this._accommodationAttachedToCourse;
},
/**
* set the accommodations attached to a course
*
* @return CourseDetailDTO The course details attached to this accommodation
*/
getIsAttachedToCourse : function() {
return this._accommodationAttached;
},
/**
* return the valid start dates for this accommodation
*
* @return Array of valid start dates
*/
getValidStartDates : function() {
return this._validStartDates;
},
/**
* return the valid start dates for this accommodation
*
* @return Array of valid start dates
*/
getValidEndDates : function() {
var validEndDates = new Array();
var endDate = new Date(this._accommodationStartDate);
endDate.setDate(endDate.getDate() - 3 + this._validDurations[0] * 7);
var endDay = parseInt(this.getAccommodationOptionDetails().accommodationEndDay);
if(endDay == 7)endDay = 0;
while(endDay != endDate.getDay()){
endDate.setDate(endDate.getDate() + 1);
}
validEndDates.push(endDate);
var endDateTime = endDate.getTime();
var week = 86000 * 1000 * 7;
this._validDurations.each(function(item, index) {
// we already added the first end date
if (index > 0) {
endDateTime += week;
var date = new Date(endDate);
date.setDate(date.getDate() + (7 * index));
validEndDates.push(date);
}
}.bind(this));
return validEndDates;
},
/**
* Returns the parent
*
* @return SchoolAccommodations The parent
*/
getParent : function() {
return this._schoolAccommodationsContainer;
},
/**
* Remove the accommodation from the list
*/
removeAccommodation : function() {
this._accommodationDurationsList.deleteList();
if(this._container.getParent())this._container.remove();
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-Andrďż˝ Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
*
* @param AccommodationListItemDTO schoolAccommodationsDTO The DTO containing all the accommodations informations
* @param Object translateDTO The DTO containing all the translations for this class
* @param Element eListContainer The list container
* @param School oSchool The school
**/
var SchoolAccommodations = Events.extend({
/**
* This is the initialization function
*/
initialize : function(schoolAccommodationsDTO, translateDTO, eListContainer, oSchool) {
this._schoolAccommodationsDTO = schoolAccommodationsDTO;
this._translateDTO = translateDTO;
this._accommodations = new Array();
this._school = oSchool;
this._listContainer = eListContainer;
this._classNameBase = this._school.getClassNameBase();
this._calendar = new BookingCalendar({
days: this._school._translateDTO.days, // days of the week starting at sunday
months: this._school._translateDTO.months,
offset: this._school._translateDTO.firstDayOfWeek
});
this._calendar.addEvent('dateselected', function(e){
this._calendar.getLinkedElement().fireEvent('dateselected', this._calendar.getSelectedDate());
this._calendar.hide();
}.bind(this));
this.addEvent('refreshAccommodations', function(item, index) {
this.refreshAccommodations();
}.bind(this));
},
getCalendar : function(){
return this._calendar;
},
/**
* Returns an object containing the informations for the calculation price
*
* @return Array The informations needed to calculate the price
*/
getDTO : function() {
var accommodationsDTO = new Array();
this._accommodations.each(function(item, index) {
if (item.isComplete()) {
accommodationsDTO.push(item.getDTO());
}
});
return accommodationsDTO;
},
/**
* Populate the accommodation from a dto
*
* @param Array toPopulateDTO The accommodations to add
*/
populateFromDTO : function(toPopulateDTO) {
var accommodations = new Array();
if (toPopulateDTO) {
toPopulateDTO.each(function(item, index) {
// check
this._schoolAccommodationsDTO.each(function(accommodationItem, accommodationIndex) {
var accommodationToAdd = accommodationItem.option.filter(function(optionItem, optionIndex) {
return optionItem.id == item.id;
});
if (accommodationToAdd[0]) {
accommodationToAdd[0].parentId = accommodationItem.id;
accommodationToAdd[0].dto = item;
accommodations.push(accommodationToAdd[0]);
}
}.bind(this));
}.bind(this));
}
if (accommodations.length) {
for (var i = 0; i < accommodations.length; i++) {
this.addAccommodation(accommodations[i].parentId, accommodations[i].id);
if (this._accommodations.length)this._accommodations.getLast().populateFromDTO(accommodations[i].dto);
}
}
},
/**
*  Return the classNameBase
*/
getClassNameBase : function() {
return this._classNameBase;
},
/**
* Returns the visual accommodation container
*/
getHtml : function() {
this._accommodationContainer = new Element('div', {'class': this._classNameBase + 'Section' + ' ' + this._classNameBase2 + 'Section'});
this._accommodationTitle = new Element('div', {'class': this._classNameBase + 'Section-Title' + ' ' + this._classNameBase2 + 'Section-Title'});
this._accommodationListContainer = new Element('div', {'class': this._classNameBase + 'Courses-CoursesList-Container' + ' ' + this._classNameBase2 + 'Courses-CoursesList-Container'});
this._accommodationUserAccommodationList = new Element('div', {'class': this._classNameBase + 'Courses-UserCoursesList' + ' ' + this._classNameBase2 + 'Courses-UserCoursesList'});
this._accommodationAddButton = new Element('div', {'class': this._classNameBase + 'AddButton' + ' ' + this._classNameBase2 + 'AddButton'});
this._accommodationTitle.injectInside(this._accommodationContainer);
this._accommodationListContainer.injectInside(this._accommodationContainer);
this._accommodationUserAccommodationList.injectInside(this._accommodationListContainer);
this._accommodationAddButton.injectInside(this._accommodationContainer);
this._accommodationTitle.setHTML(this._translateDTO.title);
this._accommodationAddButton.setHTML(this._translateDTO.add);
this.accommodationsList = new SchoolList(this._accommodationAddButton, this._classNameBase);
this.getVisualAccommodationList(this.accommodationsList, this.addAccommodationEventFunction);
this.refreshVisualAccommodationList(this.accommodationsList);
this.accommodationsList.getHtml().injectInside(this._listContainer);
this.accommodationsList.initializeEvents();
var displayAccommodations = false;
for(var i = 0; i < this._schoolAccommodationsDTO.length; i++){
if(this._schoolAccommodationsDTO[i].option.length){
displayAccommodations = true;
}
}
if(!displayAccommodations){
this._accommodationContainer.setStyle('display', 'none');
}
return this._accommodationContainer;
},
/**
* Generate the accommodation list
*
* @param SchoolList list The list to refresh
*
*/
getVisualAccommodationList : function(list, eventFunction, context) {
if(!context) context = this;
// clearing the list
list.clear();
this._schoolAccommodationsDTO.each(function(item, index) {
var sectionId = parseInt(item.id);
var value = new Object();
value.type = 'category';
value.sectionId = sectionId;
list.addItem(value, item.name);
list.getListItems().getLast().getHtml().addClass(this._classNameBase + 'List-Item-Category');
list.getListItems().getLast().getHtml().addClass(this._classNameBase2 + 'List-Item-Category');
item.option.each(function(item, index) {
item.parentId = sectionId;
var listItem = new SchoolListItem(item, item.name, this._classNameBase);
list.addListItem(listItem);
listItem.getHtml().addClass(this._classNameBase + 'List-Item-Accommodation');
listItem.getHtml().addClass(this._classNameBase2 + 'List-Item-Accommodation');
listItem.getHtml().addEvent('click', eventFunction.bind(context));
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.notAvailable);
if (this.getCompletedCourses().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
addAccommodationEventFunction : function(e){
e = new Event(e);
var listItem = e.target.listItemContainer;
if (listItem.getIsSelectionnable()) {
this.addAccommodation(listItem.getValue().parentId, listItem.getValue().id);
this._school.fireEvent('heightModified');
// refresh the accommodation, but not the shopping cart result price
this.refreshAccommodations(null, true);
}
},
/**
* Refresh the accommodation list
*
* @param SchoolList list The list to refresh
*
*/
refreshVisualAccommodationList : function(list) {
var availableAccommodations = this.getAvailableAccommodations();
var accommodationStartDate = this.getSchoolAccommodationStartDate();
var accommodationEndDate = this.getAccommodationEndDate();
list.getListItems().each(function(item, index) {
if (availableAccommodations.contains(item.getValue().parentId)) {
var startDate = new Date(accommodationStartDate);
var day = startDate.getDay();
if (day == 0)day = 7;
while (parseInt(item.getValue().accommodationStartDay) != day) {
startDate.setDate(startDate.getDate() - 1);
day = startDate.getDay();
if (day == 0)day = 7;
}
var endDate = new Date(accommodationEndDate);
var day = endDate.getDay();
if (day == 0)day = 7;
while (parseInt(item.getValue().accommodationEndDay) != day) {
endDate.setDate(endDate.getDate() + 1);
day = endDate.getDay();
if (day == 0)day = 7;
}
}
var available =  true;
// check the availability for this accommodation
if(accommodationStartDate && accommodationEndDate && item.getValue().availabilities && item.getValue().availabilities.length){
var availabilities = item.getValue().availabilities;
var startWeek = accommodationStartDate.getWeek();
var startYear = accommodationStartDate.getFullYear();
var endWeek = accommodationEndDate.getWeek();
var duration  = this.getDurationInWeeks(accommodationEndDate, accommodationStartDate);
available = false;
var i = 0;
if(startWeek == endWeek){
if(availabilities[startYear + '' + endWeek] == undefined){
available = true;
}
}else {
while (duration > 0 && startWeek != endWeek && !available){
if(availabilities[startYear + '' + startWeek] == undefined){
available = true;
}
if(startWeek == 52){
startWeek = 1;
startYear++;
}else {
startWeek++;
}
duration--;
}
}
}
// if the accommodation is available,
// the duration is longer than the minimum duration of the accommodation and the number of participant is big enough
if (availableAccommodations.contains(item.getValue().parentId)
&& this.getDurationInWeeks(endDate, startDate) >= item.getValue().minimumDurationInWeeks
&& this.getSchoolParticipants() >= item.getValue().minimumNumberOfPeople) {
item.setIsSelectionnable(available);
} else {
// if the item is not a category,
if (item.getValue().type != 'category') {
item.setIsSelectionnable(false);
}
}
}.bind(this));
if (this.getCompletedCourses().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Add an accommodation
*
* @param Number id The accommodation ID
* @param Number optionID The accommodation Option ID
* @param Boolean attachedAccommodation True if the accommodation is attached (false by default)
*
* @return True if the accommodation is added
*/
addAccommodation : function(id, optionId, attachedAccommodation) {
var accommodationDetailsDTO = this._schoolAccommodationsDTO.copy();
// retrieve the course informations
accommodationDetailsDTO = accommodationDetailsDTO.filter(function(item, index) {
return item.id == id;
}.bind(this));
var accommodationOptionDetails = accommodationDetailsDTO[0].option.filter(function(item, index) {
return item.id == optionId;
}.bind(this));
var newAccommodation = new SchoolAccommodationObject(accommodationDetailsDTO[0], accommodationOptionDetails[0], this._translateDTO.accommodationObject, this._classNameBase ,this);
// if the accommodation has valid start dates it is added
if (newAccommodation.getStartDates().length) {
if(!attachedAccommodation)this._accommodations.push(newAccommodation);
newAccommodation.createVisualAccommodation(attachedAccommodation);
if(attachedAccommodation)this._accommodations.push(newAccommodation);
if(!newAccommodation.getHtml()){
return false;
}
newAccommodation.getHtml().injectInside(this._accommodationUserAccommodationList);
newAccommodation.addEvent('deleteAccommodation', function(e) {
this.deleteAccommodation(newAccommodation);
}.bind(this));
return true;
} else {
return false;
}
},
/**
* Refresh all the accommodations
*
* it is called when an accommodation or a course is modified
*
* @optionalparam String option The options - lists if the list have to be regenerated
* @optionalparam boolean noPriceRefresh True if the price should not be refreshed
*/
refreshAccommodations : function(option, noPriceRefresh) {
this.refreshVisualAccommodationList(this.accommodationsList);
// if an accomodation need more than the number of people selected, it's deleted
var accommodationModified = false;
for (var i = 0; i < this._accommodations.length; i++) {
if (this._accommodations[i].getAccommodationOptionDetails().minimumNumberOfPeople > this.getSchoolParticipants()) {
this._accommodations[i].removeAccommodation();
this._accommodations.remove(this._accommodations[i]);
accommodationModified = true;
i--;
}
}
if (accommodationModified) this._school.fireEvent('refreshPrice');
// if there are no more courses, all the accommodations are deleted
if (this.getCompletedCourses().length == 0) {
var accommodations = this._accommodations.length;
for (var i = 0; i < this._accommodations.length; i++) {
if (this._accommodations.length) {
this._accommodations[i].removeAccommodation();
this._accommodations.remove(this._accommodations[i]);
i--;
}
}
this.displayAddButton(false);
// and if there was any accommodations and there is no transfers, we send a refresh price (else the refresh price will be made by the school transfers)
if (accommodations && !this._school.getCompletedTransfers()) {
this._school.fireEvent('refreshPrice');
}
} else {
// getting the mandatory accommodations
var mandatoryAccommodations = this._school.getMandatoryAccommodations();
// checking if the there are no unavailable accommodation on the basket
var availableAccommodations = this.getAvailableAccommodations();
// remove the unauthorized accommodations
for (var i = 0; i < this._accommodations.length; i++) {
if (!availableAccommodations.contains(parseInt(this._accommodations[i]._accommodationDetails.id))) {
this._accommodations[i].removeAccommodation();
this._accommodations.remove(this._accommodations[i]);
i--;
}
}
for (var i = 0; i < this._accommodations.length; i++) {
this._accommodations[i].setIsAttachedToCourse(false);
}
// if there are mandatory accommodations
if (mandatoryAccommodations.length) {
this.checkMandatoryAccomodations(mandatoryAccommodations);
}
// retrieve the max start and end date value (based on the courses and acommodation start day and end day)
var startDate = this.getAccommodationStartDate();
var endDate = this.getAccommodationEndDate();
if (this._accommodations.length && endDate < this._accommodations.getLast().getAccommodationEndDate()) {
var endDay = parseInt(this._accommodations.getLast().getAccommodationOptionDetails().accommodationEndDay);
if (endDay == 7)endDay = 0;
while (endDay != endDate.getDay()) {
endDate.setDate(endDate.getDate() + 1);
}
if (endDate < this._accommodations.getLast().getAccommodationEndDate()) {
// delete the accommodations that are beyond the end date
for (var i = this._accommodations.length - 1; i > 0; i--) {
if (this._accommodations[i].getAccommodationEndDate() > endDate) {
this._accommodations[i].removeAccommodation();
this.deleteAccommodation(this._accommodations[i]);
}
}
// if there are still accommodations the last one is adapted to fit the new dates
if (this._accommodations.length) {
var duration = this.getDurationInWeeks(endDate, this._accommodations.getLast().getAccommodationStartDate());
// if the new duration is smaller than the minimum
if (duration < this._accommodations.getLast().getAccommodationOptionDetails().minimumDurationInWeeks) {
duration = this._accommodations.getLast().getAccommodationOptionDetails().minimumDurationInWeeks;
// if it can't be adapted, it is deleted
if (this.getDurationInWeeks(endDate, startDate) < duration) {
this._accommodations.getLast().removeAccommodation();
this.deleteAccommodation(this._accommodations.getLast());
} else {
this._accommodations.getLast().refreshAccommodationData(this._accommodations.getLast().getAccommodationStartDate(), duration, endDate);
}
} else {
this._accommodations.getLast().refreshAccommodationData(this._accommodations.getLast().getAccommodationStartDate(), duration, endDate);
}
}
}
}
// if the new accommodation startDate is smaller than the old one
if (this._accommodations.length && startDate > this._accommodations[0].getAccommodationStartDate()
&& !this._accommodations[0].getIsAttachedToCourse()) {
for (var i = 0; i < this._accommodations.length; i++) {
if (this._accommodations[i].getAccommodationStartDate() < startDate) {
this._accommodations[i].removeAccommodation();
this.deleteAccommodation(this._accommodations[i]);
i--;
}
}
if (this._accommodations.length) {
var duration = this.getDurationInWeeks(this._accommodations[0].getAccommodationEndDate(), startDate);
if (duration < this._accommodations[0].getAccommodationOptionDetails().minimumDurationInWeeks) duration = this._accommodations[0].getAccommodationOptionDetails().minimumDurationInWeeks;
this._accommodations[0].refreshAccommodationData(startDate, duration, this._accommodations[0].getAccommodationEndDate());
}
}
// if the lists have to be generated again
if (option == 'lists') {
this._accommodations.each(function(item, index) {
if (!this._accommodations[0].getIsAttachedToCourse()) {
item.reGenerateAccommodationLists();
this.checkAccommodations(item);
}
}.bind(this));
} else {
this._accommodations.each(function(item, index) {
if (!this._accommodations[0].getIsAttachedToCourse()) {
item.refreshAccommodationLists();
this.checkAccommodations(item);
}
}.bind(this));
}
var refreshPrice = false;
if (this._accommodations.length == 1) {
noPriceRefresh = false;
}
for (var i = 0; i < this._accommodations.length; i++) {
if (this._accommodations[i].isComplete()) {
refreshPrice = true;
break;
}
}
if (!noPriceRefresh && refreshPrice) {
this._school.fireEvent('refreshPrice');
}
// check if the add button must be displayed or not
if((this.getCompletedCourses().length == mandatoryAccommodations.length
&& mandatoryAccommodations.length <= this._accommodations.length)
|| (this._accommodations.length && this._accommodations.getLast().getIsAttachedToCourse() == true
&& this._accommodations.getLast().getAttachedToCourse().courseId == this._school.getCourses().getValidAddedCourses(true).getLast().getCourseDetails().id)){
this.displayAddButton(false);
}else{
this.displayAddButton(true);
}
}
},
/**
* check if the mandatory accommodations are correctly added and displayed
*
* @param Array mandatoryAccommodations The mandatory accommodations list
* @optionalparam Integer notToAdd The accommodationOption id to not add
*
*/
checkMandatoryAccomodations : function(mandatoryAccommodations) {
// check each mandatory accommodations
for (var i = 0; i < mandatoryAccommodations.length; i++) {
// getting the accommodations informations to add
var accommodationsToAdd = this._schoolAccommodationsDTO.filter(function(item, index) {
return mandatoryAccommodations[i].ids.contains(parseInt(item.id));
});
// if there is a valid accommodation to add
if (accommodationsToAdd.length) {
var accommodationsAlreadyAdded = new Array();
// checking if the accommodation is already present
if (this._accommodations.length) {
this._accommodations.each(function(item, index) {
for (var j = 0; j < accommodationsToAdd.length; j++) {
if (item._accommodationDetails.id == accommodationsToAdd[j].id && !(item.getIsAttachedToCourse())) {
accommodationsAlreadyAdded.push(item);
}
}
}.bind(this));
}
// if there are no accommodation added
if (!accommodationsAlreadyAdded.length) {
var added = false;
var j = 0;
var k = 0;
while (!added) {
// find a valid accommodation to add in the list
if (j < accommodationsToAdd.length) {
// find the first valid accommodation option
if (k < accommodationsToAdd[j].option.length) {
this.addAccommodation(accommodationsToAdd[j].id, accommodationsToAdd[j].option[k].id, true);
if (this._accommodations.length) {
this._accommodations[this._accommodations.length - 1].setIsAttachedToCourse(true);
this._accommodations[this._accommodations.length - 1].setAttachedToCourse(mandatoryAccommodations[i]);
// set the values
var startDate = this.getAccommodationValidStartDates(this._accommodations[this._accommodations.length - 1], this._accommodations[this._accommodations.length - 1]._accommodationStartDatesList);
if (startDate.length) {
this._accommodations[this._accommodations.length - 1].setAttachedAccommodationStartDate(startDate[0]);
var duration = this.getAccommodationValidDuration(this._accommodations[this._accommodations.length - 1], this._accommodations[this._accommodations.length - 1]._accommodationDurationsList);
if (duration.length) {
this._accommodations[this._accommodations.length - 1].setAttachedAccommodationDuration(duration[0]);
}
}
if (startDate.length && duration.length) {
added = true;
} else {
// remove the accommodation and try to add the next one
this._accommodations[this._accommodations.length - 1].removeAccommodation();
this._accommodations.remove(this._accommodations[this._accommodations.length - 1]);
k++;
}
}else{
j++;
}
} else {
j++;
}
} else {
added = true;
}
}
} else {
accommodationsAlreadyAdded[0].setIsAttachedToCourse(true);
accommodationsAlreadyAdded[0].setAttachedToCourse(mandatoryAccommodations[i]);
var startDate = this.getAccommodationValidStartDates(accommodationsAlreadyAdded[0], accommodationsAlreadyAdded[0]._accommodationStartDatesList);
if (startDate.length) {
accommodationsAlreadyAdded[0].setAttachedAccommodationStartDate(startDate[0]);
var duration = this.getAccommodationValidDuration(accommodationsAlreadyAdded[0], accommodationsAlreadyAdded[0]._accommodationDurationsList);
if (duration.length) {
accommodationsAlreadyAdded[0].setAttachedAccommodationDuration(duration[0]);
//                          accommodationsAlreadyAdded[0].refreshAccommodationLists();
this._accommodations[this._accommodations.length - 1].reGenerateAccommodationLists();
}
}
// if something was not valid, remove the accommodation and add another one
if (!startDate.length || !duration.length) {
this._accommodations.remove(accommodationsAlreadyAdded[0]);
accommodationsAlreadyAdded[0].removeAccommodation();
i--;
}
}
}
}
},
/**
* Check all the accommodations and modify them to fit the accommodation passed in parameter
*
* @param SchoolAccommodationsObject accommodation The accommodation to check
*
*/
checkAccommodations : function(accommodation) {
var index = this._accommodations.indexOf(accommodation);
// if it's the first accommodation and there are more than one accommodation
if (index == 0 && this._accommodations.length > 1) {
if (accommodation.getAccommodationEndDate() > this._accommodations[index + 1].getAccommodationStartDate() && this._accommodations[index + 1].isComplete() && accommodation.isComplete()) {
var duration = this.getDurationInWeeks(this._accommodations[index + 1].getAccommodationEndDate(), accommodation.getAccommodationEndDate());
if (duration < this._accommodations[index + 1].getAccommodationOptionDetails().minimumDurationInWeeks) duration = this._accommodations[index + 1].getAccommodationOptionDetails().minimumDurationInWeeks;
// set the new data for the next accommodation
if(this._accommodations[index+1].getIsAttachedToCourse() == false)this._accommodations[index + 1].refreshAccommodationData(accommodation.getAccommodationEndDate(), duration, this._accommodations[index + 1].getAccommodationEndDate());
}
}
// if it's not the first accommodation
if (index > 0) {
// set the previous valid accommodation with valid data (endDate is set with the actual accommodation startDate and duration is calculated)
// if the startDate is higher than the previous end Date
if (accommodation.getAccommodationStartDate() < this._accommodations[index - 1].getAccommodationEndDate() && this._accommodations[index - 1].isComplete() && accommodation.isComplete()) {
var duration = this.getDurationInWeeks(accommodation.getAccommodationStartDate(), this._accommodations[index - 1].getAccommodationStartDate());
if (duration < this._accommodations[index - 1].getAccommodationOptionDetails().minimumDurationInWeeks) {
duration = this._accommodations[index - 1].getAccommodationOptionDetails().minimumDurationInWeeks;
}
// set the new data for this accommodation
if(this._accommodations[index-1].getIsAttachedToCourse() == false)this._accommodations[index - 1].refreshAccommodationData(this._accommodations[index - 1].getAccommodationStartDate(), duration, accommodation.getAccommodationStartDate());
}
}
// if it's not the first and not the last one
if (index > 0 && this._accommodations.getLast() != accommodation) {
if (accommodation.getAccommodationEndDate() > this._accommodations[index + 1].getAccommodationStartDate() && this._accommodations[index + 1].isComplete() && accommodation.isComplete()) {
var duration = this.getDurationInWeeks(this._accommodations[index + 1].getAccommodationEndDate(), accommodation.getAccommodationEndDate());
if (duration < this._accommodations[index + 1].getAccommodationOptionDetails().minimumDurationInWeeks) {
duration = this._accommodations[index + 1].getAccommodationOptionDetails().minimumDurationInWeeks;
}
// set the new data for this accommodation
if(this._accommodations[index+1].getIsAttachedToCourse() == false)this._accommodations[index + 1].refreshAccommodationData(accommodation.getAccommodationEndDate(), duration, this._accommodations[index + 1].getAccommodationEndDate());
}
}
}
,
/**
* Return the school accommodation start date
*
* @return Date the school accommodations start date
*/
getSchoolAccommodationStartDate : function() {
return this._school.getAccommodationStartDate();
},
getSchoolParticipants : function() {
return this._school.getParticipants();
},
/**
* Returns the possible startDate for the accommodation given in parameter
*
* @param SchoolAccommodationObject accommodation The accommodation
*
* @return Date The possible startdates
*/
getAccommodationStartDate : function() {
var startDate = this.getSchoolAccommodationStartDate();
if(this._accommodations.length){
var day = startDate.getDay();
if (day == 0)day = 7;
if(this._accommodations[0] && this._accommodations[0].getAccommodationOptionDetails().accommodationStartDay > 0){
while (this._accommodations[0].getAccommodationOptionDetails().accommodationStartDay != day) {
startDate.setDate(startDate.getDate() - 1);
day = startDate.getDay();
if (day == 0)day = 7;
}
}
}
return startDate;
},
/**
* Returns the valid startDates for an accommodation given in parameter
*
* @param SchoolAccommodationObject accommodation The accommodation
* @param Array accommodationStartDates Array of number containing all the possible start dates
*
* @return Array An array of possible start dates
*/
getAccommodationValidStartDates : function(accommodation, accommodationStartDates) {
var validStartDates = new Array();
var startDates = accommodation.getStartDates();
/* var startDates = new Array();
for(var i = 0; i < accommodationStartDates.getListItems().length; i++ ){
startDates.push(accommodationStartDates.getListItems()[i].getValue());
}*/
var minimumDuration = accommodation.getAccommodationOptionDetails().minimumDurationInWeeks;
var availabilities = accommodation.getAccommodationOptionDetails().availabilities;
// if this accommodation is not the first, we remove the minimum durations of the previous one
if (this._accommodations.indexOf(accommodation) > 0) {
for (var i = 0; i < this._accommodations.indexOf(accommodation); i++) {
if (this._accommodations[i].isComplete()) {
if(this._accommodations[i].getIsAttachedToCourse() == true){
startDates.splice(0, this._accommodations[i]._accommodationDuration);
}else{
startDates.splice(0, this._accommodations[i].getAccommodationOptionDetails().minimumDurationInWeeks);
}
}
}
}
// if this accommodation is not the last, we remove the minimum durations of the next one
if (this._accommodations.getLast() != accommodation) {
for (var i = this._accommodations.length - 1; i > this._accommodations.indexOf(accommodation); i--) {
if (this._accommodations[i].isComplete()) {
if(this._accommodations[i].getIsAttachedToCourse() == true){
startDates.splice(startDates.length - this._accommodations[i]._accommodationDuration, this._accommodations[i]._accommodationDuration);
}else{
startDates.splice(startDates.length - this._accommodations[i].getAccommodationOptionDetails().minimumDurationInWeeks, this._accommodations[i].getAccommodationOptionDetails().minimumDurationInWeeks);
}
}
}
}
startDates.each(function(item, index) {
var date = item;
var year = date.getFullYear();
var week = date.getWeek();
if (accommodation.getAccommodationOptionDetails().accommodationStartDay == 7) {
if (week > 1)week = week + 1;
}
// check the availabilities for this start date
var toAdd = true;
if (availabilities) {
for (var i = 0; i < parseInt(minimumDuration); i++) {
if (week > 52) {
var lastWeek = (new Date(date.getFullYear(), 12, 31)).getWeek();
if (week < lastWeek) {
week = week - lastWeek;
year = year + 1;
}
}
if (availabilities[year + '' + week] == 0) {
toAdd = false;
}
week++;
}
}
if (toAdd) {
validStartDates.push(date);
}
}.bind(this));
// if the accommodation is attached to a course, we must find the only course start date available
if (accommodation.getIsAttachedToCourse()) {
var courseStartDate = (new Date()).fromIso(accommodation.getAttachedToCourse().startDate);
var courseStartTime = courseStartDate.getTime();
for (var i = 0; i < validStartDates.length; i++) {
var n = (i == 0? i : i + 1);
if(validStartDates.length > n) {
var validStartTime = validStartDates[n].getTime();
// if the start date is smaller that the course start time (minus 3 days) we remove it
if (validStartTime < (courseStartTime - (86400 * 3 * 1000))) {
validStartDates.splice(0, i + 1);
i--;
}
// if the start date is bigger that the course start time (+3 days) we remove it
if (validStartTime > (courseStartTime + (86400 * 3 * 1000))) {
validStartDates.splice(n, validStartDates.length - 1);
}
}
}
return validStartDates;
}
return validStartDates;
},
/**
* Return the added accommodations
*/
getAccommodations : function(){
return this._accommodations;
},
/**
* Returns the final endDate for a given accommodation
*
* @param SchoolAccommodationObject accommodation The accommodation
*
* @return Date the endDate
*/
getAccommodationEndDate : function(accommodation) {
return this._school.getAccommodationEndDate(accommodation);
},
/**
* Returns an array of valid durations calculated from the startdates of the accommodation and
* the endDate returned by the parent
*
* @return Array An Array of number containing the valid durations
*/
getAccommodationValidDuration : function(accommodation, durationList) {
// check if this accommodation is attached to a course
if (accommodation.getIsAttachedToCourse()) {
var accommodationEndDate = this._school.getCourseAccommodationEndDate(accommodation.getAttachedToCourse().courseId, (new Date()).fromIso(accommodation.getAttachedToCourse().startDate), accommodation);
// if there is an accommodation end date returned
if (accommodationEndDate) {
var duration = this.getDurationInWeeks(accommodationEndDate, accommodation._accommodationStartDate);
}else{
return [];
}
}
// if the accommodations is not attached
var validDurations = new Array();
var durations = durationList;
var durationsToRemove = 0;
// if the accommodation has a start date
if (accommodation.getAccommodationStartDate()) {
var difference = this.getDurationInWeeks(this.getAccommodationEndDate(accommodation), accommodation.getAccommodationStartDate());
durationsToRemove = durations.getListItems().length - 1 + parseInt(accommodation.getAccommodationOptionDetails().minimumDurationInWeeks) - Math.round(difference);
if(this._accommodations.indexOf(accommodation) >= 0){
for (var i = this._accommodations.indexOf(accommodation); i < this._accommodations.length; i++) {
if (accommodation != this._accommodations[i] && this._accommodations[i].isComplete()) {
if (this._accommodations[i].getIsAttachedToCourse() == true) {
durationsToRemove = parseInt(durationsToRemove + parseInt(this._accommodations[i]._accommodationDuration));
} else {
durationsToRemove = parseInt(durationsToRemove + parseInt(this._accommodations[i].getAccommodationOptionDetails().minimumDurationInWeeks));
}
}
}
}
} else {
for (var i = 0; i < this._accommodations.length; i++) {
if (accommodation != this._accommodations[i] && this._accommodations[i].isComplete()) {
durationsToRemove = parseInt(durationsToRemove + parseInt(this._accommodations[i].getAccommodationOptionDetails().minimumDurationInWeeks));
}
}
}
var week = -1;
var year = -1;
if (accommodation.getAccommodationStartDate()) {
week  = accommodation.getAccommodationStartDate().getWeek();
year  = accommodation.getAccommodationStartDate().getFullYear();
if(accommodation.getAccommodationOptionDetails().accommodationStartDay == 7){
if(week > 1)week = week+1;
}
}
// add the duration items
if(durationsToRemove < 0)durationsToRemove = 0;
for(var i = 0; i < (durations.getListItems().length - durationsToRemove); i++){
var value = durations.getListItems()[i].getValue();
if(week == -1 || !accommodation.getAccommodationOptionDetails().availabilities ||
accommodation.getAccommodationOptionDetails().availabilities[accommodation.getAccommodationStartDate().getFullYear() + '' + (week + parseInt(value)-1)] != 0){
validDurations.push(parseInt(value));
}else{
break;
}
}
if (accommodation.getIsAttachedToCourse()) {
if (duration && validDurations.contains(duration)) {
return [parseInt(duration)];
} else {
return [];
}
}
return validDurations;
}
,
/**
* Returns the end date of the previous accommodation
*
* @param SchoolAccommodationObject accommodation The accommodation
*/
getPreviousEndDate : function(accommodation) {
var previousEndDate = this.getAccommodationEndDate();
for (var i = 0; i < this._accommodations.indexOf(accommodation); i++) {
if (this._accommodations[i].isComplete()) previousEndDate = this._accommodations[i].getAccommodationEndDate();
}
return previousEndDate;
}
,
/**
* Returns the duration in weeks between a startDate and an end date
*
* @param Date endDate The end date
* @param Date starDate The startdate
* @return Number The duration in week
*/
getDurationInWeeks : function(endDate, startDate) {
var duration = endDate - startDate;
duration = Math.round(duration / (1000 * 60 * 60 * 24 * 7));
if(duration == 0 && startDate.getTime() < endDate.getTime() ){
duration = 1;
}
return duration;
},
/**
* Returns the completed accommodations
*
* @return SchoolAccommodationObject[] The completed accommodations
*/
getCompletedAccommodations : function() {
var accommodations = new Array();
this._accommodations.each(function(item, index) {
if (item.isComplete) {
accommodations.push(item);
}
});
return accommodations;
},
/**
* Return the completed courses for this school (if any)
*
*/
getCompletedCourses : function() {
return this._school.getCompletedCourses();
},
/**
* Delete the accommodation given in parameter
*
* @param Element accommodation The accommodation to delete
*/
deleteAccommodation : function(accommodation) {
this._accommodations.remove(accommodation);
this.refreshAccommodations();
this._school.fireEvent('heightModified');
//        if (!this._accommodations.length) {
this.fireEvent('refreshPrice');
//        }
},
/**
*  Returns the available accommodations
*
* @return Array of integer The Accommodation IDs
*/
getAvailableAccommodations : function() {
return this._school.getAvailableAccommodations();
},
/**
* Return an array containing the available transfers
*
* @return Array of transfers ID
*/
getAvailableTransfers : function() {
var availableTransfers = new Array();
for (var i = 0; i < this._accommodations.length; i++) {
availableTransfers = availableTransfers.merge(this._accommodations[i].getAccommodationDetails().availableTransfers);
}
return availableTransfers;
},
/**
* Return the max accommodation end date for a course
*
* @param integer courseId The Course ID
* @param Date startDate the course start date
*
* @return Date The course accommodation end date
*/
getCourseAccommodationEndDate : function(courseId, startDate, accommodation) {
return this._school.getCourseAccommodationEndDate(courseId, startDate, accommodation);
},
/**
* Display or hide the add button
*
* @param boolean isDisplayed True to display the hide button
*/
displayAddButton : function(isDisplayed){
if(isDisplayed){
this._accommodationAddButton.setStyle('display', '');
}else{
this._accommodationAddButton.setStyle('display', 'none');
}
},
/**
* Returns the parent of this object
*
* @return Object The parent object
*/
getSchool : function() {
return this._school;
}
,
/**
* Returns the school accommodations DTO
*
* @return Object The school accommodations DTO
*/
getSchoolAccommodationsDTO : function() {
return this._schoolAccommodationsDTO;
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @event Event refreshPrice This is fired when the price have to be recalculated
* @event Event refreshAccommodations This is fired when a course is modified and the accommodations have to be refreshed
* @event Event heightModified This is fired when a course is added or deleted
*
* @param FixedDatesCourseListItemDTO schoolFixedCoursesDTO The DTO containing all the fixed courses informations
* @param VariableDatesCourseListItemDTO schoolVariableCoursesDTO The DTO containing all the variable courses informations
* @param Object translateDTO The DTO containing all the translations for this class
* @param School parent The parent
**/
var SchoolCourses = Events.extend({
/**
* This is the initialization function
*
*/
initialize : function(schoolFixedCoursesDTO, schoolVariableCoursesDTO, schoolOptionalCoursesDTO, translateDTO, listContainer, parent) {
this._schoolFixedCoursesDTO = schoolFixedCoursesDTO;
this._schoolVariableCoursesDTO = schoolVariableCoursesDTO;
this._schoolOptionalCoursesDTO = schoolOptionalCoursesDTO;
this._listContainer = listContainer;
this._translateDTO = translateDTO;
this._courses = new Array();
this._parent = parent;
this._classNameBase = this.getParent().getClassNameBase();
this.addEvent('refreshCourses', function() {
this.refreshCourses();
}.bind(this));
},
/**
* Returns an object containing the informations for the calculation price
*
* @return Object The fixed course informations needed to calculate the price
*/
getFixedCoursesDTO : function() {
var schoolDTO = new Array();
this._courses.each(function(item, index) {
if (item.getCourseDetails().type == 'fixedDate' && item.isComplete()) {
schoolDTO.push(item.getDTO());
}
});
return schoolDTO;
},
/**
* Returns an object containing the informations for the calculation price
*
* @return Object the variable course informations needed to calculate the price
*/
getVariableCoursesDTO : function() {
var schoolDTO = new Array();
this._courses.each(function(item, index) {
if (item.getCourseDetails().type == 'variableDate' && item.isComplete()) {
schoolDTO.push(item.getDTO());
}
});
return schoolDTO;
},
/**
* Returns an object containing the informations for the calculation price
*
* @return Object the variable course informations needed to calculate the price
*/
getOptionalCoursesDTO : function() {
var schoolDTO = new Array();
this._courses.each(function(item, index) {
if (item.getCourseDetails().type == 'optional' && item.isComplete()) {
schoolDTO.push(item.getDTO());
}
});
return schoolDTO;
},
/**
*
* Populate the fixed courses from a dto
*
* @param Array The fixed course informations needed to populate
*/
populateCoursesFromDTO : function(fixedCoursesToPopulateDTO, variableCoursesToPopulateDTO, optionalCoursesToPopulateDTO) {
// push every courses into one array
var coursesDTO = new Array();
if (fixedCoursesToPopulateDTO) {
fixedCoursesToPopulateDTO.each(function(item, index) {
item.courseType = "fixed";
coursesDTO.push(item);
});
}
if (variableCoursesToPopulateDTO) {
variableCoursesToPopulateDTO.each(function(item, index) {
item.courseType = "variable";
coursesDTO.push(item);
});
}
if (optionalCoursesToPopulateDTO) {
optionalCoursesToPopulateDTO.each(function(item, index) {
item.courseType = "optional";
coursesDTO.push(item);
});
}
// sort the courses by startdates
coursesDTO.sort(function(x1, x2) {
return ((new Date()).fromIso(x1.startDate) - (new Date()).fromIso(x2.startDate));
});
coursesDTO.each(function(item, index) {
var course;
switch(item.courseType){
case 'variable':
course = this._schoolVariableCoursesDTO.filter(function(itemDTO, indexDTO) {
return itemDTO.id == item.id;
}.bind(this));
break;
case 'fixed':
course = this._schoolFixedCoursesDTO.filter(function(itemDTO, indexDTO) {
return itemDTO.id == item.id;
}.bind(this));
break;
case 'optional':
course = this._schoolOptionalCoursesDTO.filter(function(itemDTO, indexDTO) {
return itemDTO.id == item.id;
}.bind(this));
break;
}
// if a course has been found
if (course[0]) {
this.addCourse(course[0]);
this._courses[this._courses.length - 1].populateFromDTO(item);
}
}.bind(this));
},
/**
*  Return the classNameBase
*/
getClassNameBase : function() {
return this._classNameBase;
},
/**
* Refresh all the courses
*
*/
refreshCourses : function() {
var availableOptionalCourses = this.getAvailableOptionalCourses();
// remove the optionals course not allowed to be there
this._courses.each(function(item, index) {
if (item.getCourseDetails().type == 'optional' && !availableOptionalCourses.contains(parseInt(item.getCourseDetails().id))) {
this._courses.remove(item);
item.removeCourse();
}
}.bind(this));
// check the dates
this._courses.each(function(item, index) {
if (item.getCourseDetails().type == 'optional') {
var modified = false;
var validStartDates = this.getValidOptionalCourseStartDate(item);
if (validStartDates.length && !validStartDates.contains(item.getCourseStartDate())) {
item.setCourseStartDate(validStartDates[0]);
modified = true;
}
var validDurations = this.getValidOptionalCourseDuration(item);
if (!validDurations.contains(item.getCourseDuration()) && !item.getCourseDetails().oneDayCourse ) {
item.setCourseDuration(validDurations.getLast());
modified = true;
}
if(!validStartDates.length &&  !validDurations.length){
this._courses.remove(item);
item.removeCourse();
}
if (modified) item.refreshOptionalCourseData();
}
}.bind(this));
this.refreshVisualCoursesList(this.coursesList);
if(this.optionalCoursesList){
this.refreshVisualOptionalCoursesList(this.optionalCoursesList);
}
this._courses.each(function(item, index) {
item.refreshLists();
});
this.displayAddButton(this.getValidAddedCourses().length);
this._parent.fireEvent('refreshAccommodations');
},
/**
* Returns the visual course container
*
*/
getHtml : function() {
this._courseContainer = new Element('div', {'class': this._classNameBase + 'Section'});
this._mainCourseContainer = new Element('div', {'class': this._classNameBase + 'Section-Courses'});
this._courseTitle = new Element('div', {'class': this._classNameBase + 'Section-Title'});
this._courseListContainer = new Element('div', {'class': this._classNameBase + 'Courses-CoursesList-Container'});
this._courseUserCoursesList = new Element('div', {'class': this._classNameBase + 'Courses-UserCoursesList'});
this._courseAddButton = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._courseTitle.injectInside(this._mainCourseContainer);
this._courseListContainer.injectInside(this._mainCourseContainer);
this._courseUserCoursesList.injectInside(this._mainCourseContainer);
this._courseAddButton.injectInside(this._mainCourseContainer);
this._mainCourseContainer.injectInside(this._courseContainer);
this._courseTitle.setHTML(this._translateDTO.title);
this._courseAddButton.setHTML(this._translateDTO.add);
// initialize the courses list
this.coursesList = new SchoolList(this._courseAddButton, this._classNameBase);
this.getVisualCoursesList(this.coursesList);
this.coursesList.getHtml().injectInside(this._listContainer);
this.coursesList.initializeEvents();
if(this._schoolOptionalCoursesDTO.length){
this._optionalCourseContainer = new Element('div', {'class': this._classNameBase + 'Section-Courses'});
this._optionalCourseTitle = new Element('div', {'class': this._classNameBase + 'Section-Title'});
this._optionalCourseListContainer = new Element('div', {'class': this._classNameBase + 'Courses-CoursesList-Container'});
this._optionalCourseUserCoursesList = new Element('div', {'class': this._classNameBase + 'Courses-UserCoursesList'});
this._optionalCourseAddButton = new Element('div', {'class': this._classNameBase + 'AddButton '});
this._optionalCourseTitle.injectInside(this._optionalCourseContainer);
this._optionalCourseListContainer.injectInside(this._optionalCourseContainer);
this._optionalCourseUserCoursesList.injectInside(this._optionalCourseContainer);
this._optionalCourseAddButton.injectInside(this._optionalCourseContainer);
this._optionalCourseTitle.setHTML(this._translateDTO.optionalCourseTitle);
this._optionalCourseAddButton.setHTML(this._translateDTO.optionalCourseAdd);
this._optionalCourseContainer.injectInside(this._courseContainer);
// initialize the optional courses list
this.optionalCoursesList = new SchoolList(this._optionalCourseAddButton, this._classNameBase);
this.getVisualOptionalCoursesList(this.optionalCoursesList);
this.optionalCoursesList.getHtml().injectInside(this._listContainer);
this.optionalCoursesList.initializeEvents();
}
return this._courseContainer;
},
/**
* Generate the courses list for the "add a course" button
*
* @param SchoolList list The list we want to populate
*
*/
getVisualCoursesList : function(list) {
var validCourses = this.getValidCourses();
// clearing the list
list.clear();
var section = '';
//        list.addItem('category', this._translateDTO.coursesCategory);
//        list.getListItems().getLast().getHtml().addClass(this._classNameBase + 'List-Item-Category');
validCourses.each(function(item, index) {
// Add each courses
var listItem = new SchoolListItem(item, item.name, this._classNameBase);
list.addListItem(listItem);
listItem.getHtml().addClass(this._classNameBase + 'List-Item');
listItem.getHtml().addEvent('click', function() {
if(listItem.getIsSelectionnable()){
this.addCourse(item);
this._parent.fireEvent('heightModified');
}
}.bind(this));
}, this);
list.addItem('error', this._translateDTO.notAvailable);
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Generate the optional courses list for the "add an optional course" button
*
* @param SchoolList list The list we want to populate
*
*/
getVisualOptionalCoursesList : function(list) {
var validCourses = this.getValidCourses(null, true);
// clearing the list
list.clear();
var section = '';
validCourses.each(function(item, index) {
// Add each courses
var listItem = new SchoolListItem(item, item.name, this._classNameBase);
list.addListItem(listItem);
listItem.getHtml().addClass(this._classNameBase + 'List-Item');
listItem.getHtml().addEvent('click', function() {
if(listItem.getIsSelectionnable()){
this.addCourse(item);
this._parent.fireEvent('heightModified');
}
}.bind(this));
}, this);
list.addItem('error', this._translateDTO.notAvailable);
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Refresh the courses list
*
* @param SchoolList list the list we want to populate
*
*/
refreshVisualCoursesList : function(list) {
var validCourses = this.getValidCourses();
// retrieving the id of the available optional course
var availableOptionalCourses = this.getAvailableOptionalCourses();
list.getListItems().each(function(item, index) {
if ((validCourses.indexOf(item.getValue()) != -1)) {
item.setIsValid(true);
item.setIsSelectionnable(true);
// if the course is optional, checking that it's allowed to be selectionned
if (item.getValue().type == 'optional') {
if (!availableOptionalCourses.contains(parseInt(item.getValue().id))) {
item.setIsSelectionnable(false);
}
}
} else {
if(item.getValue() != 'category') item.setIsSelectionnable(false);
}
}.bind(this));
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Refresh the optional courses list
*
* @param SchoolList list the list we want to populate
*
*/
refreshVisualOptionalCoursesList : function(list) {
var validCourses = this.getValidCourses(null, true);
// retrieving the id of the available optional course
var availableOptionalCourses = this.getAvailableOptionalCourses();
list.getListItems().each(function(item, index) {
if ((validCourses.indexOf(item.getValue()) != -1)) {
item.setIsValid(true);
item.setIsSelectionnable(availableOptionalCourses.contains(parseInt(item.getValue().id)));
} else {
if(item.getValue() != 'category') item.setIsSelectionnable(false);
}
}.bind(this));
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* return the list of available optional course
*
* @return integer[] Array of optional course IDs
*/
getAvailableOptionalCourses : function() {
var completedCourses = this.getCompletedCourses();
var availableOptionalCourses = new Array();
for (var i = 0; i < completedCourses.length; i++) {
if (completedCourses[i].getCourseDetails().type != 'optional') {
for (var j = 0; j < completedCourses[i].getCourseDetails().availableOptionalCourses.length; j++) {
availableOptionalCourses.include(completedCourses[i].getCourseDetails().availableOptionalCourses[j]);
}
}
}
return availableOptionalCourses;
},
/**
* Add a selected course
*
* @param Object course The course DTO
*/
addCourse : function(course) {
var newCourse;
switch (course.type) {
case 'fixedDate' :
newCourse = new SchoolFixedCourseObject(course, this._translateDTO.courseObject, this._listContainer, this._classNameBase, this);
break;
case 'variableDate' :
newCourse = new SchoolVariableCourseObject(course, this._translateDTO.courseObject, this._listContainer, this._classNameBase, this);
break;
case 'optional' :
newCourse = new SchoolOptionalCourseObject(course, this._translateDTO.courseObject, this._listContainer, this._classNameBase, this);
break;
}
newCourse.addEvent('refreshPrice', this.refreshPrice.bind(this));
this._courses.push(newCourse);
newCourse.createVisualCourse();
newCourse.addEvent('deleteCourse', function(e) {
this.deleteCourse(newCourse);
}.bind(this));
// add the html course
switch (course.type) {
case 'optional' :
this._courses.getLast().getHtml().injectInside(this._optionalCourseListContainer);
break;
default:
this._courses.getLast().getHtml().injectInside(this._courseUserCoursesList);
break;
}
},
/**
* Delete the course given in parameter
*
* @param SchoolCourseObject course The course to delete
*/
deleteCourse : function(course) {
this._courses.remove(course);
if (this._parent.getCompletedAccommodations().length == 0 && this._parent.getCompletedTransfers() == 0) {
this.refreshCourses();
this._parent.fireEvent('heightModified');
this.fireEvent('refreshPrice');
} else {
this.refreshCourses();
this._parent.fireEvent('heightModified');
}
},
/**
* Replace a course with another one
*
* @param SchoolCourseObject oldCourse The course we want to replace
* @param Object newCourse The new Course DTO
* @param Object oldCourseValues The old course values
*/
replaceCourse : function(oldCourse, newCourse, oldCourseValues) {
var i = this._courses.indexOf(oldCourse);
switch (newCourse.type) {
case 'fixedDate' :
var replaceCourse = new SchoolFixedCourseObject(newCourse, this._translateDTO.courseObject, this._listContainer, this._classNameBase,  this);
this._courses[i] = replaceCourse;
replaceCourse.createVisualCourse();
oldCourse.getHtml().replaceWith(replaceCourse.getHtml());
replaceCourse.addEvent('deleteCourse', function(e) {
this.deleteCourse(replaceCourse);
}.bind(this));
if (oldCourseValues) {
this._courses[i].refreshFixedCourseData(this._courses[i].getNewFixedCourseDates(oldCourseValues));
} else {
this._courses[i].refreshLists();
}
break;
case 'variableDate' :
var replaceCourse = new SchoolVariableCourseObject(newCourse, this._translateDTO.courseObject, this._listContainer, this._classNameBase,  this);
this._courses[i] = replaceCourse;
replaceCourse.createVisualCourse();
oldCourse.getHtml().replaceWith(replaceCourse.getHtml());
replaceCourse.addEvent('deleteCourse', function(e) {
this.deleteCourse(replaceCourse);
}.bind(this));
if (oldCourseValues) {
this._courses[i].replaceVariableCourseDates(oldCourseValues.startDate, oldCourseValues.duration);
} else {
this._courses[i].refreshLists();
}
break;
case 'optional' :
var replaceCourse = new SchoolOptionalCourseObject(newCourse, this._translateDTO.courseObject, this._listContainer, this._classNameBase,  this);
this._courses[i] = replaceCourse;
replaceCourse.createVisualCourse();
oldCourse.getHtml().replaceWith(replaceCourse.getHtml());
replaceCourse.addEvent('deleteCourse', function(e) {
this.deleteCourse(replaceCourse);
}.bind(this));
if (oldCourseValues) {
this._courses[i].replaceOptionalCourseDates(oldCourseValues.startDate, oldCourseValues.duration);
} else {
this._courses[i].refreshLists();
}
break;
}
this._courses[i].addEvent('refreshPrice', this.refreshPrice.bind(this));
this._parent.fireEvent('heightModified');
},
refreshPrice : function(){
this.fireEvent('refreshPrice');
},
/**
* Returns True if the course given in parameter is a fixed course
*
* @param Object course The course DTO
*
* @return Boolean Returns true if the course given in parameter is a fixed course
*/
getIsFixedCourse : function(course) {
return course.type == 'fixedDate';
},
/**
* Returns all the courses stocked in the DTO
*
* @return Array An array containing all the courses
*/
getCourses : function() {
var validCourses = new Array();
// retrieving the valid fixed courses
this._schoolFixedCoursesDTO.each(function(item, index) {
validCourses.include(item);
});
// retrieving the variable courses
this._schoolVariableCoursesDTO.each(function(item, index) {
validCourses.include(item);
});
return validCourses;
},
/**
* Returns all the optional courses stocked in the DTO
*
* @return Array An array containing all the courses
*/
getOptionalCourses : function() {
var validCourses = new Array();
// retrieving the valid optional courses
this._schoolOptionalCoursesDTO.each(function(item, index) {
validCourses.include(item);
});
return validCourses;
},
/**
* This method returns the number of completed courses
*
* @return SchoolCourseObject The courses completed
*
*/
getCompletedCourses : function() {
var completedCourses = new Array();
if (this._courses.length) {
this._courses.each(function(item, index) {
if (item.isComplete()) {
completedCourses.push(item);
}
});
}
return completedCourses;
},
/**
* Returns all the courses added in the cart
*
* @return Array An array containing all the courses
*/
getAddedCourses : function() {
return this._courses;
},
/**
* Return all the valid courses added in the cart
*
* @param Array An array containing all the courses
*/
getValidAddedCourses : function(bIgnoreOptional) {
var validCourses = new Array();
for (var i = 0; i < this._courses.length; i++) {
if (this._courses[i].isComplete()) {
if(!bIgnoreOptional || this._courses[i].getCourseDetails().type != 'optional'){
validCourses.push(this._courses[i]);
}
}
}
return validCourses;
},
/**
* Returns the valid courses for a given period based on a courseObject
*
* @param SchoolCoursesObject course The course object, if empty we consider that we want to add a new course
*
* @return Array An array of course ID (by default the one that is given in parameter)
*/
getValidCourses : function(course, optionalCourse) {
var startDate = new Date();
var endDate = new Date(startDate.getFullYear() + 10, startDate.getMonth(), startDate.getDate());
var validCourses = new Array();
// initializing the start and end dates
// if we want to add a new course
if (!course) {
if (this._courses.length > 0 && this._courses.getLast()._courseEndDate) {
startDate = this._courses.getLast()._courseEndDate;
}
// if we want to replace a course
} else {
// if the course is not the last one and there are more than one course
if (course != this._courses.getLast() && this._courses.length > 1) {
if (this._courses[this._courses.indexOf(course) + 1]._courseStartDate)endDate = this._courses[this._courses.indexOf(course) + 1]._courseStartDate;
}
// if this courses is not the first
if (this._courses.indexOf(course) > 0) {
if (this._courses[this._courses.indexOf(course) - 1]._courseEndDate)startDate = this._courses[this._courses.indexOf(course) - 1]._courseEndDate;
}
}
if (!optionalCourse) {
// retrieving the valid fixed courses
this._schoolFixedCoursesDTO.each(function(item, index) {
var courseItem = item;
item.sessions.each(function(item, index) {
//alert(item.courseStartDate);
if (item.courseStartDate >= startDate && item.courseEndDate <= endDate) {
validCourses.include(courseItem);
}
});
});
// retrieving the valid variable courses
this._schoolVariableCoursesDTO.each(function(item, index) {
var itemDuration = item.duration[0];
var courseItem = item;
item.startDates.each(function(item, index) {
var itemEndDate = new Date(item.getFullYear(), item.getMonth(), item.getDate() + itemDuration * 7);
if (item >= startDate && itemEndDate <= endDate) {
validCourses.include(courseItem);
}
}.bind(this));
}, this);
} else {
// retrieving the valid optional courses
this._schoolOptionalCoursesDTO.each(function(item, index) {
// need to recalulcate the start date for the optional courses
var completedCourses = this.getCompletedCourses();
if (completedCourses.length) {
var startDate = completedCourses[0].getCourseStartDate();
} else {
var startDate = new Date();
}
for (var i = 0; i < completedCourses.length; i++) {
if (completedCourses[i].getCourseDetails().availableOptionalCourses && completedCourses[i].getCourseDetails().availableOptionalCourses.contains(parseInt(item.id))) {
startDate = completedCourses[i].getCourseStartDate();
break;
}
}
var itemDuration = parseInt(item.duration[0]);
var courseItem = item;
item.startDates.each(function(itemStartDate, index) {
var itemEndDate = new Date(itemStartDate.getFullYear(), itemStartDate.getMonth(), (itemStartDate.getDate() + itemDuration * 7));
if (itemStartDate >= startDate && itemEndDate <= endDate) {
validCourses.include(courseItem);
}
}.bind(this));
}, this);
}
// if there is no course available and we are not on the add course list,
//  we just add the one that is already there
if (!validCourses.length && course) {
var courseItem = this._schoolVariableCoursesDTO.filter(function(item, index) {
return item.id == course._courseDetails.id;
}.bind(this));
if (!courseItem.length) {
courseItem = this._schoolFixedCoursesDTO.filter(function(item, index) {
return  item.id == course._courseDetails.id;
}.bind(this));
}
validCourses.include(courseItem[0]);
}
// sort the list
validCourses = validCourses.sort(this.sortFunction);
return validCourses;
},
/**
* function called to sort an array of valid courses
*
* @param courseDTO a The first course to compare
* @param courseDTO b The second course to compare
*/
sortFunction : function(a, b) {
return a.position - b.position;
},
/**
* Returns the valid courses date session for a given period based on a courseObject
*
* @param SchoolCoursesObject course The course object, if empty we consider that we want to add a new course
*
* @return Array An array of validSessions
*/
getValidFixedCourseSession : function(course) {
var validSessions = new Array();
var startDate = new Date();
var endDate = new Date(startDate.getFullYear() + 10, startDate.getMonth(), startDate.getDate());
// if the course is not the last one and there are more than one course
if (course != this._courses.getLast() && this._courses.length > 1) {
for (var i = this._courses.indexOf(course) + 1; i < this._courses.length; i++) {
if (this._courses[i]._courseStartDate)endDate = this._courses[i]._courseStartDate;
}
}
// if this courses is not the first
if (this._courses.indexOf(course) > 0) {
for (var i = this._courses.indexOf(course) - 1; i >= 0; i--) {
if (this._courses[i].getCourseDetails().type != 'optional' && this._courses[i]._courseEndDate)startDate = this._courses[i]._courseEndDate;
}
}
// retrieve the valid sessions
course._courseDetails.sessions.each(function(item, index) {
if (item.courseStartDate >= startDate && item.courseEndDate <= endDate) {
validSessions.include(item);
}
}.bind(this));
return validSessions;
},
/**
* Returns the valid courses date session for a given period based on a courseObject
*
* @param SchoolCoursesObject course The course object, if empty we consider that we want to add a new course
*
* @return Array An Array of valid start date
*/
getValidVariableCourseStartDate : function(course) {
var validStartDates = new Array();
var startDate = new Date();
var endDate = new Date(startDate.getFullYear() + 10, startDate.getMonth(), startDate.getDate());
var minimalEndDate = '';
var duration = course._courseDuration;
var availabilities = course.getCourseDetails().availabilities;
if (!duration) {
duration = course._courseDetails.duration[0];
}
// if the course is not the last one and there are more than one course
if (course != this._courses.getLast() && this._courses.length > 1) {
for (var i = this._courses.indexOf(course) + 1; i < this._courses.length; i++) {
if (this._courses[i].getCourseDetails().type != 'optional' && this._courses[i]._courseStartDate)endDate = this._courses[i]._courseStartDate;
}
}
// if this courses is not the first
if (this._courses.indexOf(course) > 0) {
for (var i = 0; i < this._courses.indexOf(course); i++) {
if (this._courses[i].getCourseDetails().type != 'optional' && this._courses[i]._courseEndDate)startDate = this._courses[i]._courseEndDate;
}
}
course._courseDetails.startDates.each(function(item, index) {
// the minimal end date is the date minus the minimal course duration
minimalEndDate = new Date(item.getFullYear(), item.getMonth(), item.getDate() + 7 * duration);
if (item >= startDate && minimalEndDate <= endDate) {
var year = item.getFullYear();
var week = item.getWeek();
if (course.getCourseDetails().courseStartDay == 7) {
if (week > 1)week = week + 1;
}
// check the availabilities for this start date
var toAdd = true;
if (availabilities) {
for (var i = 0; i < duration; i++) {
if (week > 52) {
var lastWeek = (new Date(item.getFullYear(), 12, 31)).getWeek();
if (week < lastWeek) {
week = week - lastWeek;
year = year + 1;
}
}
if (availabilities[year + '' + week] == 0) {
toAdd = false;
}
week++;
}
}
if (toAdd) {
validStartDates.push(item);
}
}
}.bind(this));
return validStartDates;
},
/**
* Returns the valid courses date session for a given period based on a courseObject
*
* @param SchoolCoursesObject course The course object, if empty we consider that we want to add a new course
*
* @return Array An Array of valid start date
*/
getValidOptionalCourseStartDate : function(course) {
var validStartDates = new Array();
var periods = new Array();
var sameCoursesPeriods = new Array();
var addedCourses = this.getValidAddedCourses();
var sameCourses = new Array();
var availabilities =  course.getCourseDetails().availabilities;
var additionalDays = course.getCourseDetails().additionalDays;
// check every course to calculate the start date and end date validity
for (var i = 0; i < addedCourses.length; i++) {
if (addedCourses[i].getCourseDetails().type != 'optional' && addedCourses[i].getCourseDetails().availableOptionalCourses.contains(parseInt(course.getCourseDetails().id))) {
var period = new Object();
period.startDate = (new Date()).fromIso(addedCourses[i].getDTO().startDate);
period.endDate = (new Date()).fromIso(addedCourses[i].getDTO().endDate);
if(additionalDays){
period.endDate.setDate(period.endDate.getDate() + additionalDays);
}
periods.push(period);
}
if (addedCourses[i].getCourseDetails().type == 'optional' && addedCourses[i].getCourseDetails().id == course.getCourseDetails().id && addedCourses[i] != course) {
sameCourses.push(addedCourses[i]);
}
}
if (sameCourses.length) {
for (var i = 0; i < sameCourses.length; i++) {
var period = new Object();
period.startDate = sameCourses[i]._courseStartDate;
period.endDate = sameCourses[i]._courseEndDate;
sameCoursesPeriods.push(period);
}
}
var minimalEndDate = '';
var duration = course._courseDuration;
if (!duration) {
duration = course._courseDetails.duration[0];
}
course._courseDetails.startDates.each(function(item, index) {
// check if the same courses is already added
var toAdd = true;
if (sameCoursesPeriods.length) {
for (var j = 0; j < sameCoursesPeriods.length; j++) {
if ((item >= sameCoursesPeriods[j].startDate && item <= sameCoursesPeriods[j].endDate)) {
toAdd = false;
}
}
}
if (toAdd) {
// the minimal end date is the date minus the minimal course duration
if(course.getCourseDetails().oneDayCourse){
minimalEndDate = new Date(item.getFullYear(), item.getMonth(), item.getDate());
} else {
minimalEndDate = new Date(item.getFullYear(), item.getMonth(), item.getDate() + 7 * duration);
}
minimalEndDate = course.getOptionalCourseEndDate(minimalEndDate);
for (var i = 0; i < periods.length; i++) {
if (item >= periods[i].startDate && minimalEndDate <= periods[i].endDate) {
var year = item.getFullYear();
var week = item.getWeek();
if (course.getCourseDetails().courseStartDay == 7) {
if (week > 1)week = week + 1;
}
// check the availabilities for this start date
var toAdd = true;
if (availabilities) {
for (var i = 0; i < duration; i++) {
if (week > 52) {
var lastWeek = (new Date(item.getFullYear(), 12, 31)).getWeek();
if (week < lastWeek) {
week = week - lastWeek;
year = year + 1;
}
}
if (availabilities[year + '' + week] == 0) {
toAdd = false;
}
week++;
}
}
// if the item can be added
if (toAdd) {
validStartDates.include(item);
break;
}
}
}
}
}.bind(this));
return validStartDates;
},
/**
* Returns the valid courses date session for a given period based on a courseObject
*
* @param SchoolCoursesObject course The course object, if empty we consider that we want to add a new course
*
* @return Array An array of valid durations
*/
getValidOptionalCourseDuration : function(course) {
var validDurations = new Array();
var sameCoursesPeriods = new Array();
var addedCourses = this.getValidAddedCourses();
var sameCourses = new Array();
var periods = new Array();
var availabilities = course.getCourseDetails().availabilities;
var additionalDays = course.getCourseDetails().additionalDays;
if(addedCourses.length){
for (var i = 0; i < addedCourses.length; i++) {
if (addedCourses[i].getCourseDetails().type != 'optional' && addedCourses[i].getCourseDetails().availableOptionalCourses.contains(parseInt(course.getCourseDetails().id))) {
var period = new Object();
period.startDate = (new Date()).fromIso(addedCourses[i].getDTO().startDate);
period.endDate = (new Date()).fromIso(addedCourses[i].getDTO().endDate);
if(additionalDays){
period.endDate.setDate(period.endDate.getDate() + additionalDays);
}
periods.push(period);
}
if (addedCourses[i].getCourseDetails().type == 'optional' && addedCourses[i].getCourseDetails().id == course.getCourseDetails().id && addedCourses[i] != course) {
sameCourses.push(addedCourses[i]);
}
}
if (sameCourses.length) {
for (var i = 0; i < sameCourses.length; i++) {
var period = new Object();
period.startDate = sameCourses[i]._courseStartDate;
period.endDate = sameCourses[i]._courseEndDate;
sameCoursesPeriods.push(period);
}
}
var optionEndDate = '';
var week = -1;
var year = -1;
if (course.getCourseStartDate()) {
week = course.getCourseStartDate().getWeek();
year = course.getCourseStartDate().getFullYear();
if(course.getCourseDetails().courseStartDay== 7){
if(week > 1)week = week+1;
}
}
// for each duration
for (var i = 0; i < (course.getCourseDetails().duration.length); i++) {
var value = course.getCourseDetails().duration[i];
// check if there is an availability
if (week == -1 || !availabilities ||
availabilities[year + '' + (week + parseInt(value) - 1)] != 0) {
var toAdd = true;
// the minimal end date is the date minus the minimal course duration
if (course._courseStartDate) {
optionEndDate = new Date(course._courseStartDate.getFullYear(), course._courseStartDate.getMonth(), course._courseStartDate.getDate() + 7 * value);
optionEndDate = course.getOptionalCourseEndDate(optionEndDate);
} else {
optionEndDate = new Date(periods[0].startDate.getFullYear(), periods[0].startDate.getMonth(), periods[0].startDate.getDate() + 7 * value);
}
// check each periods of courses it can be attached
for (var j = 0; j < periods.length; j++) {
if (course._courseStartDate >= periods[j].startDate && optionEndDate <= periods[j].endDate || !course._courseStartDate) {
// and check the end date meets the right range.
for (var k = 0; k < sameCoursesPeriods.length; k++) {
if (optionEndDate >= sameCoursesPeriods[k].startDate && optionEndDate < sameCoursesPeriods[k].endDate) {
toAdd = false;
}
}
if (toAdd) {
validDurations.include(value);
break;
}
}
}
// if there is no more availability, the valid durations stops here
}else{
break;
}
}
}
return validDurations;
},
/**
* Returns the valid courses date session for a given period based on a courseObject
*
* @param SchoolCoursesObject course The course object, if empty we consider that we want to add a new course
*
* @return Array An array of valid durations
*/
getValidVariableCourseDuration : function(course) {
var validDurations = new Array();
var startDate = new Date();
var endDate = new Date(startDate.getFullYear() + 10, startDate.getMonth(), startDate.getDate());
var calculatedEndDate;
var availabilities = course.getCourseDetails().availabilities;
// if the course is not the last one and there are more than one course
if (course != this._courses.getLast() && this._courses.length > 1) {
for (var i = this._courses.indexOf(course) + 1; i < this._courses.length; i++) {
if (this._courses[i].getCourseDetails().type != 'optional' && this._courses[i]._courseStartDate)endDate = this._courses[i]._courseStartDate;
}
}
// if this courses is not the first
if (this._courses.indexOf(course) > 0) {
for (var i = this._courses.indexOf(course) - 1; i >= 0; i--) {
if (this._courses[i]._courseEndDate)startDate = this._courses[i]._courseEndDate;
}
}
var week = -1;
var year = -1;
if (course.getCourseStartDate()) {
week = course.getCourseStartDate().getWeek();
year = course.getCourseStartDate().getFullYear();
if(course.getCourseDetails().courseStartDay == 7){
if(week > 1)week = week+1;
}
}
// find the default start date, usefull when the start date is not the same as the course information one
if(course.getCourseStartDate()){
var defaultCourseStartDate = new Date(course.getCourseStartDate());
// if the course start day is not the same as the given in the course informations
if (defaultCourseStartDate && course.getCourseDetails().courseStartDay && course.getCourseDetails().courseStartDay !=  defaultCourseStartDate.getDay()) {
var courseStartDayUp = (defaultCourseStartDate.getDay() == 0 ? 7 : defaultCourseStartDate.getDay());
var courseStartDayDown = courseStartDayUp;
var iter = 0;
while (course.getCourseDetails().courseStartDay != courseStartDayDown && course.getCourseDetails().courseStartDay != courseStartDayUp) {
if (courseStartDayDown == 0)courseStartDayDown = 7;
if (courseStartDayUp == 8)courseStartDayUp = 1;
courseStartDayDown--;
courseStartDayUp++;
iter++;
}
if (courseStartDayDown == course.getCourseDetails().courseStartDay) {
defaultCourseStartDate.setDate(defaultCourseStartDate.getDate() - iter);
} else {
defaultCourseStartDate.setDate(defaultCourseStartDate.getDate() + iter);
}
}
}
for (var i = 0; i < (course.getCourseDetails().duration.length); i++) {
var value = course.getCourseDetails().duration[i];
// the minimal end date is the date minus the minimal course duration
if (defaultCourseStartDate) {
calculatedEndDate = new Date(defaultCourseStartDate.getFullYear(), defaultCourseStartDate.getMonth(), defaultCourseStartDate.getDate() + 7 * value);
} else {
calculatedEndDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate() + 7 * value);
}
if (defaultCourseStartDate >= startDate && calculatedEndDate <= endDate || !defaultCourseStartDate) {
var currentYear = year;
var currentWeek = week;
if(currentWeek > 52){
currentWeek = currentWeek - 52;
currentYear = currentYear + 1;
}
if (currentWeek == -1 || !availabilities ||
availabilities[currentYear + '' + (currentWeek + parseInt(value) - 1)] != 0) {
validDurations.push(value);
} else {
break;
}
}
}
return validDurations;
},
/**
* Returns the accommodation start date
*
* @optionalparam AccommodationDTO accommodation The Accommodation DTO
*
* @return Date The  possible start date
*/
getAccommodationStartDate : function() {
var newDate = null;
this._courses.each(function(item, index) {
// check if the course is complete
if (item.isComplete()) {
// if it is a fixed Course
if (item.getIsFixedCourse()) {
// if this accommodation is available with this course
if (newDate > item._courseDetails.sessions[item._session].accommodationStartDate || newDate == null) {
newDate = new Date(item._courseDetails.sessions[item._session].accommodationStartDate);
}
// if it's a variable course
} else {
// if this accommodation is available with this course
// the new date is set
if (newDate > item._courseStartDate || newDate == null) {
newDate = new Date(item._courseStartDate);
}
}
}
}.bind(this));
return newDate;
},
/**
* Returns the maximal final date
*
* @return Date The end date for the accommodations
*/
getAccommodationEndDate : function() {
var endDate = new Date();
if (this._courses.length) {
for (var i = 0; i < this._courses.length; i++) {
if (this._courses[i].getCourseDetails().type != 'optional' && this._courses[i].isComplete()) {
if (this._courses[i].getIsFixedCourse()) {
endDate = new Date(this._courses[i]._courseDetails.sessions[this._courses[i]._session].accommodationEndDate);
} else {
endDate = new Date(this._courses[i]._courseEndDate);
}
}
}
}
return endDate;
},
/**
*  Returns the available accommodations
*
* @return Array of integer The Accommodation IDs
*/
getAvailableAccommodations : function() {
var availableAccommodations = new Array();
for (var i = 0; i < this._courses.length; i++) {
if (this._courses[i].getCourseDetails().type != 'optional') {
availableAccommodations = availableAccommodations.merge(this._courses[i].getAvailableAccommodations());
}
}
return availableAccommodations;
},
/**
* Return an array containing the mandatory accommodations with their start and end date
*
* @return Array of MandatoryAccommodationsDTO
*/
getMandatoryAccommodations : function() {
var mandatoryAccommodations = new Array();
for (var i = 0; i < this._courses.length; i++) {
if (this._courses[i].getCourseDetails().type != 'optional' && this._courses[i].getCourseDetails().accommodationMandatory == true) {
var mandatoryAccommodation = new Object();
mandatoryAccommodation.courseId = this._courses[i].getCourseDetails().id;
mandatoryAccommodation.ids = this._courses[i].getCourseDetails().availableAccommodations;
mandatoryAccommodation.startDate = this._courses[i].getDTO().startDate;
mandatoryAccommodation.endDate = this._courses[i].getDTO().endDate;
mandatoryAccommodations.push(mandatoryAccommodation);
}
}
return mandatoryAccommodations;
},
/**
* Return true if the transfer is mandatory
*
* @return boolean true if the transfers are mandatory
*/
getIsTransferMandatory : function() {
var mandatory = false;
for (var i = 0; i < this._courses.length; i++) {
if (this._courses[i].getCourseDetails().type != 'optional' && this._courses[i].getCourseDetails().transferMandatory == true) {
mandatory = true;
}
}
return mandatory;
},
/**
* Display or hide the optional course add button
*
* @param boolean isDisplayed True to display the hide button
*/
displayAddButton : function(isDisplayed){
if (this._optionalCourseAddButton) {
if (isDisplayed) {
this._optionalCourseAddButton.setStyle('display', 'block');
} else {
this._optionalCourseAddButton.setStyle('display', 'none');
}
}
},
/**
* Returns the parent of this object
*
* @return SchoolPriceEstimation The parent object
*/
getParent : function() {
return this._parent;
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param TransferListItemDTO schoolTransfersDTO the transfers informations
* @param SchoolPriceEstimation parent the parent
**/
var SchoolCurrencySelector = Events.extend({
/**
* This is the initialization function
* @param TranslateDTO translateDTO The DTO containing the translations
* @param String defaultCurrency The default currency
* @param Array currenciesList An array containing all the currencies
* @param Object parent The parent
*/
initialize : function(translateDTO, defaultCurrency, currenciesList,parent) {
this._translateDTO = translateDTO;
this._parent = parent;
this._classNameBase = this._parent.getClassNameBase();
this._currencyAvailableList = currenciesList;
this._currency = defaultCurrency;
},
/**
* return the visual transfer container
*/
getHtml : function() {
this._currencyContainer = new Element('div', {'class': this._classNameBase + 'Currency-Section'});
this._currencyTitle = new Element('div', {'class': this._classNameBase + 'Currency-Section-Title'});
this._currencyTitleText = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title-Text'});
this._currencyTitleText.injectInside(this._currencyTitle);
this._currencyButtons = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._currencyButtons.addClass( this._classNameBase + 'CurrencyButton');
this._currencyTitle.injectInside(this._currencyContainer);
//        this._currencyButtons.injectInside(this._currencyContainer);
this._currencyTitleText.setHTML(this._translateDTO.title);
this._currencyButtons.setHTML(this._currency);
this._currencyButtons.injectInside(this._currencyTitle);
this._currencyList = new SchoolList(this._currencyButtons, this._classNameBase);
this.createVisualList(this._currencyList);
this._currencyList.getHtml().injectInside(this._parent.getListContainer());
this._currencyList.initializeEvents();
return this._currencyContainer;
},
/**
* Generate the list of currency
*
* @param SchoolList list The list to update
*/
createVisualList : function(list) {
for (var i = 0; i < this._currencyAvailableList.length; i++) {
list.addItem(this._currencyAvailableList[i].currencyCode, this._currencyAvailableList[i].currencyName + " (" + this._currencyAvailableList[i].currencyCode  + ")");
}
list.getListItems().each(function(item, index) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (item.getValue() == this._currency) {
this._currencyButtons.setHTML(item.getHtmlValue());
list.setSelectedItem(item);
}
item.getHtml().addEvent('click', function(event) {
this._currencyButtons.setHTML(item.getHtmlValue());
this._currency = item.getValue();
this._parent.fireEvent('refreshPrice');
list.setSelectedItem(item);
}.bind(this));
}.bind(this));
},
/**
* Returns the number of currency
*
* @return number The number of currency
*/
getCurrency : function() {
return this._currency;
},
/**
* Set the currency
*
* @param String currency the currency code to use
*/
setCurrency : function(currency){
this._currency  = currency;
this._currencyButtons.setHTML(currency);
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @event Event deleteCourse This event is fired when a course is deleted
*
* @param FixedDatesCourseListItemDTO courseDetails The object containing the course informations
* @param Object translateDTO The object containing all the translations for this class
* @param SchoolCourses parent The parent
*
**/
var SchoolFixedCourseObject = Events.extend({
/**
* This is the initialization function
*/
initialize : function(courseDetails, translateDTO, listContainer, classNamePrefix ,parent) {
this._translateDTO = translateDTO;
this._courseDetails = courseDetails;
this._parent = parent;
this._listContainer = listContainer;
this._classNameBase = classNamePrefix;
this._dateFormat = this._parent.getParent().getDateFormat();
this._monthsTranslations = this._parent.getParent().getMonthTranslations();
this._courseStartDate = null;
this._courseEndDate = null;
this._courseDuration = null;
this._manager = this._parent.getParent().getParent();
this._manager.addEvent('descriptionsUpdated', function(){
this.updateDescriptions();
}.bind(this));
},
/**
* Return the course details DTO
*
* @return CourseDetailsDTO The course Details DTO
*/
getCourseDetails : function() {
return this._courseDetails;
},
/**
* Returns true if the course is complete
*
* @return boolean true if the course is complete
*/
isComplete : function() {
if (this._courseStartDate && this._courseEndDate && this._courseDuration) {
return true;
} else {
return false;
}
},
/**
* Generate the html structure of the course
* and add an event on the delete button
*
*/
createVisualCourse : function() {
this._container = new Element('div', {'class': this._classNameBase + 'ItemAdded'});
this._title = new Element('div', {'class': this._classNameBase + 'Section-Item-Title'});
this._subTitle = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle'});
this._moreInfo = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle MoreInfos'});
this._moreInfo.setStyle('display','none');
this._startDateContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-StartDate-Container'});
this._endDateContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-EndDate-Container'});
this._startDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._startDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value ' + this._classNameBase + 'Section-Item-ToUpdate'});
this._endDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._endDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-ValueNotEditable'});
this._durationDateContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-Duration-Container'});
this._duration = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._durationValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-ValueNotEditable'});
this._deleteButton = new Element('div', {'class': this._classNameBase + 'Section-Item-DeleteButton'});
this._duration.injectInside(this._durationDateContainer);
this._durationValue.injectInside(this._durationDateContainer);
this._startDate.injectInside(this._startDateContainer);
this._startDateValue.injectInside(this._startDateContainer);
this._endDate.injectInside(this._endDateContainer);
this._endDateValue.injectInside(this._endDateContainer);
this._title.injectInside(this._container);
this._subTitle.injectInside(this._container);
this._moreInfo.injectInside(this._container);
new Element('div',{'style':'clear:both'}).injectInside(this._container);
this._startDateContainer.injectInside(this._container);
this._endDateContainer.injectInside(this._container);
this._durationDateContainer.injectInside(this._container);
this._deleteButton.injectInside(this._container);
new Element('div',{'style':'clear:both'}).injectInside(this._container);
this._title.setHTML(this._courseDetails.name);
this._subTitle.setHTML(this._courseDetails.subtitle);
this._moreInfo.setHTML(this._translateDTO.moreInfos);
this._startDate.setHTML(this._translateDTO.startDate);
this._startDateValue.setHTML(this._translateDTO.dateSelect);
this._endDate.setHTML(this._translateDTO.endDate);
this._endDateValue.setHTML(this._translateDTO.endDateValue);
this._duration.setHTML(this._translateDTO.duration);
this._durationValue.setHTML(this._translateDTO.durationSelect);
this._deleteButton.setHTML(this._translateDTO.deleteButton);
// add event listener
this._deleteButton.addEvent('click', function(e) {
this.removeCourse();
this.fireEvent('deleteCourse');
}.bind(this));
this.updateDescriptions();
this._coursesValidList = new SchoolList(this._title, this._classNameBase);
this.getVisualValidCoursesList(this._coursesValidList);
this._coursesValidList.getHtml().injectInside(this._listContainer);
this._coursesValidList.initializeEvents();
this._schoolSessionsList = new SchoolList(this._startDateValue, this._classNameBase);
this.getVisualFixedCourseStartDates(this._courseDetails.sessions, this._schoolSessionsList);
this._schoolSessionsList.getHtml().injectInside(this._listContainer);
this._schoolSessionsList.initializeEvents();
this.refreshLists();
},
/**
* Returns the html Element of this course
*
* @return Element The Html view of this course
*/
getHtml : function() {
return this._container;
},
updateDescriptions : function(){
if (this._manager.getDescription && this._manager.getDescription('course', this._courseDetails.courseTypeId) && this._manager.getDescription('course', this._courseDetails.courseTypeId) != '') {
this._moreInfo.setAttribute('title', this._courseDetails.name + ' :: ' + this._manager.getDescription('course', this._courseDetails.courseTypeId));
this._moreInfo.setStyle('display','');
if(!this._descriptionToolTip ){
this._descriptionToolTip = new SynergeeTips(this._moreInfo, {'className':'PriceEstimationToolTip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
}else {
this._descriptionToolTip.build(this._moreInfo);
}
}else {
this._moreInfo.setStyle('display','none');
}
},
/**
* return the course start date
*
* @return Date The course start date
*/
getCourseStartDate : function() {
return this._courseStartDate;
},
/**
* return the course start date
*
* @return Date The course start date
*/
getCourseEndDate : function() {
return this._courseEndDate;
},
/**
* return the accommodation end date for this course
*
* @return Date The accommodation end date date
*/
getAccommodationEndDate : function() {
return this._courseDetails.sessions[this._session].accommodationEndDate;
},
/**
* Returns an object containing the informations for the calculation price
*
* @return Object The informations needed to calculate the price
*/
getDTO : function() {
var courseDTO = new Object();
courseDTO.id = this._courseDetails.id;
courseDTO.startDate = this._courseStartDate.toIso();
courseDTO.endDate = this._courseEndDate.toIso();
return courseDTO;
},
/**
* Populate the fixed course from a dto
*
* @param Object The fixed course informations needed to populate
*/
populateFromDTO : function(toPopulateDTO) {
var courseInfos = new Object();
courseInfos.courseStartDate = (new Date()).fromIso(toPopulateDTO.startDate);
courseInfos.courseEndDate = (new Date()).fromIso(toPopulateDTO.endDate);
// Set the variables for this course
this._courseStartDate = courseInfos.courseStartDate;
this._courseEndDate = courseInfos.courseEndDate;
this._courseDuration = this.getCalculatedDuration(courseInfos.courseStartDate, courseInfos.courseEndDate);
// set the visual data of this course
this._startDateValue.setHTML(courseInfos.courseStartDate.format(this._dateFormat, this._monthsTranslations));
this._endDateValue.setHTML(courseInfos.courseEndDate.format(this._dateFormat, this._monthsTranslations));
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
// if the session hasn't been found (when the course is populated)
this._courseDetails.sessions.each(function(item, index) {
if (item.courseStartDate.format(this._dateFormat, this._monthsTranslations) == courseInfos.courseStartDate.format(this._dateFormat, this._monthsTranslations)) {
this._session = index;
}
}.bind(this));
},
/**
* Refresh all the lists of this course
*
*/
refreshLists : function() {
this.refreshVisualValidCoursesList(this._coursesValidList);
this.refreshVisualFixedCourseStartDates(this._parent.getValidFixedCourseSession(this), this._schoolSessionsList);
if(this._schoolSessionsList.getValidListItems().length == 1 ){
this._startDateValue.addClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-Info-Value');
this._schoolSessionsList.removeButtonEvent();
if(this._courseStartDate != this._schoolSessionsList.getValidListItems()[0].getValue().courseStartDate
|| this._courseEndDate != this._schoolSessionsList.getValidListItems()[0].getValue().courseEndDate)this._schoolSessionsList.getValidListItems()[0].getHtml().fireEvent('click');
}else{
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._startDateValue.addClass(this._classNameBase + 'Section-Item-Info-Value');
this._schoolSessionsList.addButtonEvent();
}
},
/**
* Regenerate all the lists of this course
*
*/
reGenerateLists : function() {
// remove old list if exists
if (this._coursesValidList.getListItems().length) {
this._coursesValidList.getHtml().remove();
this._coursesValidList.clear();
}
if (this._schoolSessionsList.getListItems().length) {
this._schoolSessionsList.getHtml().remove();
this._schoolSessionsList.clear();
}
// add the list of courses that fit the start and end Date
this.getVisualValidCoursesList(this._coursesValidList);
this._coursesValidList.getHtml().injectInside(this._listContainer);
this._coursesValidList.initializeEvents();
this.getVisualFixedCourseStartDates(this._courseDetails.sessions, this._schoolSessionsList);
this.refreshVisualFixedCourseStartDates(this._parent.getValidFixedCourseSession(this), this._schoolSessionsList);
this._schoolSessionsList.getHtml().injectInside(this._listContainer);
this._schoolSessionsList.initializeEvents();
},
/**
* Refresh the values when the user change a course information
*
* @param Object values The new values
*/
refreshFixedCourseData : function(values) {
// Set the variables for this course
this._courseStartDate = values.courseStartDate;
this._courseEndDate = values.courseEndDate;
this._courseDuration = this.getCalculatedDuration(values.courseStartDate, values.courseEndDate);
// set the visual data of this course
this._startDateValue.setHTML(values.courseStartDate.format(this._dateFormat, this._monthsTranslations));
this._endDateValue.setHTML(values.courseEndDate.format(this._dateFormat, this._monthsTranslations));
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
// set the session number
this._session = this._courseDetails.sessions.indexOf(values);
// if the session hasn't been found (when the course is populated)
if (this._session == -1) {
this._courseDetails.sessions.each(function(item, index) {
if (item.courseStartDate.format(this._dateFormat, this._monthsTranslations) == values.courseStartDate.format(this._dateFormat, this._monthsTranslations)) {
this._session = index;
}
}.bind(this));
}
// refresh the valid course list for this period
if (this.isComplete()) {
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._parent.fireEvent('refreshCourses');
this._parent.fireEvent('refreshPrice');
}
},
/**
* Replace the courses and find the best possible dates
*
* @param Number newCourseId  The new course ID
*/
replaceCourse : function(newCourse) {
this._durationValue.removeClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
if (this._parent.getIsFixedCourse(newCourse)) {
if (this.isComplete()) {
this._courseDetails = newCourse;
this._durationValue.addClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this.refreshFixedCourseData(this.getNewFixedCourseDates(this._courseStartDate));
this._title.setHTML(this._courseDetails.name);
this._subTitle.setHTML(this._courseDetails.subtitle);
this.reGenerateLists();
this._parent.fireEvent('refreshCourses');
} else {
this._schoolSessionsList.getHtml().remove();
this._coursesValidList.getHtml().remove();
this._parent.replaceCourse(this, newCourse);
}
} else {
this._schoolSessionsList.getHtml().remove();
this._coursesValidList.getHtml().remove();
if (this.isComplete()) {
var values = new Object();
values.startDate = this._courseStartDate;
values.duration = this._courseDuration;
this._parent.replaceCourse(this, newCourse, values);
} else {
this._parent.replaceCourse(this, newCourse);
}
}
},
/**
* Returns the best dates for the new fixed courses based on the old one
*
* @param Date oldStartDate The date of the replaced course
*
* @return Object The new dates session.
*/
getNewFixedCourseDates : function(oldStartDate) {
if (oldStartDate) {
var dateDifference;
var newDates;
this._courseDetails.sessions.each(function(item, index) {
if (dateDifference > Math.abs(oldStartDate - item.courseStartDate) || !dateDifference) {
dateDifference = Math.abs(oldStartDate - item.courseStartDate);
newDates = item;
}
}.bind(this));
return newDates;
}
},
/**
* Set a list of valid courses
*
* @param SchoolList list The valid courses list
*
*/
getVisualValidCoursesList : function(list) {
var validCourses = this._parent.getCourses();
// clearing the list
list.clear();
validCourses.each(function(item, index) {
list.addItem(item, item.name);
list.getListItems().getLast().getHtml().addClass(this._classNameBase + 'List-Item');
list.getListItems().getLast().getHtml().addEvent('click', function() {
this.replaceCourse(item);
}.bind(this));
}, this);
this.refreshVisualValidCoursesList(list);
},
/**
* Refresh a list of course that have possible dates between this courseStartDate and courseEndDate
*
* @param SchoolList list The valid courses list
*
*/
refreshVisualValidCoursesList : function(list) {
var validCourses = this._parent.getValidCourses(this);
list.getListItems().each(function(item, index) {
if (validCourses.indexOf(item.getValue()) != -1) {
item.setIsValid(true);
} else {
item.setIsValid(false);
}
}.bind(this));
},
/**
* Generate a formated list from an array of a fixed course start dates
*
* @param Array startDates An array of Date containing all the possible startDates
* @param SchoolList list The valid courses list
*/
getVisualFixedCourseStartDates : function(startDates, list) {
var firstValid = true;
var index = 0;
// clearing the list
list.clear();
startDates.each(function(item, index) {
list.addItem(item, item.courseStartDate.format(this._dateFormat, this._monthsTranslations));
index = list.getListItems().indexOf(list.getListItems().getLast());
list.getListItems().getLast().getHtml().addEvent('click', function() {
if (list.getListItems()[index].getIsSelectionnable())this.refreshFixedCourseData(item);
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.noValidStartDates);
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Refresh a list from an array of a fixed course start dates
*
* @param Array validStartDates An array of Date containing the validated startDates
* @param SchoolList list The valid courses list
*/
refreshVisualFixedCourseStartDates : function(validStartDate, list) {
var firstValid = true;
list.getListItems().each(function(item, index) {
if (validStartDate.indexOf(item.getValue()) != -1) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (firstValid)list.setSelectedItem(item);
if (this._courseStartDate == item.getValue().courseStartDate) list.setSelectedItem(item);
firstValid = false;
} else {
if (item.getValue == 'error')item.setIsValid(false);
item.setIsSelectionnable(false);
}
}.bind(this));
},
/**
* Return the duration in weeks.
* To perform the calculation we count the number of time the week day of the start date
* can be repeated between the start date and the end date.
*
* @param date startDate The start date
* @param date endDate The end date
* @return integer the number of weeks
*/
getCalculatedDuration : function(startDate, endDate) {
startDate = startDate.getTime();
endDate = endDate.getTime() - (86400 * 3 *1000) ;
var numberOfWeeks = 0;
while (startDate <= endDate) {
numberOfWeeks++;
startDate += (86400 * 7 * 1000);
}
return numberOfWeeks;
},
/**
*  Returns the available accommodations for this course
*
* @return Array of integer The Accommodation IDs
*/
getAvailableAccommodations : function() {
return this._courseDetails.availableAccommodations;
},
/**
*  return the course duration
*
* @return integer The course duration
*/
getCourseDuration : function() {
return this._courseDuration;
},
/**
* Returns true if it's a fixed course
*
* @return Boolean Return true because it's a fixed course
*/
getIsFixedCourse : function() {
return true;
},
/**
* This function remove the course from the list
*
*/
removeCourse : function() {
this._schoolSessionsList.getHtml().remove();
this._coursesValidList.getHtml().remove();
this._container.remove();
}
});
/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param number id the insurance ID
* @param char name the insurance name
* @param SchoolInsurances parent
**/
var SchoolInsuranceObject = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, insuranceDTO, translateDTO, parent) {
this._translateDTO = translateDTO;
this._insuranceDTO = insuranceDTO;
this._insuranceName = this._insuranceDTO.name;
this._type = this._insuranceDTO.type;
this._insuranceId = id;
this._parent = parent;
this._classNameBase = this._parent.getClassNameBase();
this._isMandatory = false;
this._insuranceStartDate = null;
this._insuranceEndDate = null;
this._insuranceDuration = null;
this._manager = this._parent.getParent();
this._manager.addEvent('descriptionsUpdated', function() {
this.updateDescriptions();
}.bind(this));
},
/**
* Generate the Html structure of this insurance
*/
createVisualInsurance : function() {
this._container = new Element('div', {'class': this._classNameBase + 'ItemAdded'});
this._title = new Element('div', {'class': this._classNameBase + 'Section-Item-Title'});
this._moreInfo = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle MoreInfos'});
this._moreInfo.setStyle('display', 'none');
this._startDateContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-StartDate-Container'});
this._endDateContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-EndDate-Container'});
this._startDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._startDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-ValueNotEditable'});
this._endDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._endDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-ValueNotEditable'});
this._durationContainer = new Element('div', {'class': this._classNameBase + 'Section-Item-Duration-Container'});
this._duration = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._durationValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-ValueNotEditable'});
this._deleteButton = new Element('div', {'class': this._classNameBase + 'Section-Item-DeleteButton'});
this._duration.injectInside(this._durationContainer);
this._durationValue.injectInside(this._durationContainer);
this._startDate.injectInside(this._startDateContainer);
this._startDateValue.injectInside(this._startDateContainer);
this._endDate.injectInside(this._endDateContainer);
this._endDateValue.injectInside(this._endDateContainer);
this._title.injectInside(this._container);
this._moreInfo.injectInside(this._container);
new Element('div', {'style':'clear:both'}).injectInside(this._container);
this._startDateContainer.injectInside(this._container);
this._endDateContainer.injectInside(this._container);
this._durationContainer.injectInside(this._container);
this._deleteButton.injectInside(this._container);
new Element('div', {'style':'clear:both'}).injectInside(this._container);
this._title.setHTML(this._insuranceName);
this._startDate.setHTML(this._translateDTO.startDate);
this._moreInfo.setHTML(this._translateDTO.moreInfos);
this._startDateValue.setHTML(this._translateDTO.dateSelect);
this._endDate.setHTML(this._translateDTO.endDate);
this._endDateValue.setHTML(this._translateDTO.endDateValue);
this._duration.setHTML(this._translateDTO.duration);
this._durationValue.setHTML(this._translateDTO.durationSelect);
this._deleteButton.setHTML(this._translateDTO.deleteButton);
// add event listener
this._deleteButton.addEvent('click', function(e) {
this.removeInsurance();
this.fireEvent('deleteInsurance');
}.bind(this));
this.updateDescriptions();
this._insuranceList = new SchoolList(this._title, this._classNameBase);
this.getVisualInsuranceList(this._insuranceList);
this._insuranceList.getHtml().injectInside(this._parent.getParent().getListContainer());
this._insuranceList.initializeEvents();
},
getInsuranceInformations : function() {
return this._insuranceDTO;
},
updateDescriptions : function() {
if (this._manager.getDescription && this._manager.getDescription('insurance', this._insuranceId) && this._manager.getDescription('insurance', this._insuranceId) != '') {
this._moreInfo.setAttribute('title', this._insuranceName + ' :: ' + this._manager.getDescription('insurance', this._insuranceId));
this._moreInfo.setStyle('display', '');
if (!this._descriptionToolTip) {
this._descriptionToolTip = new SynergeeTips(this._moreInfo, {'className':'PriceEstimationToolTip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
} else {
this._descriptionToolTip.build(this._moreInfo);
}
} else {
this._moreInfo.setStyle('display', 'none');
}
},
/**
* Returns an object containing the informations for the calculation price
*
* @return object The informations needed to calculate the price
*/
getDTO : function() {
var insuranceDTO = new Object();
insuranceDTO.id = this._insuranceId;
return insuranceDTO;
},
/**
* Return the insurance ID
*
* @return integer The Insurance ID
*/
getInsuranceId : function() {
return parseInt(this._insuranceId);
},
/**
* Populate the insurance from a dto
*/
populateFromDTO : function(toPopulateDTO) {
// there is nothing to populate in fact
},
setMandatory : function(mandatory) {
this._isMandatory = mandatory;
if (this._isMandatory) {
this._deleteButton.setStyle('display', 'none');
} else {
this._deleteButton.setStyle('display', '');
}
},
/**
* Set the dates of the insurance
* @param Date startDate The Start Date
* @param Date endDate The End Date
*/
setDates : function(startDate, endDate, duration) {
this._insuranceStartDate = startDate;
if (endDate)endDate.setDate(endDate.getDate() + this._insuranceDTO.additionalMandatoryDays);
this._insuranceEndDate = endDate;
this._insuranceDuration = duration + this._insuranceDTO.additionalMandatoryDays;
this.refreshInsuranceInterface();
},
/**
* Return true if the insurance is complete
*
* @return Boolean Return true if complete
*/
isComplete : function() {
if (this._insuranceStartDate && this._insuranceEndDate && this._insuranceDuration)return true;
return false;
},
/**
* Returns the HTML structure of this course
*
* @return Element the insurance element
*/
getHtml : function() {
return this._container;
},
/**
* Generate the list of insurances for this school
*
* @param schoolList list The list to update
*/
getVisualInsuranceList : function(list) {
list.clear();
this._parent._schoolInsurancesDTO.each(function(item, index) {
list.addItem(item.id, item.name);
list.getListItems().getLast().getHtml().addEvent('click', function() {
this.setInsurance(item);
}.bind(this));
}.bind(this));
if (!this._parent._schoolInsurancesDTO || this._parent.getParent().getCompletedCourses().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
this.refreshVisualInsuranceList();
},
/**
* refresh the list of insurances for this school
*
*/
refreshVisualInsuranceList : function() {
this._parent.refreshVisualInsuranceList(this._insuranceList);
},
/**
* Refresh the visual interface of this insurance
*
*/
refreshInsuranceInterface : function() {
if (this._insuranceStartDate && this._insuranceEndDate) {
this._startDateValue.setHTML(this._insuranceStartDate.format(this._parent.getParent().getDateFormat(), this._parent.getParent().getMonthTranslations()));
this._endDateValue.setHTML(this._insuranceEndDate.format(this._parent.getParent().getDateFormat(), this._parent.getParent().getMonthTranslations()));
if (this._insuranceDuration > 1) {
this._durationValue.setHTML(this._translateDTO.days.replace("%0", this._insuranceDuration));
} else {
this._durationValue.setHTML(this._translateDTO.day.replace("%0", this._insuranceDuration));
}
}
},
/**
* Replace the insurance with the one given in parameter
*
* @param Object insurance The insurance DTO
*/
setInsurance : function(insurance) {
this._insuranceName = insurance.name;
this._insuranceId = insurance.id;
this._type = insurance.type;
this._insuranceDTO = insurance;
this._title.setHTML(this._insuranceName);
this.updateDescriptions();
// the check will be done again by the insurances container
this.setMandatory(false);
this.fireEvent('refreshPrice');
},
/**
* Generate the options list for a insurance
* and set an event on each option
*
* @param SchoolList The list to update
*/
getVisualInsuranceOptionsList : function(list) {
list.clear();
list.getListItems().each(function(item, index) {
item.getHtml().addClass(this._classNameBase + 'List-Item');
item.getHtml().addEvent('click', function() {
this._parent.getParent().fireEvent('refreshPrice');
}.bind(this));
}.bind(this));
},
/**
* Remove the insurance from the list
*
*/
removeInsurance : function() {
this._container.remove();
}
});
/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param InsuranceListItemDTO schoolInsurancesDTO the insurances informations
* @param Object translateDTO The DTO containing the translations for this class
* @param SchoolPriceEstimation parent the parent
**/
var SchoolInsurances = Events.extend({
/**
* This is the initialization function
*/
initialize : function(schoolInsurancesDTO, translateDTO, parent) {
this._schoolInsurancesDTO = schoolInsurancesDTO;
this._schoolInsurancesDTO = new Hash();
if (schoolInsurancesDTO) {
for (var i = 0; i < schoolInsurancesDTO.length; i++) {
this._schoolInsurancesDTO.set(schoolInsurancesDTO[i].id, schoolInsurancesDTO[i]);
}
}
this._translateDTO = translateDTO;
this._parent = parent;
this._classNameBase = this.getParent().getClassNameBase();
this._insurances = new Array();
this._mandatoryInsurances = new Array();
this._defaultCheckedInsurances = new Array();
this._schoolInsurancesDTO.each(function(item, index) {
if (item.mandatory) {
this._mandatoryInsurances.push(item);
}
if (item.defaultChecked) {
this._defaultCheckedInsurances.push(item);
}
}.bind(this));
},
/**
* Returns the visual insurance container
*/
getHtml : function() {
this._insuranceContainer = new Element('div', {'class': this._classNameBase + 'Section'});
this._insuranceTitle = new Element('div', {'class': this._classNameBase + 'Section-Title'});
this._insuranceListContainer = new Element('div', {'class': this._classNameBase + 'Courses-CoursesList-Container'});
this._insuranceUserAccommodationList = new Element('div', {'class': this._classNameBase + 'Courses-UserCoursesList'});
this._insuranceAddButton = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._insuranceTitle.injectInside(this._insuranceContainer);
this._insuranceListContainer.injectInside(this._insuranceContainer);
this._insuranceUserAccommodationList.injectInside(this._insuranceListContainer);
this._insuranceAddButton.injectInside(this._insuranceContainer);
if (this._translateDTO) {
this._insuranceTitle.setHTML(this._translateDTO.title);
this._insuranceAddButton.setHTML(this._translateDTO.add);
}
this._insurancesList = new SchoolList(this._insuranceAddButton, this._classNameBase);
this.getVisualInsuranceList(this._insurancesList);
this._insurancesList.getHtml().injectInside(this._parent.getListContainer());
this._insurancesList.initializeEvents();
return this._insuranceContainer;
},
/**
*  Return the classNameBase
*/
getClassNameBase : function() {
return this._classNameBase;
},
/**
* Returns an array containing the informations for the calculation price
*
* @return Array The informations needed to calculate the price
*/
getDTO : function() {
var insurancesDTO = new Array();
this._insurances.each(function(item, index) {
if (item.isComplete()) {
insurancesDTO.push(item.getDTO());
}
}.bind(this));
return insurancesDTO;
},
/**
* Populate the insurances from a dto
*/
populateFromDTO : function(toPopulateDTO) {
if (toPopulateDTO) {
toPopulateDTO.each(function(item, index) {
this.addInsurance(item.id, true);
}.bind(this));
}
},
/**
* Retrieve the list of insurances for this school
*
* @param schoolList list The list to update
*/
getVisualInsuranceList : function(list) {
list.clear();
this._schoolInsurancesDTO.each(function(item, index) {
list.addItem(item.id, item.name);
list.getListItems().getLast().setIsValid(true);
list.getListItems().getLast().setIsSelectionnable(true)
list.getListItems().getLast().getHtml().addEvent('click', function() {
this.addInsurance(item.id);
}.bind(this));
}.bind(this));
this.refreshVisualInsuranceList(list);
},
/**
* Refresh the list of insurances for this school
*
* @param schoolList list The list to update
* @param availabilityItem boolean True if there is a last item to be used
*/
refreshVisualInsuranceList : function(list) {
var validListItem = 0;
list.getListItems().each(function(item, index) {
if (this._duration && (this._schoolInsurancesDTO.get(item.getValue()).availableFrom <= this._duration) &&  !this.isAdded(parseInt(item.getValue()))) {
item.setIsValid(true);
item.setIsSelectionnable(true);
validListItem++;
} else {
item.setIsValid(false);
}
}.bind(this));
if(validListItem){
this._insuranceAddButton.setStyle('display','');
}else {
this._insuranceAddButton.setStyle('display','none');
}
},
/**
* Refresh the value of the insurances (all insurances have the same duration)
*/
refreshValues : function() {
this._startDate = this.getInsuranceStartDate();
this._endDate = this.getInsuranceEndDate();
this._courseStartDate = this.getInsuranceStartDate(true);
this._courseEndDate = this.getInsuranceEndDate(true);
this._duration = this.getCalculatedDuration(this._startDate, this._endDate);
this._courseDuration = this.getCalculatedDuration(this._courseStartDate, this._courseEndDate);
if (this._insurances) {
for (var i = 0; i < this._insurances.length; i++) {
// Check if the insurance is calculated from the duration of the course
if(this._insurances[i].getInsuranceInformations().durationCalculationMethod == 1){
this._insurances[i].setDates(new Date(this._courseStartDate), new Date(this._courseEndDate), this._courseDuration);
} else {
this._insurances[i].setDates(new Date(this._startDate), new Date(this._endDate), this._duration);
}
}
}
},
/**
* Return the insurance start date calculated from the course and accommodation
*/
getInsuranceStartDate : function(courseOnly) {
if(!courseOnly)courseOnly = false;
return this._parent.getStartDate(courseOnly);
},
/**
* Return the insurance start date calculated from the course and accommodation
*/
getInsuranceCourseStartDate : function(courseOnly) {
if(!courseOnly)courseOnly = false;
return this._parent.getCourseStartDate(courseOnly);
},
/**
* Return the insurance end date calculated from the course and accommodation
*/
getInsuranceEndDate : function() {
return this._parent.getEndDate();
},
/**
* Return the durationof the insurance
*/
getInsuranceDuration : function() {
return this._duration;
},
/**
* Return the duration in days.
* To perform the calculation we count the number of time the week day of the start date
* can be repeated between the start date and the end date.
*
* @param date startDate The start date
* @param date endDate The end date
* @return integer the number of Days
*/
getCalculatedDuration : function(startDate, endDate) {
var numberOfDays = 0;
// The number of milliseconds in one day
var oneDay = 1000 * 60 * 60 * 24;
if (startDate && endDate && startDate.getTime && endDate.getTime) {
startDate = startDate.getTime();
endDate = endDate.getTime() + 1000;
var differenceMs = Math.abs(startDate - endDate)
numberOfDays = (Math.round(differenceMs/oneDay)) + 1;
}
return numberOfDays;
},
/**
* Refresh the insurances lists
*
*/
refreshInsurances : function() {
this.refreshValues();
var transfNb = this._insurances.length;
this.refreshVisualInsuranceList(this._insurancesList);
// refresh every insurance list for the added insurances
this._mandatoryInsurances.each(function(item, index) {
if (!this.isAdded(item.id)) {
var minDuration = (parseInt(item.mandatoryFrom) ? parseInt(item.mandatoryFrom) : 0);
var addedInsurance = null;
if (this._duration > 0 && minDuration <= this._duration) {
this.addInsurance(item.id);
if (addedInsurance = this.getAddedInsurance(item.id)) {
addedInsurance.setMandatory(true);
}
}
} else {
var minDuration = (parseInt(item.mandatoryFrom) ? parseInt(item.mandatoryFrom) : 0);
if (minDuration > this._duration) {
if (addedInsurance = this.getAddedInsurance(item.id)) {
addedInsurance.setMandatory(false);
}
}
}
}.bind(this));
// removing the insurances that are not meeting the min weeks
this._insurances.each(function(item, index){
if(this._schoolInsurancesDTO.get(item.getInsuranceId()).availableFrom > this._duration){
item.removeInsurance();
this._insurances.remove(item);
}
}.bind(this));
// remove all the insurance if there are no more course on the quote
if (this._parent.getCompletedCourses().length == 0) {
for (var i = this._insurances.length - 1; i >= 0; i--) {
this._insurances[i].removeInsurance();
this._insurances.remove(this._insurances[i]);
}
this._parent.fireEvent('heightModified');
if (transfNb > 0)this._parent.fireEvent('refreshPrice');
}else {
this._defaultCheckedInsurances.each(function(item, index) {
if (!this.isAdded(item.id)) {
this.addInsurance(item.id);
}
this._defaultCheckedInsurances.remove(item);
}.bind(this))
}
// refresh every insurance list for the added insurances
if (this._insurances) {
for (var i = 0; i < this._insurances.length; i++) {
this._insurances[i].refreshVisualInsuranceList();
}
}
},
/**
* Add a insurance from its ID
*
* @param Number id The insurance id
*/
addInsurance : function(id, noTest) {
if (this._schoolInsurancesDTO.hasKey(id) && (this._schoolInsurancesDTO.get(id).availableFrom <= this._duration  || noTest)  && !this.isAdded(id)) {
var schoolInsurance = this._schoolInsurancesDTO.get(id);
var newInsurance = new SchoolInsuranceObject(schoolInsurance.id, schoolInsurance, this._translateDTO.insuranceObject, this);
newInsurance.addEvent('refreshPrice', this.refreshPrice.bind(this));
this._insurances.push(newInsurance);
newInsurance.createVisualInsurance();
this._insurances.getLast().getHtml().injectInside(this._insuranceUserAccommodationList);
newInsurance.addEvent('deleteInsurance', function(e) {
this.deleteInsurance(newInsurance);
}.bind(this));
this.refreshPrice();
}
},
refreshPrice: function() {
this.fireEvent('refreshPrice');
},
/**
* Returns the parent of this object
*
* @return SchoolPriceEstimation The parent
*/
getParent : function() {
return this._parent;
},
/**
* Display or hide the add button
*
* @param boolean isDisplayed True to display the hide button
*/
displayAddButton : function(isDisplayed) {
if (isDisplayed) {
this._insuranceAddButton.setStyle('display', 'block');
} else {
this._insuranceAddButton.setStyle('display', 'none');
}
},
/**
* Returns the number of completed insurances
*
* @return Number The number of completed insurances
*/
getCompletedInsurances : function() {
return this._insurances;
},
/**
* Test if the insurance is added
*
* @param insuranceId The insurance id
*
* @return Boolean True if the insurance is added
*/
isAdded : function (insuranceId) {
insuranceId  = parseInt(insuranceId);
if (this._insurances) {
for (var i = 0; i < this._insurances.length; i++) {
if (this._insurances[i].getInsuranceId() == insuranceId)return true;
}
}
return false;
},
/**
* Return the added insurance from its id
* @param insuranceId integer The insurance ID
*
* @return SchoolInsuranceObject The insurance object
*
*/
getAddedInsurance : function (insuranceId) {
if (this._insurances) {
for (var i = 0; i < this._insurances.length; i++) {
if (this._insurances[i].getInsuranceId() == parseInt(insuranceId))return this._insurances[i];
}
}
return false;
},
/**
* Delete the given insurance
*
* @param SchoolInsuranceObject insurance The insurance to delete
*/
deleteInsurance : function(insurance) {
this._insurances.remove(insurance);
this._parent.fireEvent('heightModified');
this._parent.fireEvent('refreshPrice');
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param Element button the button attached to the list
*
**/
var SchoolList = Events.extend({
/**
* This is the initialization function
*/
initialize : function(button, classNameBase) {
this._classNameBase = classNameBase;
this._listItems = new Array();
this._button = button;
this._list = this.setHtml();
this._list.setStyle('display', 'none');
this._selectedItem = -1;
this._buttonEventInitialized = false;
},
/**
* return true if the event on the list button is initialized
*
* @return boolean True if initialized
*/
getButtonEventInitialized : function() {
return this._buttonEventInitialized;
},
/**
*  Create the HTML structure
*
* @return Element The div container
*/
setHtml : function() {
return new Element('div', {'class': this._classNameBase + 'List', 'style':'display:none'});
},
/**
* This method add an element to the list
*
* @param Object value The value of the item
* @param String html The html value of the item
*/
addItem : function(value, html) {
var newItem = new SchoolListItem(value, html, this._classNameBase);
this._listItems.push(newItem);
newItem._listItem.injectInside(this._list);
},
/**
* This method add an element to the list
*
* @param SchoolListItem listItem The school list item
*/
addListItem : function(schooListItem) {
this._listItems.push(schooListItem);
schooListItem._listItem.injectInside(this._list);
},
/**
* this method clear the list
*/
clear : function() {
this._listItems = new Array();
this._list = this.setHtml();
},
/**
* This method return the list html formatted
*
* @return Element The list element
*/
getHtml : function() {
return this._list;
},
/**
* This method return the listItem Array
*
* @return Array The array containing all the list items
*/
getListItems : function() {
return this._listItems;
},
/**
* Returns the valid list items
*
* @return SchoolListItem[] The valid list items
*/
getValidListItems : function() {
var listItems = new Array();
this._listItems.each(function(item, index) {
if (item.getIsValid()) {
listItems.push(item);
}
});
return listItems;
},
/**
* Returns the height of a valid Item
*
* @return Number The height of a valid Item
*/
getItemHeight : function() {
var test = false;
var height = 0;
var i = 0;
while (!test) {
height = this._listItems[i].getHtml().getCoordinates().height;
test = this._listItems[i].getIsValid();
i++;
}
return height;
},
/**
* Returns the height of a list
*
* @return Number The height of this school list
*/
getListHeight : function() {
var height = 0;
this._listItems.each(function(item, index) {
if (item.getIsValid()) {
height = height + item.getHtml().getCoordinates().height;
}
});
return height;
},
/**
* This method set the item the list has to scroll to
*
* @param SchoolListItem item The item the list has to scroll to
*/
setSelectedItem : function(item) {
if (this._selectedItem != -1){
if(this._listItems[this._selectedItem])this._listItems[this._selectedItem].getHtml().removeProperty('id');
}
this._selectedItem = this._listItems.indexOf(item);
if(this._listItems[this._selectedItem])this._listItems[this._selectedItem].getHtml().setProperty('id', 'firstValid');
},
/**
* This method return the selected item
*
* @return SchoolListItem item The selected item
*/
getSelectedItem : function() {
if (this._selectedItem != -1){
if(this._listItems[this._selectedItem])
return this._listItems[this._selectedItem];
}
return null;
},
/**
*  Initialize the main events for this list
*/
initializeEvents : function() {
//        if (this.getValidListItems().length) {
var myTimer = -1;
// add the mouseleave event on the list
this.getHtml().addEvent('mouseleave', function() {
myTimer = this.getHtml().setStyles.delay(500, this.getHtml(), {'visibility':'hidden','display':'none', 'z-index':0});
}.bind(this));
this.getHtml().addEvent('mouseover', function() {
$clear(myTimer);
});
this._listItems.each(function(item, index) {
item.getHtml().addEvent('click', function() {
if (!(item.getValue() == 'category' || item.getValue() == 'error' )) {
this.getHtml().setStyle('visibility', 'hidden');
this.getHtml().setStyle('display', 'none');
this.getHtml().setStyle('height', '0px');
}
}.bind(this));
}.bind(this));
// add an event on the button to appear the list
this.addButtonEvent();
//        }
},
/**
* Return the list button
*/
getButton : function(){
return this._button;
},
/**
* add the event on the list button
*/
addButtonEvent : function(){
if(!this._buttonEventInitialized)this._button.addEvent('click', this.buttonClickEvent.bind(this));
this._buttonEventInitialized = true;
},
/**
*  remove the button event for this button
*/
removeButtonEvent : function() {
if(this._buttonEventInitialized)this._button.removeEvent('click', this.buttonClickEvent.bind(this));
if(this._buttonEventInitialized)this._button.removeEvents();
this._buttonEventInitialized = false;
},
/**
* method to call when the button is clicked
*/
buttonClickEvent : function() {
// add an event on the button to appear the list
var scroll = new Fx.Scroll(this._list);
var listHeight = parseInt(this.getHtml().getStyle('max-height'));
if (!listHeight) listHeight = 165;
this.getHtml().setStyle('height', '0px');
if(window.ie6){
this.getHtml().setStyle('width', this._button.getCoordinates().width + 'px');
}else{
this.getHtml().setStyle('min-width', this._button.getCoordinates().width + 'px');
}
this.setPosition();
this.getHtml().setStyle('display', 'block');
// the list is scrolled to the first valid element
if (this.getHtml().getElements('div[id=firstValid]')[0]) {
scroll.toElement(this.getHtml().getElements('div[id=firstValid]')[0]);
}
// set the overflow-y auto if the list is taller than the list
if (this.getListHeight() > listHeight) {
this.getHtml().setStyle('overflow-y', 'auto');
if(window.ie6){
this.getHtml().setStyle('width', (parseInt(this.getHtml().getStyle('width')) + 15) + 'px');
}else{
this.getHtml().setStyle('min-width', (parseInt(this.getHtml().getStyle('width')) + 15) + 'px');
}
new Fx.Style(this.getHtml(), 'height', {transition : Fx.Transitions.Quart.easeOut}).start('0', (listHeight) + 'px');
} else {
new Fx.Style(this.getHtml(), 'height', {transition : Fx.Transitions.Quart.easeOut}).start('0', this.getListHeight() + 'px');
}
this.getHtml().setStyle('visibility', 'visible');
this.getHtml().setStyle('z-index', 1000);
},
deleteList : function(){
this.removeButtonEvent();
if(this.getHtml().getParent())this.getHtml().remove();
},
/**
* This function Set the list position relative to its button
*
*/
setPosition : function() {
this._list.setStyle('left', this._button.getCoordinates().left);
this._list.setStyle('top', this._button.getCoordinates().top);
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param Object value The value of the item
* @param String html The visual value of the item
*
**/
var SchoolListItem = Events.extend({
/**
* This is the initialization function
*/
initialize : function(value, html, classNameBase) {
this._classNameBase = classNameBase;
this._value = value;
this._html = html;
this.setVisualHtml();
this._isValid = true;
this._isSelectionnable = true;
},
/**
* Create the HTHML part of the item
*/
setVisualHtml : function() {
this._listItem = new Element('div');
this._listItem.setHTML(this._html);
this._listItem.listItemContainer = this;
},
/**
* set the new html value
*
* @param html String the new html value
*/
setHtml : function(html){
this._html = html;
this._listItem.setHTML(this._html);
},
/**
* Returns the element
*
* @return Element The list item
*/
getHtml : function() {
return this._listItem;
},
/**
* Returns the html value of the item
*
* @return Element The Html view of the item
*/
getHtmlValue : function() {
return this._html;
},
/**
* Returns the element value
*
* @return Object The item value
*/
getValue : function() {
return this._value;
},
/**
*  Set the validity of a list item
*
* @param Boolean validity The new validity of the list item
*/
setIsValid : function(validity) {
if (validity) {
this.getHtml().setStyle('display', 'block');
} else {
this.getHtml().setStyle('display', 'none');
}
this._isValid = validity;
},
/**
* Returns true if the item is valid
*
* @return Boolean Return true if the item is valid
*/
getIsValid : function() {
return this._isValid;
},
/**
* This method set if an item is selectionnable or not
*
* @param Boolean value Set true if the item is selectionnable
*/
setIsSelectionnable : function(value) {
if (value) {
this.getHtml().addClass(this._classNameBase + 'List-Item');
this.getHtml().removeClass(this._classNameBase + 'NotSelectionable');
} else {
this.getHtml().addClass(this._classNameBase + 'NotSelectionable');
this.getHtml().removeClass(this._classNameBase + 'List-Item');
}
this._isSelectionnable = value;
},
/**
* Returns true if the item is selectionnable
*
* @return Boolean Returns true if the item is selectionnable
*/
getIsSelectionnable : function() {
return this._isSelectionnable;
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @event Event deleteCourse This event is fired when a course is deleted
*
* @param FixedDatesCourseListItemDTO courseDetails courseDetails The object containing the course informations
* @param Object translateDTO The object containing all the translations for this class
* @param SchoolCourses parent The parent
*
**/
var SchoolOptionalCourseObject = Events.extend({
/**
* This is the initialization function
*
*/
initialize : function(courseDetails, translateDTO, listContainer, classNamePrefix, parent) {
this._translateDTO = translateDTO;
this._courseDetails = courseDetails;
this._parent = parent;
this._listContainer = listContainer;
this._classNameBase = classNamePrefix;
this._dateFormat = this._parent.getParent().getDateFormat();
this._monthsTranslations = this._parent.getParent().getMonthTranslations();
this._courseStartDate = null;
this._courseEndDate = null;
this._courseDuration = null;
this._manager = this.getParent().getParent().getParent();
this._manager.addEvent('descriptionsUpdated', function(){
this.updateDescriptions();
}.bind(this));
},
/**
* Return the course details DTO
*
* @return CourseDetailsDTO The course Details DTO
*/
getCourseDetails : function() {
return this._courseDetails;
},
/**
* Return true if the course is complete
*
* @return Boolean Return true if the course is complete
*/
isComplete : function() {
if (this._courseStartDate && this._courseEndDate && this._courseDuration) {
return true;
} else {
return false;
}
},
/**
* Generate the html structure of the course
* and add an event on the delete button
*
*/
createVisualCourse : function() {
this._container = new Element('div', {'class': this._classNameBase + 'ItemAdded'});
this._title = new Element('div', {'class': this._classNameBase + 'Section-Item-Title'});
this._subTitle = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle'});
this._moreInfo = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle MoreInfos'});
this._moreInfo.setStyle('display','none');
this._startDateContainer = new Element('div',{'class': this._classNameBase + 'Section-Item-StartDate-Container'});
this._endDateContainer = new Element('div',{'class': this._classNameBase + 'Section-Item-EndDate-Container'});
this._startDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._startDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value ' + this._classNameBase + 'Section-Item-ToUpdate'});
this._endDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._endDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-ValueNotEditable'});
this._durationContainer = new Element('div',{'class': this._classNameBase + 'Section-Item-Duration-Container'});
this._duration = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._durationValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value ' + this._classNameBase + 'Section-Item-ToUpdate'});
this._deleteButton = new Element('div', {'class': this._classNameBase + 'Section-Item-DeleteButton'});
this._duration.injectInside(this._durationContainer);
this._durationValue.injectInside(this._durationContainer);
this._startDate.injectInside(this._startDateContainer);
this._startDateValue.injectInside(this._startDateContainer);
this._endDate.injectInside(this._endDateContainer);
this._endDateValue.injectInside(this._endDateContainer);
this._title.injectInside(this._container);
this._subTitle.injectInside(this._container);
this._moreInfo.injectInside(this._container);
new Element('div',{'style':'clear:both'}).injectInside(this._container);
this._startDateContainer.injectInside(this._container);
this._endDateContainer.injectInside(this._container);
this._durationContainer.injectInside(this._container);
this._deleteButton.injectInside(this._container);
new Element('div',{'style':'clear:both'}).injectInside(this._container);
this._title.setHTML(this._courseDetails.name);
this._subTitle.setHTML(this._courseDetails.subtitle);
this._moreInfo.setHTML(this._translateDTO.moreInfos);
this._startDate.setHTML(this._translateDTO.startDateOptional);
this._startDateValue.setHTML(this._translateDTO.dateSelectOptional);
this._endDate.setHTML(this._translateDTO.endDateOptional);
this._endDateValue.setHTML(this._translateDTO.endDateValueOptional);
this._duration.setHTML(this._translateDTO.durationOptional);
this._durationValue.setHTML(this._translateDTO.durationSelectOptional);
this._deleteButton.setHTML(this._translateDTO.deleteButtonOptional);
// add event listener
this._deleteButton.addEvent('click', function(e) {
this.removeCourse();
this.fireEvent('deleteCourse');
}.bind(this));
this.updateDescriptions();
this._coursesValidList = new SchoolList(this._title, this._classNameBase);
this.getVisualValidCoursesList(this._coursesValidList);
this._coursesValidList.getHtml().injectInside(this._listContainer);
this._coursesValidList.initializeEvents();
this._schoolStartList = new SchoolList(this._startDateValue, this._classNameBase);
this.getVisualOptionalCourseStartDates(this._courseDetails.startDates, this._schoolStartList);
this.refreshVisualOptionalCourseStartDates(this._parent.getValidOptionalCourseStartDate(this), this._schoolStartList);
this._schoolStartList.getHtml().injectInside(this._listContainer);
this._schoolStartList.initializeEvents();
this._schoolDurationList = new SchoolList(this._durationValue, this._classNameBase);
this.getVisualOptionalCourseDurationList(this._courseDetails.duration, this._schoolDurationList);
this.refreshVisualOptionalCourseDurationList(this._parent.getValidOptionalCourseDuration(this), this._schoolDurationList);
this._schoolDurationList.getHtml().injectInside(this._listContainer);
this._schoolDurationList.initializeEvents();
if(this._courseDetails.oneDayCourse){
this._duration.setStyle('display','none');
this._durationValue.setStyle('display','none');
}
},
/**
* Returns the html Element of this course
*
* @return Element The HTML view of this course
*/
getHtml : function() {
return this._container;
},
updateDescriptions : function(){
if (this._manager.getDescription && this._manager.getDescription('course', this._courseDetails.courseTypeId) && this._manager.getDescription('course', this._courseDetails.courseTypeId) != '') {
this._moreInfo.setAttribute('title', this._courseDetails.name + ' :: ' + this._manager.getDescription('course', this._courseDetails.courseTypeId));
this._moreInfo.setStyle('display','');
if(!this._descriptionToolTip ){
this._descriptionToolTip = new SynergeeTips(this._moreInfo, {'className':'PriceEstimationToolTip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
}else {
this._descriptionToolTip.build(this._moreInfo);
}
}else {
this._moreInfo.setStyle('display','none');
}
},
/**
* Return an object containing the informations for the calculation price
*
* @return Object The informations needed to calculate the price
*/
getDTO : function() {
var courseDTO = new Object();
courseDTO.id = this._courseDetails.id;
courseDTO.startDate = this._courseStartDate.toIso();
courseDTO.endDate = this._courseEndDate.toIso();
return courseDTO;
},
/**
* Populate the variable course from a dto
*
* @param Object The fixed course informations needed to populate
*/
populateFromDTO : function(toPopulateDTO) {
this._courseStartDate = (new Date()).fromIso(toPopulateDTO.startDate);
this._startDateValue.setHTML(this._courseStartDate.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
this._courseEndDate = (new Date()).fromIso(toPopulateDTO.endDate);
this._courseDuration = this.getCalculatedDuration(this._courseStartDate, this._courseEndDate );
if(this._courseDetails.duration.length && this._courseDuration < parseInt(this._courseDetails.duration[0])) this._courseDuration = parseInt(this._courseDetails.duration[0]);
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
// If the start and the duration are set,  the end date is calculated
if (this._courseStartDate && this._courseDuration) {
this._courseEndDate = this.getOptionalCourseEndDate();
this._endDateValue.setHTML(this._courseEndDate.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
}
// when the user selects only the start date, the duration is set with the minimal value
if (this._courseStartDate && !this._courseDuration) {
this._courseDuration = this._courseDetails.duration[0];
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
this._courseEndDate = this.getOptionalCourseEndDate();
this._endDateValue.setHTML(this._courseEndDate.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
}
},
/**
* Refresh all the lists of this course
*
*/
refreshLists : function() {
// add the list of courses that fit the start and end Date
this.refreshVisualValidCoursesList(this._coursesValidList);
// initialize the start date list and its event
this.refreshVisualOptionalCourseStartDates(this._parent.getValidOptionalCourseStartDate(this), this._schoolStartList);
// initialize the duration list and its event
this.refreshVisualOptionalCourseDurationList(this._parent.getValidOptionalCourseDuration(this), this._schoolDurationList);
},
/**
* Generate all the lists of this course
*
*/
reGenerateLists : function() {
// remove old list if exists
if (this._coursesValidList._listItems.length) {
this._coursesValidList.getHtml().remove();
this._coursesValidList.clear();
}
if (this._schoolStartList._listItems.length) {
this._schoolStartList.getHtml().remove();
this._schoolStartList.clear();
}
if (this._schoolDurationList._listItems.length) {
this._schoolDurationList.getHtml().remove();
this._schoolDurationList.clear();
}
this.getVisualValidCoursesList(this._coursesValidList);
this._coursesValidList.getHtml().injectInside(this._listContainer);
this._coursesValidList.initializeEvents();
this.getVisualOptionalCourseStartDates(this._courseDetails.startDates, this._schoolStartList);
this.refreshVisualOptionalCourseStartDates(this._parent.getValidOptionalCourseStartDate(this), this._schoolStartList);
this._schoolStartList.getHtml().injectInside(this._listContainer);
this._schoolStartList.initializeEvents();
this.getVisualOptionalCourseDurationList(this._courseDetails.duration, this._schoolDurationList);
this.refreshVisualOptionalCourseDurationList(this._parent.getValidOptionalCourseDuration(this), this._schoolDurationList);
this._schoolDurationList.getHtml().injectInside(this._listContainer);
this._schoolDurationList.initializeEvents();
},
/**
* Refresh the course data
*
*/
refreshOptionalCourseData : function() {
// If the start and the duration are set,  the end date is calculated
if (this._courseStartDate && this._courseDuration) {
this._courseEndDate = this.getOptionalCourseEndDate();
this._endDateValue.setHTML(this._courseEndDate.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
this._durationValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
}
// when the user selects only the start date, the duration is set with the minimal value
if (this._courseStartDate && !this._courseDuration) {
this._courseDuration = this._courseDetails.duration[0];
this._durationValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
this._courseEndDate = this.getOptionalCourseEndDate();
this._endDateValue.setHTML(this._courseEndDate.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
}
if (this.isComplete()) {
this._durationValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
// refresh the course list
this._parent.fireEvent('refreshCourses');
this._parent.fireEvent('refreshPrice');
}
},
/**
*  Returns the endDate of a variable course
*
* @param Date endDate The enddate to calculate
* @return Date The variable course end date
*/
getOptionalCourseEndDate : function(endDate) {
if ((this._courseDetails.courseStartDay == this._courseDetails.courseEndDay && this._courseDetails.oneDayCourse)) {
if (!endDate)endDate = new Date(this._courseStartDate);
} else {
if (!endDate)endDate = new Date(this._courseStartDate.getFullYear(), this._courseStartDate.getMonth(), this._courseStartDate.getDate() + this._courseDuration * 7);
var endDateDay = endDate.getDay();
if (endDateDay == 0) endDateDay = 7;
while (endDateDay != this._courseDetails.courseEndDay) {
endDate.setDate(endDate.getDate() - 1);
endDateDay = endDate.getDay();
if (endDateDay == 0) endDateDay = 7;
}
}
return endDate;
},
/**
* Replace the courses and find the best possible dates
*
* @param Object The new course DTO
*/
replaceCourse : function(newCourse) {
this._durationValue.removeClass(this._classNameBase + 'Section-Item-Info-Value');
this._schoolStartList.getHtml().remove();
this._schoolDurationList.getHtml().remove();
this._coursesValidList.getHtml().remove();
if (this.isComplete()) {
this._parent.replaceCourse(this, newCourse, this._courseStartDate);
} else {
this._parent.replaceCourse(this, newCourse);
}
this.updateDescriptions();
},
/**
* this method find the best dates and duration for the new variable course based on the old one
*
* @param Date oldStartDate the date of the replaced course
* @param number oldDuration the duration of the replaced course
*/
replaceOptionalCourseDates : function(oldStartDate, oldDuration) {
// if the start date is already set
if (oldStartDate) {
var dateDifference = null;
var newDate;
this._courseDetails.startDates.each(function(item, index) {
if (dateDifference > Math.abs(oldStartDate.getTime() - item.getTime()) || dateDifference == null) {
dateDifference = Math.abs(oldStartDate.getTime() - item.getTime());
newDate = item;
}
});
// if there is already a duration set
if (oldDuration) {
var durationDifference = null;
var newDuration;
this._courseDetails.duration.each(function(item, index) {
if (durationDifference > Math.abs(oldDuration - item) || durationDifference == null) {
durationDifference = Math.abs(oldDuration - item);
newDuration = item;
}
});
this._courseDuration = newDuration;
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
}
this._courseStartDate = newDate;
this._startDateValue.setHTML(newDate.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
this.refreshOptionalCourseData();
}
},
/**
* Generate a list of valid course
*
* @param SchoolList list The valid courses list
*
*/
getVisualValidCoursesList : function(list) {
var validCourses = this._parent.getOptionalCourses();
// clearing the list
list.clear();
validCourses.each(function(item, index) {
list.addItem(item, item.name);
list.getListItems().getLast().getHtml().addClass(this._classNameBase + 'List-Item');
list.getListItems().getLast().getHtml().addEvent('click', function() {
this.replaceCourse(item);
}.bind(this));
}, this);
this.refreshVisualValidCoursesList(list);
},
/**
* Refresh a list of course that have possible dates between this courseStartDate and courseEndDate
*
* @param SchoolList list The courses list
*
*/
refreshVisualValidCoursesList : function(list) {
var validCourses = this._parent.getValidCourses(this, true);
list.getListItems().each(function(item, index) {
if (validCourses.indexOf(item.getValue()) != -1) {
item.setIsValid(true);
} else {
item.setIsValid(false);
}
}.bind(this));
},
/**
* This function set a formated list from an array of a course start dates
*
* @param Array startDates An array of Date containing all the possible startDates
* @param SchoolList list The valid courses list
*/
getVisualOptionalCourseStartDates : function(startDates, list) {
// clearing the list
list.clear();
startDates.each(function(item, index) {
list.addItem(item, item.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
index = list.getListItems().indexOf(list.getListItems().getLast());
list.getListItems().getLast().getHtml().addEvent('click', function() {
if (list.getListItems()[index].getIsSelectionnable()) {
// Set the variables for this course
this._courseStartDate = item;
// set the visual data of this course
this._startDateValue.setHTML(item.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
this.refreshOptionalCourseData();
}
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.noValidStartDates);
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* this function refresh a list from an array of a course start dates
*
* @param Array validStartDates an array of Date containing the validated startDates
* @param SchoolList list the valid courses list
*/
refreshVisualOptionalCourseStartDates : function(validStartDate, list) {
var firstValid = true;
list.getListItems().each(function(item, index) {
if (validStartDate.indexOf(item.getValue()) != -1) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (firstValid) {
list.setSelectedItem(item);
}
if (this._courseStartDate == item.getValue()) {
list.setSelectedItem(item);
}
firstValid = false;
} else {
if (item.getValue == 'error') {
item.setIsValid(false);
}
item.setIsSelectionnable(false);
}
}.bind(this));
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* This function return a formated list from an array of duration
*
* @param Array durations An array of Date containing the startDates
* @param Array validDurations An array of number containing the validated durations
*/
getVisualOptionalCourseDurationList : function(durations, list) {
// clearing the list
list.clear();
durations.each(function(item, index) {
if (item > 1) {
list.addItem(item, this._translateDTO.weeks.replace('%0', item));
} else {
list.addItem(item, this._translateDTO.week.replace('%0', item));
}
index = list.getListItems().indexOf(list.getListItems().getLast());
// adding the event on the valid courses
list.getListItems().getLast().getHtml().addEvent('click', function() {
if (list.getListItems()[index].getIsSelectionnable()) {
this._courseDuration = item;
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
this.refreshOptionalCourseData();
}
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.noValidDuration);
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* This function return a formated list from an array of duration
*
* @param Array validDurations An array of number containing the validated durations
* @param SchoolList list The list to refresh
*/
refreshVisualOptionalCourseDurationList : function(validDurations, list) {
var firstValid = true;
list.getListItems().each(function(item, index) {
if (validDurations.indexOf(item.getValue()) != -1) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (firstValid)list.setSelectedItem(item);
if (this._courseDuration == item.getValue()) list.setSelectedItem(item);
firstValid = false;
} else {
if (item.getValue == 'error')item.setIsValid(false);
item.setIsSelectionnable(false);
}
}.bind(this));
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Return the duration in weeks.
* To perform the calculation we count the number of time the week day of the start date
* can be repeated between the start date and the end date.
*
* @param date startDate The start date
* @param date endDate The end date
* @return integer the number of weeks
*/
getCalculatedDuration : function(startDate, endDate) {
startDate = startDate.getTime();
endDate = endDate.getTime() - (86400 * 3 *1000) ;
var numberOfWeeks = 0;
while(startDate <= endDate) {
numberOfWeeks++;
startDate += (86400 * 7 * 1000);
}
return numberOfWeeks;
},
/**
*  Returns the available accommodations for this course
*
* @return Array of integer The Accommodation IDs
*/
getAvailableAccommodations : function() {
return this._courseDetails.availableAccommodations;
},
/**
*  return the course duration
*
* @return integer The course duration
*/
getCourseDuration : function() {
return this._courseDuration;
},
/**
*  set the course duration
*
* @param integer duration The course duration
*/
setCourseDuration : function(duration) {
this._courseDuration = duration;
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
},
/**
* return the course start date
*
* @return Date The course start date
*/
getCourseStartDate : function() {
return this._courseStartDate;
},
/**
* return the course start date
*
* @return Date The course start date
*/
getCourseEndDate : function() {
return this._courseEndDate;
},
/**
*  set the course duration
*
* @param integer duration The course duration
*/
setCourseStartDate : function(startDate) {
this._courseStartDate = startDate;
this._startDateValue.setHTML(this._courseStartDate.format(this._dateFormat, this._parent.getParent().getMonthTranslations()));
},
/**
* Returns false is it's not a fixed course
*
* @return Boolean Return false because it's a variable course
*/
getIsFixedCourse : function() {
return false;
},
/**
* return the parent
*
* @return SchoolCourses The parent
*/
getParent : function() {
return this._parent;
},
/**
* Remove the course from the list
*
*/
removeCourse : function() {
this._schoolStartList.getHtml().remove();
this._schoolDurationList.getHtml().remove();
this._coursesValidList.getHtml().remove();
this._container.remove();
}
});
/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param TransferListItemDTO schoolTransfersDTO the transfers informations
* @param SchoolPriceEstimation parent the parent
**/
var SchoolParticipants = Events.extend({
/**
* This is the initialization function
*/
initialize : function(translateDTO, enabled, parent) {
this._translateDTO = translateDTO;
this._enabled = enabled;
this._parent = parent;
this._classNameBase = this._parent.getClassNameBase();
this._participant = 1;
},
/**
* return the visual transfer container
*/
getHtml : function() {
this._participantContainer = new Element('div', {'class': this._classNameBase + 'Participants-Section'});
this._participantTitle = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title'});
this._participantTitleText = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title-Text'});
this._participantTitleText.injectInside(this._participantTitle);
this._participantButtons = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._participantButtons.addClass( this._classNameBase + 'ParticipantsButton');
this._participantTitle.injectInside(this._participantContainer);
this._participantTitleText.setHTML(this._translateDTO.title);
this._participantButtons.setHTML('1');
this._participantButtons.injectInside(this._participantTitle);
this._participantsList = new SchoolList(this._participantButtons, this._classNameBase);
this.createVisualList(this._participantsList);
this._participantsList.getHtml().injectInside(this._parent.getListContainer());
this._participantsList.initializeEvents();
if(!this._enabled){
this._participantContainer.setStyle('display', 'none');
}
return this._participantContainer;
},
/**
* Generate the list of participants
*
* @param SchoolList list The list to update
*/
createVisualList : function(list) {
for (var i = 1; i < 50; i++) {
if(i > 1){
list.addItem(i, i);
} else{
list.addItem(i, i);
}
}
list.getListItems().each(function(item, index) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (item.getValue() == this._participant) {
list.setSelectedItem(item);
}
item.getHtml().addEvent('click', function(event) {
this._participantButtons.setHTML(item.getHtmlValue());
this._participant = item.getValue();
this._parent.refreshAccommodations();
this._parent.fireEvent('refreshPrice');
list.setSelectedItem(item);
}.bind(this));
}.bind(this));
},
/**
* Returns the number of participant
*
* @return number The number of participants
*/
getParticipant : function() {
if(!this._participant)this._participant = 1;
return this._participant;
},
setParticipant : function(participants){
this._participant  = participants;
this._participantButtons.setHTML(participants);
//        this._participantButtons.setHTML(participants + (participants > 1? " "+this._translateDTO.participants : " "+this._translateDTO.participant));
}
});/**
* This class is used for the price calculation functionnalities DTO
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
**/
var SchoolPriceCalculatorDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function() {
this.dateFormat = '';
this.schoolInformations = '';
this.schoolFixedDatesCourses = new Array();
this.schoolVariableDatesCourses = new Array();
this.schoolOptionalCourses = new Array();
this.schoolAccommodations = new Array();
this.schoolTransfers = new Array();
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var SchoolInformationDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(schoolGroupID, vacationAndHolidays) {
this.schoolGroupID = schoolGroupID;
this.vacationAndHolidays = vacationAndHolidays;
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var FixedDatesCourseListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name, sessions, subtitle, accommodationMandatory, transferMandatory, availableAccommodations, position, availableOptionalCourses, courseTypeId) {
this.id = id;
this.type = 'fixedDate';
this.name = name;
this.sessions = sessions;
this.subtitle = subtitle;
this.accommodationMandatory = accommodationMandatory;
this.transferMandatory = transferMandatory;
this.availableAccommodations = availableAccommodations;
this.position = position;
this.availableOptionalCourses = availableOptionalCourses;
this.courseTypeId = courseTypeId;
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var FixedDatesCourseSessionListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(courseStartDate, courseEndDate, accommodationStartDate, accommodationEndDate) {
this.courseStartDate = courseStartDate;
this.courseEndDate = courseEndDate;
this.accommodationStartDate = accommodationStartDate;
this.accommodationEndDate = accommodationEndDate;
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var VariableDatesCourseListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name, startDates, duration, courseStartDay, courseEndDay, subtitle,  accommodationMandatory, transferMandatory, availableAccommodations, position, availableOptionalCourses, availabilities, courseTypeId) {
this.id = id;
this.type = 'variableDate';
this.name = name;
this.startDates = startDates;
this.duration = duration;
this.courseStartDay = courseStartDay;
this.courseEndDay = courseEndDay;
this.subtitle = subtitle;
this.accommodationMandatory = accommodationMandatory;
this.transferMandatory = transferMandatory;
this.availableAccommodations = availableAccommodations;
this.position = position;
this.availableOptionalCourses = availableOptionalCourses;
this.availabilities = availabilities;
this.courseTypeId = courseTypeId;
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var OptionalCourseListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name, startDates, duration, courseStartDay, courseEndDay, subtitle, position, availabilities, oneDayCourse, courseTypeId, additionalDays) {
this.id = id;
this.type = 'optional';
this.name = name;
this.startDates = startDates;
this.duration = duration;
this.courseStartDay = courseStartDay;
this.courseEndDay = courseEndDay;
this.subtitle = subtitle;
this.position = position;
this.availabilities = availabilities;
this.oneDayCourse = oneDayCourse;
this.courseTypeId = courseTypeId;
this.additionalDays = (additionalDays ? parseInt(additionalDays) : 0);
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var AccommodationOptionListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name, minimumDurationInWeeks, minimumNumberOfPeople, accommodationStartDay, accommodationEndDay, availabilities, noAccommodation, additionalNightsBefore, additionalNightsAfter, additionalNightsOnBounds) {
this.id = id;
this.name = name;
this.minimumDurationInWeeks = minimumDurationInWeeks;
this.minimumNumberOfPeople = minimumNumberOfPeople;
this.accommodationStartDay = accommodationStartDay;
this.accommodationEndDay = accommodationEndDay;
this.availabilities = availabilities;
this.noAccommodation = noAccommodation;
this.additionalNightsBefore = parseInt(additionalNightsBefore);
this.additionalNightsAfter = parseInt(additionalNightsAfter);
this.additionalNightsOnBounds = parseInt(additionalNightsOnBounds);
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var AccommodationListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name, option, availableTransfers, accommodationType ) {
this.id = id;
this.name = name;
this.option = option;
this.availableTransfers = availableTransfers;
this.accommodationType = accommodationType ? parseInt(accommodationType): 0;
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var TransferListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name, type) {
this.id = id;
this.name = name;
this.type = type;
}
});
/**
* This class is used for the price calculation functionalities
*
**/
var InsuranceListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name,defaultChecked, mandatory, availableFrom, mandatoryFrom, additionalMandatoryDays, durationCalculationMethod) {
this.id = parseInt(id);
this.name = name;
this.defaultChecked = (defaultChecked ? parseInt(defaultChecked) : 0);
this.mandatory =  (mandatory ? parseInt(mandatory) : 0);
this.availableFrom = (availableFrom ? parseInt(availableFrom) : 0);
this.mandatoryFrom = (mandatoryFrom ? parseInt(mandatoryFrom) : 0);
this.additionalMandatoryDays = (additionalMandatoryDays ? parseInt(additionalMandatoryDays) : 0);
this.durationCalculationMethod = (durationCalculationMethod ? parseInt(durationCalculationMethod) : 0);
}
});
/**
* This class is used for the price calculation functionalities
*
**/
var PromotionListItemDTO = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name, triggers) {
this.id = parseInt(id);
this.name = name;
this.triggers = triggers;
}
});
ď»ż/**
* This class is used for the price estimation functionnalities
*
* @author Yves-AndrĂ© Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param TransferListItemDTO schoolTransfersDTO the transfers informations
* @param Object translateDTO The DTO containing the translations for this class
* @param SchoolPriceEstimation parent the parent
**/
var SchoolSection = Events.extend({
/**
* This is the initialization function
*/
initialize : function(schoolItemsDTO, translateDTO, parent) {
this._schoolItemsDTO = schoolItemsDTO;
this._translateDTO = translateDTO;
this._parent = parent;
this._classNameBase = this.getParent().getClassNameBase();
this._items = new Array();
},
/**
* Returns the visual transfer container
*/
getHtml : function() {
this._container = new Element('div', {'class': this._classNameBase + 'Section'});
this._title = new Element('div', {'class': this._classNameBase + 'Section-Title'});
this._listContainer = new Element('div', {'class': this._classNameBase + 'Section-List-Container'});
this._addedItemsList = new Element('div', {'class': this._classNameBase + 'Section-List'});
this._addButton = new Element('div', {'class': this._classNameBase + 'Button' + ' ' + this._classNameBase + 'AddButton'});
this._title.injectInside(this._container);
this._listContainer.injectInside(this._container);
this._addedItemsList.injectInside(this._listContainer);
this._addButton.injectInside(this._container);
this._title.setHTML(this._translateDTO.title);
this._addButton.setHTML(this._translateDTO.add);
this._itemsList = new SchoolList(this._addButton, this._classNameBase);
this.getVisualItemsList(this._itemsList);
this._itemsList.getHtml().injectInside(this._parent.getListContainer());
this._itemsList.initializeEvents();
if(!this._schoolItemsDTO.length){
this._container.setStyle('display','none');
}
return this._container;
},
/**
*  Return the classNameBase
*/
getClassNameBase : function() {
return this._classNameBase;
},
/**
* Returns an array containing the informations for the calculation price
*
* @return Array The informations needed to calculate the price
*/
getDTO : function() {
var dto = new Array();
this._items.each(function(item, index) {
if (item.isComplete()) {
dto.push(item.getDTO());
}
});
return dto;
},
/**
* Retrieve the list of transfers for this school
*
* @param schoolList list The list to update
*/
getVisualItemsList : function(list) {
list.clear();
this._schoolItemsDTO.each(function(item, index) {
list.addItem(item.id, item.name);
list.getListItems().getLast().getHtml().addEvent('click', function() {
this.addItem(item.id);
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.notAvailable);
if (this._parent.getCompletedCourses().length > 0) {
if (this._schoolTransfersDTO.length) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setHtml(this._translateDTO.noTransfers);
list.getListItems().getLast().setIsValid(true);
}
} else {
list.getListItems().getLast().setHtml(this._translateDTO.notAvailable);
list.getListItems().getLast().setIsValid(true);
}
this.refreshVisualTransferList(list);
},
/**
* Returns the parent of this object
*
* @return SchoolPriceEstimation The parent
*/
getParent : function() {
return this._parent;
},
addItem : function(id){
var schoolItemsDTO = this._schoolItemsDTO.copy();
var schoolItem = schoolItemsDTO.filter(function(item, index) {
return item.id == id;
}.bind(this));
/*   var newItem = new SchoolItemObject(schoolItem[0].id, schoolItem[0].name, schoolItem[0].type, this._translateDTO.itemObject, this);
this._items.push(newItem);
newItem.createVisualItem();
this._items.getLast().getHtml().injectInside(this._addedItemsList);
newItem.addEvent('deleteItem', function(e) {
this.deleteItem(newItem);
}.bind(this));
this._parent.fireEvent('heightModified');
this._parent.fireEvent('refreshPrice');
*/
},
/**
* Display or hide the add button
*
* @param boolean isDisplayed True to display the hide button
*/
displayAddButton : function(isDisplayed) {
if (isDisplayed) {
this._addButton.setStyle('display', '');
} else {
this._addButton.setStyle('display', 'none');
}
},
/**
* Returns the number of completed transfers
*
* @return Number The number of completed transfers
*/
getCompletedItems : function() {
return this._items.length;
},
/**
* Delete the given transfer
*
* @param SchoolItemObject transfer The transfer to delete
*/
deleteItem : function(item) {
this._items.remove(item);
this._parent.fireEvent('heightModified');
this._parent.fireEvent('refreshPrice');
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-Andrďż˝ Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param TransferListItemDTO schoolTransfersDTO the transfers informations
* @param Object translateDTO The DTO containing the translations for this class
* @param SchoolPriceEstimation parent the parent
**/
var SchoolPromotions = SchoolSection.extend({
/**
* This is the initialization function
*/
initialize : function(schoolItemsDTO, translateDTO, parent) {
this.parent(schoolItemsDTO, translateDTO, parent);
this.promotions = new Array();
this._xhrValidate = new XHR();
this._xhrValidate.addEvent('onSuccess', function(e)
{
if(parseInt(e)){
// we can add the promotion
for(var i = 0; i < this.promotions.length; i++){
if(this.promotions[i] == parseInt(e)){
this.displayMessage(this._translateDTO.promotionAlreadyAdded);
this._parent.fireEvent('refreshPrice');
return 0;
}
}
this.promotions.push(parseInt(e));
this._parent.fireEvent('refreshPrice');
}else {
this.displayMessage(this._translateDTO.invalidCode);
}
}.bind(this));
},
/**
* Returns the visual transfer container
*/
getHtml : function() {
this._codeDefaultText = this._translateDTO.enterYourCode;
this._container = new Element('div', {'class': this._classNameBase + 'Section'});
this._title = new Element('div', {'class': this._classNameBase + 'Section-Title'});
this._listContainer = new Element('div', {'class': this._classNameBase + 'Section-List-Container'});
this._addedItemsList = new Element('div', {'class': this._classNameBase + 'Section-List'});
this._addButton = new Element('div', {'class': this._classNameBase + 'Button' + ' ' + this._classNameBase + 'AddButton PromotionAddButton'});
this._codeInput = new Element('input').setProperties({'type' : 'text', 'value' : this._codeDefaultText, 'class' : 'Synergee-Web-Page-Form-Text', 'id':'promotionInput'});
this._title.injectInside(this._container);
this._listContainer.injectInside(this._container);
this._addedItemsList.injectInside(this._listContainer);
this._codeInput.injectInside(this._container);
this._addButton.injectInside(this._container);
this._title.setHTML(this._translateDTO.title);
this._addButton.setHTML(this._translateDTO.add);
this._codeInput.addEvent('focus', function() {
if (this._codeInput.getProperty('value') == this._codeDefaultText)
this._codeInput.setProperty('value', '');
}.bind(this));
this._codeInput.addEvent('blur', function() {
if (this._codeInput.getProperty('value') == '')
this._codeInput.setProperty('value', this._codeDefaultText);
}.bind(this));
this._codeInput.addEvent('change', function(){
if(this._codeInput.getProperty('value') == '' || this._codeInput.getProperty('value') == this._codeDefaultText){
this._addButton.addClass('Disabled');
}else {
this._addButton.removeClass('Disabled');
}
}.bind(this));
this._addButton.addEvent('click', this.validateCode.bind(this));
if(!this._schoolItemsDTO.length){
this._container.setStyle('display','none');
}
return this._container;
},
displayMessage : function(message){
this._parent.displayMessage(message);
},
validateCode : function(){
if(this._codeInput.getProperty('value') != '' && this._codeInput.getProperty('value') != this._codeDefaultText){
this._xhrValidate.send(window.getCurrentJsonUrl(this._container), 'step=validateCode&code=' + this._codeInput.getProperty('value'));
}
},
getDTO : function(){
return this.promotions;
},
/**
* Populate the transfers from a dto
*/
populateFromDTO : function(toPopulateDTO) {
if (toPopulateDTO) {
this.promotions = toPopulateDTO;
}
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param TransferListItemDTO schoolTransfersDTO the transfers informations
* @param SchoolPriceEstimation parent the parent
**/
var SchoolSelector = Events.extend({
/**
* This is the initialization function
*
* @param Object translateDTO the object containing the translations for this class
* @param SchoolsListDTO schoolsList The Schools list
* @param Objec parent The class that calls this class
*/
initialize : function(translateDTO, schoolsList, parent, advancedSchoolSelector) {
this._translateDTO = translateDTO;
this._parent = parent;
this._schoolsList = schoolsList;
this._schoolsHash = new Hash();
this._cityCountryHash = new Hash();
if (advancedSchoolSelector) {
this._advancedSchoolSelector = true;
} else {
this._advancedSchoolSelector = false;
}
this._classNameBase = this._parent.getClassNameBase();
if (this._schoolsList.length == 1 && (!this._parent.getType || this._parent.getType() == 'PriceEstimation')) {
this._selectedSchoolId = this._schoolsList[0].schoolId;
} else {
this._selectedSchoolId = null;
}
},
/**
* return the visual transfer container
*/
getHtml : function() {
this._schoolSelectorContainer = new Element('div', {'class': this._classNameBase + 'Participants-Section ' + this._classNameBase + 'SchoolsSelector-Section'});
this._schoolSelectorTitle = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title ' + this._classNameBase + 'SchoolsSelector-Section-Title'});
this._schoolSelectorTitleText = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title-Text ' + this._classNameBase + 'SchoolsSelector-Section-Title-Text'});
this._schoolSelectorTitleText.injectInside(this._schoolSelectorTitle);
this._schoolSelectorButtonsContainer = new Element('ul', {'class': this._classNameBase + 'AddSchoolMenu'});
this._schoolSelectorTitle.injectInside(this._schoolSelectorContainer);
this._schoolSelectorTitleText.setHTML(this._translateDTO.school);
if (this._schoolsList.length > 0) {
if (this._advancedSchoolSelector) {
this.programs = new Hash();
for (var i = 0; i < this._schoolsList.length; i++) {
var programId = this._schoolsList[i].schoolProgramId;
var countryCode = this._schoolsList[i].schoolCountryCode;
var cityId = this._schoolsList[i].schoolCityId;
if (!this.programs.hasKey(programId)) {
var program = new Object();
program.name = this._schoolsList[i].schoolProgramName;
program.id = this._schoolsList[i].schoolProgramId;
program.countries = new Hash();
this.programs.set(this._schoolsList[i].schoolProgramId, program);
}
if (!this.programs.get(programId).countries.hasKey(countryCode)) {
var country = new Object();
country.name = this._schoolsList[i].schoolCountryName;
country.id = countryCode;
country.cities = new Hash();
this.programs.get(programId).countries.set(countryCode, country);
}
if (!this.programs.get(programId).countries.get(countryCode).cities.hasKey(cityId)) {
var city = new Object();
city.name = this._schoolsList[i].schoolCityName;
city.id = cityId;
city.schools = new Hash();
this.programs.get(programId).countries.get(countryCode).cities.set(cityId, city);
}
if (!this._cityCountryHash.hasKey(cityId)) {
this._cityCountryHash.set(cityId, countryCode)
}
if (!this.programs.get(programId).countries.get(countryCode).cities.get(cityId).schools.hasKey(this._schoolsList[i].schoolId)) {
var school = new Object();
school.name = this._schoolsList[i].schoolName;
school.id = this._schoolsList[i].schoolId;
if (!this._schoolsHash.hasKey(school.id)) {
this._schoolsHash.set(school.id, this._schoolsList[i]);
}
this.programs.get(programId).countries.get(countryCode).cities.get(cityId).schools.set(this._schoolsList[i].schoolId, school);
}
}
this._advancedSchoolSelectorContainer = new Element('div', {'class': this._classNameBase + 'SchoolsSelector-Section-Container AdvancedSchoolSelector'});
this._programSelectorContainer = new Element('div', {'class': this._classNameBase + 'Participants-Section ' + this._classNameBase + 'SchoolsSelector-Section AdvancedSchoolSelector SchoolSelectorProgram'});
this._programSelectorTitle = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title ' + this._classNameBase + 'SchoolsSelector-Section-Title AdvancedSchoolSelector SchoolSelectorProgram'});
this._programSelectorTitleText = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title-Text ' + this._classNameBase + 'SchoolsSelector-Section-Title-Text SchoolSelectorProgram'});
this._programSelectorTitleText.injectInside(this._programSelectorTitle);
this._programSelectorTitle.injectInside(this._programSelectorContainer);
this._programSelectorTitleText.setHTML(this._translateDTO.program);
this._programSelectorContainer.injectInside(this._advancedSchoolSelectorContainer);
this._programSelectorButtons = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._programSelectorButtons.addClass(this._classNameBase + 'SchoolSelectorButton ' + this._classNameBase + 'Section-Item-ToUpdate');
this._programSelectorButtons.setHTML(this._translateDTO.addProgram);
this._programSelectorButtons.defaultText = this._translateDTO.addProgram;
this._programSelectorButtons.injectInside(this._programSelectorTitle);
this._programSelectorsList = new SchoolList(this._programSelectorButtons, this._classNameBase);
this.createAdvancedList(this._programSelectorsList, this.programs, 'program');
this._programSelectorsList.getHtml().injectInside(this._parent.getListContainer());
this._programSelectorsList.initializeEvents();
this._countrySelectorContainer = new Element('div', {'class': this._classNameBase + 'Participants-Section ' + this._classNameBase + 'SchoolsSelector-Section AdvancedSchoolSelector SchoolSelectorCountry'});
this._countrySelectorTitle = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title ' + this._classNameBase + 'SchoolsSelector-Section-Title AdvancedSchoolSelector SchoolSelectorCountry'});
this._countrySelectorTitleText = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title-Text ' + this._classNameBase + 'SchoolsSelector-Section-Title-Text SchoolSelectorCountry'});
this._countrySelectorTitleText.injectInside(this._countrySelectorTitle);
this._countrySelectorTitle.injectInside(this._countrySelectorContainer);
this._countrySelectorTitleText.setHTML(this._translateDTO.country);
this._countrySelectorContainer.injectInside(this._advancedSchoolSelectorContainer);
this._countrySelectorButtons = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._countrySelectorButtons.addClass(this._classNameBase + 'SchoolSelectorButton ' + this._classNameBase + 'Section-Item-ToUpdate');
this._countrySelectorButtons.setHTML(this._translateDTO.addCountry);
this._countrySelectorButtons.defaultText = this._translateDTO.addCountry;
this._countrySelectorButtons.injectInside(this._countrySelectorTitle);
this._countrySelectorsList = new SchoolList(this._countrySelectorButtons, this._classNameBase);
this._citySelectorContainer = new Element('div', {'class': this._classNameBase + 'Participants-Section ' + this._classNameBase + 'SchoolsSelector-Section AdvancedSchoolSelector SchoolSelectorCity'});
this._citySelectorTitle = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title ' + this._classNameBase + 'SchoolsSelector-Section-Title AdvancedSchoolSelector SchoolSelectorCity'});
this._citySelectorTitleText = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title-Text ' + this._classNameBase + 'SchoolsSelector-Section-Title-Text SchoolSelectorCity'});
this._citySelectorTitleText.injectInside(this._citySelectorTitle);
this._citySelectorTitle.injectInside(this._citySelectorContainer);
this._citySelectorTitleText.setHTML(this._translateDTO.city);
this._citySelectorContainer.injectInside(this._advancedSchoolSelectorContainer);
this._citySelectorButtons = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._citySelectorButtons.addClass(this._classNameBase + 'SchoolSelectorButton ' + this._classNameBase + 'Section-Item-ToUpdate');
this._citySelectorButtons.setHTML(this._translateDTO.addCity);
this._citySelectorButtons.defaultText = this._translateDTO.addCity;
this._citySelectorButtons.injectInside(this._citySelectorTitle);
this._citySelectorsList = new SchoolList(this._citySelectorButtons, this._classNameBase);
this._schoolSelectorContainer = new Element('div', {'class': this._classNameBase + 'Participants-Section ' + this._classNameBase + 'SchoolsSelector-Section AdvancedSchoolSelector SchoolSelectorSchool'});
this._schoolSelectorTitle = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title ' + this._classNameBase + 'SchoolsSelector-Section-Title AdvancedSchoolSelector SchoolSelectorSchool'});
this._schoolSelectorTitleText = new Element('div', {'class': this._classNameBase + 'Participants-Section-Title-Text ' + this._classNameBase + 'SchoolsSelector-Section-Title-Text SchoolSelectorSchool'});
this._schoolSelectorTitleText.injectInside(this._schoolSelectorTitle);
this._schoolSelectorTitle.injectInside(this._schoolSelectorContainer);
this._schoolSelectorTitleText.setHTML(this._translateDTO.school);
this._schoolSelectorContainer.injectInside(this._advancedSchoolSelectorContainer);
this._schoolSelectorButtons = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._schoolSelectorButtons.addClass(this._classNameBase + 'SchoolSelectorButton ' + this._classNameBase + 'Section-Item-ToUpdate');
this._schoolSelectorButtons.setHTML(this._translateDTO.addSchool);
this._schoolSelectorButtons.defaultText = this._translateDTO.addSchool;
this._schoolSelectorButtons.injectInside(this._schoolSelectorTitle);
new Element('div', {'style': 'clear:both'}).injectInside(this._advancedSchoolSelectorContainer);
this._schoolSelectorsList = new SchoolList(this._schoolSelectorButtons, this._classNameBase);
// set to inactive the inactive menu
this.setActive(this._countrySelectorButtons, false);
this.setActive(this._citySelectorButtons, false);
this.setActive(this._schoolSelectorButtons, false);
if(this._programSelectorsList.getListItems().length == 1){
this._programSelectorsList.getListItems()[0].getHtml().fireEvent('click');
this._programSelectorContainer.addClass('Component-Booking-OneOption');
}
return this._advancedSchoolSelectorContainer;
} else {
this._schoolSelectorButtons = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._schoolSelectorButtons.addClass(this._classNameBase + 'SchoolSelectorButton ' + this._classNameBase + 'Section-Item-ToUpdate');
this._schoolSelectorButtons.setHTML(this._translateDTO.add);
this._schoolSelectorButtons.injectInside(this._schoolSelectorTitle);
this._schoolSelectorsList = new SchoolList(this._schoolSelectorButtons, this._classNameBase);
this.createVisualList(this._schoolSelectorsList);
if (this._schoolsList.length == 1) {
this._schoolSelectorContainer.setStyle('display', 'none');
}
this._schoolSelectorsList.getHtml().injectInside(this._parent.getListContainer());
this._schoolSelectorsList.initializeEvents();
}
} else {
this._schoolSelectorButtons.setHTML(this._translateDTO.noSchools);
this._schoolSelectorButtons.injectInside(this._schoolSelectorTitle);
}
return this._schoolSelectorContainer;
},
/**
* Generate the list of schoolSelectors
*
* @param SchoolList list The list to update
*/
createVisualList : function(list) {
for (var i = 0; i < this._schoolsList.length; i++) {
list.addItem(this._schoolsList[i].schoolId, this._schoolsList[i].schoolName + ' - ' + this._schoolsList[i].schoolCityName + ' - ' + this._schoolsList[i].schoolCountryName);
}
list.getListItems().each(function(item, index) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (item.getValue() == this._selectedSchoolId) {
list.setSelectedItem(item);
this._schoolSelectorButtons.setHTML(item.getHtmlValue());
}
item.getHtml().addEvent('click', function(event) {
this._schoolSelectorButtons.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
if (this._selectedSchoolId != item.getValue()) {
this._schoolSelectorButtons.setHTML(item.getHtmlValue());
this._selectedSchoolId = item.getValue();
this.fireEvent('changeSchool');
list.setSelectedItem(item);
}
}.bind(this));
}.bind(this));
},
sortFunction : function(a,b){
var a = a.name.toLowerCase();
var b = b.name.toLowerCase();
if (a < b) {
return -1;
} else if (a > b) {
return  1;
} else {
return 0;
}
},
/**
* Create the list for the advanced school selector
* @param list
* @param listItems
* @param eventFunction
*/
createAdvancedList : function(list, listItems, eventFunction) {
list.clear();
var orderedListItems = new Array();
listItems.each(function(item, index) {
orderedListItems.push(item);
}.bind(this));
orderedListItems.sort(this.sortFunction);
orderedListItems.each(function(item, index) {
list.addItem(item.id, item.name);
}.bind(this));
list.getListItems().each(function(item, index) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (item.getValue() == this._selectedSchoolId) {
list.setSelectedItem(item);
this._schoolSelectorButtons.setHTML(item.getHtmlValue());
}
item.getHtml().addEvent('click', function(e) {
if (eventFunction == 'program') {
this.programEventFunction(item);
}
if (eventFunction == 'country') {
this.countryEventFunction(item);
}
if (eventFunction == 'city') {
this.cityEventFunction(item);
}
if (eventFunction == 'school') {
this.schoolEventFunction(item);
}
}.bind(this));
}.bind(this));
},
/**
* Function called when program is changed
*
* @param SchoolListItem item The new item
*/
programEventFunction : function(item) {
if (this._selectedProgramId != item.getValue()) {
this._programSelectorButtons.setHTML(item.getHtmlValue());
this._selectedProgramId = item.getValue();
this._selectedCityId = null;
this._selectedCountryId = null;
this._selectedSchoolId = null;
this.setActive(this._countrySelectorButtons, false);
this.setActive(this._citySelectorButtons, false);
this.setActive(this._schoolSelectorButtons, false);
this.updateCountryList(this._selectedProgramId);
this.fireEvent('changeSchool');
}
},
/**
* Function called when the country change
* @param SchoolListItem item The new item
*/
countryEventFunction : function(item) {
if(this._selectedCountryId != item.getValue()){
this._countrySelectorButtons.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._countrySelectorButtons.setHTML(item.getHtmlValue());
this._selectedCountryId = item.getValue();
this._selectedCityId = null;
this._selectedSchoolId = null;
this.setActive(this._citySelectorButtons, false);
this.setActive(this._schoolSelectorButtons, false);
this.updateCityList(this._selectedProgramId, this._selectedCountryId);
this.fireEvent('changeSchool');
}
},
/**
* Function called when the city change
* @param SchoolListItem item The new item
*/
cityEventFunction : function(item) {
if(this._selectedCityId != item.getValue()){
this._citySelectorButtons.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._citySelectorButtons.setHTML(item.getHtmlValue());
this._selectedCityId = item.getValue();
this._selectedSchoolId = null;
this.setActive(this._schoolSelectorButtons, false);
this.updateSchoolList(this._selectedProgramId, this._selectedCountryId, this._selectedCityId);
this.fireEvent('changeSchool');
}
},
/**
* Function called when the school change
* @param SchoolListItem item The new item
*/
schoolEventFunction : function(item) {
if(this._selectedSchoolId != item.getValue()){
this._schoolSelectorButtons.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._schoolSelectorButtons.setHTML(item.getHtmlValue());
this._selectedSchoolId = item.getValue();
this.fireEvent('changeSchool');
}
},
/**
* Update the country list
*
* @param programId
*/
updateCountryList : function(programId) {
this.createAdvancedList(this._countrySelectorsList, this.programs.get(programId).countries, 'country');
this._countrySelectorsList.getHtml().injectInside(this._parent.getListContainer());
this._countrySelectorsList.initializeEvents();
this.setActive(this._countrySelectorButtons, true);
if(this._countrySelectorsList.getListItems().length == 1){
this._countrySelectorsList.getListItems()[0].getHtml().fireEvent('click');
this._countrySelectorContainer.addClass('Component-Booking-OneOption');
}
},
/**
* Update the city list
* @param programId
* @param country
*/
updateCityList : function(programId, country) {
this.createAdvancedList(this._citySelectorsList, this.programs.get(programId).countries.get(country).cities, 'city');
this._citySelectorsList.getHtml().injectInside(this._parent.getListContainer());
this._citySelectorsList.initializeEvents();
this.setActive(this._citySelectorButtons, true);
if(this._citySelectorsList.getListItems().length == 1){
this._citySelectorsList.getListItems()[0].getHtml().fireEvent('click');
this._citySelectorContainer.addClass('Component-Booking-OneOption');
}
},
/**
* Update the school list
*
* @param programId
* @param country
* @param city
*/
updateSchoolList : function(programId, country, city) {
this.createAdvancedList(this._schoolSelectorsList, this.programs.get(programId).countries.get(country).cities.get(city).schools, 'school');
this._schoolSelectorsList.getHtml().injectInside(this._parent.getListContainer());
this._schoolSelectorsList.initializeEvents();
this.setActive(this._schoolSelectorButtons, true);
if(this._schoolSelectorsList.getListItems().length == 1){
this._schoolSelectorsList.getListItems()[0].getHtml().fireEvent('click');
this._schoolSelectorContainer.addClass('Component-Booking-OneOption');
}
},
/**
* Update the selector with the given parameter
*
*
* @param integer school The School Id
* @param integer program The program Id
* @param string country The country code
* @param integer city The city Id
*/
updateSelector : function(school, program, country, city) {
if (school.toInt()) {
if (this._schoolsHash.hasKey(school)) {
var schoolObject = this._schoolsHash.get(school);
this.updateProgramSelector(schoolObject.schoolProgramId);
this.updateCountrySelector(schoolObject.schoolCountryCode);
this.updateCitySelector(schoolObject.schoolCityId);
this.updateSchoolSelector(school);
}
} else {
if (program.toInt()) {
this.updateProgramSelector(program);
if (country) {
this.updateCountrySelector(country);
}
if (city) {
if (!country) {
this.updateCountrySelector(this._cityCountryHash.get(city));
}
this.updateCitySelector(city);
}
}
}
},
/**
* Update the program selector
*
* @param integer program The program Id
*/
updateProgramSelector : function(program) {
this._programSelectorsList.getListItems().each(function(item, index) {
if (item.getValue().toInt() == program.toInt()) {
item.getHtml().fireEvent('click');
}
}.bind(this));
},
/**
* Update the Country selector
*
* @param string country The Country code
*/
updateCountrySelector : function(country) {
this._countrySelectorsList.getListItems().each(function(item, index) {
if (item.getValue() == country) {
item.getHtml().fireEvent('click');
}
}.bind(this));
},
/**
* Update the city selector
*
* @param integer city The city Id
*/
updateCitySelector : function(city) {
this._citySelectorsList.getListItems().each(function(item, index) {
if (item.getValue().toInt() == city.toInt()) {
item.getHtml().fireEvent('click');
}
}.bind(this));
},
/**
* Update the school selector
*
* @param integer school The school Id
*/
updateSchoolSelector : function(school) {
this._schoolSelectorsList.getListItems().each(function(item, index) {
if (item.getValue() == school) {
item.getHtml().fireEvent('click');
}
}.bind(this));
},
/**
* Set active the button given
* @param button
* @param boolean
*/
setActive : function(button, active) {
if (active) {
button.removeClass(this._classNameBase + 'SchoolSelectorButtonInactive');
button.getParent().getParent().setStyle('display','');
} else {
button.addClass(this._classNameBase + 'SchoolSelectorButtonInactive');
button.getParent().getParent().setStyle('display','none');
if(button.defaultText){
button.setHTML(button.defaultText);
}
}
},
/**
* Returns the number of schoolSelector
*
* @return number The number of schoolSelectors
*/
getSelectedSchoolId : function() {
return this._selectedSchoolId;
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param number id the transfer ID
* @param char name the transfer name
* @param SchoolTransfers parent
**/
var SchoolTransferObject = Events.extend({
/**
* This is the initialization function
*/
initialize : function(id, name, type,  translateDTO, parent) {
this._translateDTO = translateDTO;
this._transferName = name;
this._type = type;
this._transferId = id;
this._parent = parent;
this._classNameBase = this._parent.getClassNameBase();
this._isMandatory = false;
// transferType 1 for round trip, 2 for one way at arrival , 3 for one way to departure
this._transferTypeData = 1;
// true if roundtrip
this._roundTrip = 1;
},
/**
* Generate the Html structure of this transfer
*/
createVisualTransfer : function() {
this._container = new Element('div', {'class': this._classNameBase + 'ItemAdded'});
this._title = new Element('div', {'class': this._classNameBase + 'Section-Item-Title'});
this._transferTypeValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value'});
this._transferType = new Element('div').setProperties({'class': this._classNameBase + 'Section-Item-Info-Name TransferType'});
this._deleteButton = new Element('div', {'class': this._classNameBase + 'Section-Item-DeleteButton'});
this._title.injectInside(this._container);
this._transferType.injectInside(this._container);
this._transferTypeValue.injectInside(this._container);
this._deleteButton.injectInside(this._container);
this._clearElement = new Element('div');
this._clearElement.setStyle('clear', 'both');
this._clearElement.injectInside(this._container);
this._title.setHTML(this._transferName);
this._transferType.setHTML(this._translateDTO.transferType);
this._transferTypeValue.setHTML(this._translateDTO.roundTrip);
this._deleteButton.setHTML(this._translateDTO.deleteButton);
// add event listener
this._deleteButton.addEvent('click', function(e) {
this.removeTransfer();
this.fireEvent('deleteTransfer');
}.bind(this));
this._transferList = new SchoolList(this._title, this._classNameBase);
this.getVisualTransferList(this._transferList);
this._transferList.getHtml().injectInside(this._parent.getParent().getListContainer());
this._transferList.initializeEvents();
this._transfersList = new SchoolList(this._transferTypeValue, this._classNameBase);
this.getVisualTransferOptionsList(this._transfersList);
this._transfersList.getHtml().injectInside(this._parent.getParent().getListContainer());
this._transfersList.initializeEvents();
if(this._transfersList.getValidListItems().length == 1){
this._transferTypeValue.setAttribute('class', this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._transfersList.removeButtonEvent();
this._transfersList.getValidListItems()[0].getHtml().fireEvent('click');
}else{
this._transferTypeValue.setAttribute('class', this._classNameBase + 'Section-Item-Info-Value');
this._transfersList.addButtonEvent();
}
},
/**
* Returns an object containing the informations for the calculation price
*
* @return object The informations needed to calculate the price
*/
getDTO : function() {
var transferDTO = new Object();
transferDTO.id = this._transferId;
transferDTO.roundTrip = this._roundTrip;
transferDTO.transferType = this._transferTypeData;
return transferDTO;
},
/**
* Set this transfer mandatory
*
* @param Boolean isMandatory True if the transfer is mandatory
*/
setIsMandatoryTransfer : function(isMandatory) {
this._isMandatory = isMandatory;
if (this._isMandatory) {
this._deleteButton.setStyle('display', 'none');
} else {
this._deleteButton.setStyle('display', 'block');
}
},
/**
* Get this transfer mandatory
*
* @return Boolean True if mandatory
*/
getIsMandatoryTransfer : function() {
return this._isMandatory;
},
/**
* Return the transfer ID
*
* @return integer The Transfer ID
*/
getTransferId : function() {
return parseInt(this._transferId);
},
/**
* Populate the transfer from a dto
*/
populateFromDTO : function(toPopulateDTO) {
this._roundTrip = parseInt(toPopulateDTO.roundTrip);
if (!this._roundTrip) {
this._transferTypeValue.setHTML(this._translateDTO.oneWay);
} else {
this._transferTypeValue.setHTML(this._translateDTO.roundTrip);
}
},
/**
* Return true if the transfer is complete
*
* @return Boolean Return true if complete
*/
isComplete : function() {
if (this._roundTrip != -1) {
return true;
}
},
/**
* Returns the HTML structure of this course
*
* @return Element the transfer element
*/
getHtml : function() {
return this._container;
},
/**
* Generate the list of transfers for this school
*
* @param schoolList list The list to update
*/
getVisualTransferList : function(list) {
list.clear();
this._parent._schoolTransfersDTO.each(function(item, index) {
list.addItem(item.id, item.name);
list.getListItems().getLast().getHtml().addEvent('click', function() {
this.setTransfer(item);
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.notAvailable);
if (!this._parent._schoolTransfersDTO || this._parent.getParent().getCompletedCourses().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
this.refreshVisualTransferList();
},
/**
* refresh the list of transfers for this school
*
*/
refreshVisualTransferList : function() {
this._parent.refreshVisualTransferList(this._transferList);
},
/**
* Replace the transfer with the one given in parameter
*
* @param Object transfer The transfer DTO
*/
setTransfer : function(transfer) {
this._transferName = transfer.name;
this._transferId = transfer.id;
this._type = transfer.type;
this._title.setHTML(this._transferName);
if (this._transfersList._listItems.length) {
this._transfersList.getHtml().remove();
this._transfersList.clear();
}
this.getVisualTransferOptionsList(this._transfersList);
this._transfersList.getHtml().injectInside(this._parent.getParent().getListContainer());
this._transfersList.initializeEvents();
if(this._transfersList.getValidListItems().length == 1){
this._transferTypeValue.setAttribute('class', this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._transfersList.removeButtonEvent();
this._transfersList.getValidListItems()[0].getHtml().fireEvent('click');
}else{
this._transferTypeValue.setAttribute('class', this._classNameBase + 'Section-Item-Info-Value');
this._transfersList.addButtonEvent();
}
this._parent.getParent().fireEvent('refreshPrice');
},
/**
* Generate the options list for a transfer
* and set an event on each option
*
* @param SchoolList The list to update
*/
getVisualTransferOptionsList : function(list) {
list.clear();
if(this._type != 2 && this._type != 4){
list.addItem(0, this._translateDTO.oneWay);
}
if(this._type != 2 && this._type != 1){
list.addItem(2, this._translateDTO.wayBack);
}
if(this._type != 1 && this._type != 4){
list.addItem(1, this._translateDTO.roundTrip);
}
list.getListItems().each(function(item, index) {
item.getHtml().addClass(this._classNameBase + 'List-Item');
item.getHtml().addEvent('click', function() {
this._transferTypeValue.setHTML(item.getHtmlValue());
this._roundTrip = item.getValue();
this._transferTypeData = item.getValue();
this._parent.getParent().fireEvent('refreshPrice');
}.bind(this));
if((this._roundTrip == 1 && this._type == 1) || (this._roundTrip == 0 && this._type == 2)){
item.getHtml().fireEvent('click');
}
}.bind(this));
},
/**
* Remove the transfer from the list
*
*/
removeTransfer : function() {
this._transfersList.getHtml().remove();
this._container.remove();
}
});
/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @param TransferListItemDTO schoolTransfersDTO the transfers informations
* @param Object translateDTO The DTO containing the translations for this class
* @param SchoolPriceEstimation parent the parent
**/
var SchoolTransfers = Events.extend({
/**
* This is the initialization function
*/
initialize : function(schoolTransfersDTO, translateDTO, parent) {
this._schoolTransfersDTO = schoolTransfersDTO;
this._translateDTO = translateDTO;
this._parent = parent;
this._classNameBase = this.getParent().getClassNameBase();
this._transfers = new Array();
},
/**
* Returns the visual transfer container
*/
getHtml : function() {
this._transferContainer = new Element('div', {'class': this._classNameBase + 'Section'});
this._transferTitle = new Element('div', {'class': this._classNameBase + 'Section-Title'});
this._transferListContainer = new Element('div', {'class': this._classNameBase + 'Courses-CoursesList-Container'});
this._transferUserAccommodationList = new Element('div', {'class': this._classNameBase + 'Courses-UserCoursesList'});
this._transferAddButton = new Element('div', {'class': this._classNameBase + 'AddButton'});
this._transferTitle.injectInside(this._transferContainer);
this._transferListContainer.injectInside(this._transferContainer);
this._transferUserAccommodationList.injectInside(this._transferListContainer);
this._transferAddButton.injectInside(this._transferContainer);
this._transferTitle.setHTML(this._translateDTO.title);
this._transferAddButton.setHTML(this._translateDTO.add);
this._transfersList = new SchoolList(this._transferAddButton, this._classNameBase);
this.getVisualTransferList(this._transfersList);
this._transfersList.getHtml().injectInside(this._parent.getListContainer());
this._transfersList.initializeEvents();
if(!this._schoolTransfersDTO.length){
this._transferContainer.setStyle('display','none');
}
return this._transferContainer;
},
/**
*  Return the classNameBase
*/
getClassNameBase : function() {
return this._classNameBase;
},
/**
* Returns an array containing the informations for the calculation price
*
* @return Array The informations needed to calculate the price
*/
getDTO : function() {
var transfersDTO = new Array();
this._transfers.each(function(item, index) {
if (item.isComplete()) {
transfersDTO.push(item.getDTO());
}
});
return transfersDTO;
},
/**
* Populate the transfers from a dto
*/
populateFromDTO : function(toPopulateDTO) {
if (toPopulateDTO) {
toPopulateDTO.each(function(item, index) {
var transfer;
transfer = this._schoolTransfersDTO.filter(function(itemDTO, indexDTO) {
return itemDTO.id == item.id;
}.bind(this));
if (transfer[0]) {
for(var i = 0; i < this._transfers.length; i++){
if(parseInt(this._transfers[i]._transferId) == parseInt(transfer[0].id)){
this._transfers[i].removeTransfer();
this._transfers.remove(this._transfers[i]);
i--;
}
}
this.addTransfer(item.id);
this._transfers[this._transfers.length - 1].populateFromDTO(item);
}
}.bind(this));
}
},
/**
* Retrieve the list of transfers for this school
*
* @param schoolList list The list to update
*/
getVisualTransferList : function(list) {
list.clear();
this._schoolTransfersDTO.each(function(item, index) {
list.addItem(item.id, item.name);
list.getListItems().getLast().getHtml().addEvent('click', function() {
this.addTransfer(item.id);
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.notAvailable);
if (this._parent.getCompletedCourses().length > 0) {
if (this._schoolTransfersDTO.length) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setHtml(this._translateDTO.noTransfers);
list.getListItems().getLast().setIsValid(true);
}
} else {
list.getListItems().getLast().setHtml(this._translateDTO.notAvailable);
list.getListItems().getLast().setIsValid(true);
}
this.refreshVisualTransferList(list);
},
/**
* Refresh the list of transfers for this school
*
* @param schoolList list The list to update
*/
refreshVisualTransferList : function(list) {
var availableTransfers = this._parent.getAvailableTransfers();
list.getListItems().each(function(item, index) {
if ((!this._schoolTransfersDTO || this._parent.getCompletedCourses().length > 0) && availableTransfers.contains(parseInt(item.getValue()))) {
item.setIsValid(true);
item.setIsSelectionnable(true);
} else {
item.setIsValid(false);
}
}.bind(this));
if (this._parent.getCompletedCourses().length > 0) {
if (this._schoolTransfersDTO.length) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setHtml(this._translateDTO.noTransfers);
list.getListItems().getLast().setIsValid(true);
}
} else {
list.getListItems().getLast().setHtml(this._translateDTO.notAvailable);
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Refresh the transfers lists
*
*/
refreshTransfers : function() {
var transfNb = this._transfers.length;
this.refreshVisualTransferList(this._transfersList);
// refresh every transfer list for the added transfers
for (var i = 0; i < this._transfers.length; i++) {
this._transfers[i].refreshVisualTransferList();
}
if (this._parent.getCompletedCourses().length == 0) {
for (var i = this._transfers.length - 1; i >= 0; i--) {
this._transfers[i].removeTransfer();
this._transfers.remove(this._transfers[i]);
}
this._parent.fireEvent('heightModified');
if (transfNb > 0)this._parent.fireEvent('refreshPrice');
} else {
// get the available transfers List
var availableTransfers = this._parent.getAvailableTransfers();
// remove the unavailable transfers
this._transfers.each(function(item) {
if (!availableTransfers.contains(item.getTransferId())) {
item.removeTransfer();
this._transfers.remove(item);
}
}.bind(this));
// add transfers if they are mandatory
if (!this._transfers.length && availableTransfers.length && this._parent.getIsTransferMandatory()) {
var transfersToAdd = this._schoolTransfersDTO.filter(function(item) {
return  availableTransfers.contains(parseInt(item.id));
});
if (transfersToAdd.length) {
this.addTransfer(transfersToAdd[0].id);
} else {
this.addTransfer(availableTransfers[0]);
}
this._transfers[0].setIsMandatoryTransfer(true);
} else {
if (this._parent.getIsTransferMandatory() && this._transfers.length) {
this._transfers[0].setIsMandatoryTransfer(true);
}
}
}
if (!this._parent.getIsTransferMandatory()) {
for (var i = 0; i < this._transfers.length; i++) {
this._transfers[i].setIsMandatoryTransfer(false);
}
}
if ((this._parent.getIsTransferMandatory() == true && this._transfers.length) || this._parent.getCompletedAccommodations().length == 0) {
this.displayAddButton(false);
} else {
this.displayAddButton(true);
}
},
/**
* Add a transfer from its ID
*
* @param Number id The transfer id
*/
addTransfer : function(id) {
var schoolTransfersDTO = this._schoolTransfersDTO.copy();
var schoolTransfer = schoolTransfersDTO.filter(function(item, index) {
return item.id == id;
}.bind(this));
var newTransfer = new SchoolTransferObject(schoolTransfer[0].id, schoolTransfer[0].name, schoolTransfer[0].type, this._translateDTO.transferObject, this);
this._transfers.push(newTransfer);
newTransfer.createVisualTransfer();
this._transfers.getLast().getHtml().injectInside(this._transferUserAccommodationList);
newTransfer.addEvent('deleteTransfer', function(e) {
this.deleteTransfer(newTransfer);
}.bind(this));
this._parent.fireEvent('heightModified');
this._parent.fireEvent('refreshPrice');
},
/**
* Returns the parent of this object
*
* @return SchoolPriceEstimation The parent
*/
getParent : function() {
return this._parent;
},
/**
* Display or hide the add button
*
* @param boolean isDisplayed True to display the hide button
*/
displayAddButton : function(isDisplayed) {
if (isDisplayed) {
this._transferAddButton.setStyle('display', '');
} else {
this._transferAddButton.setStyle('display', 'none');
}
},
/**
* Returns the number of completed transfers
*
* @return Number The number of completed transfers
*/
getCompletedTransfers : function() {
return this._transfers.length;
},
/**
* Delete the given transfer
*
* @param SchoolTransferObject transfer The transfer to delete
*/
deleteTransfer : function(transfer) {
this._transfers.remove(transfer);
this._parent.fireEvent('heightModified');
this._parent.fireEvent('refreshPrice');
}
});/**
* This class is used for the price estimation functionnalities
*
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @event Event deleteCourse This event is fired when a course is deleted
*
* @param FixedDatesCourseListItemDTO courseDetails courseDetails The object containing the course informations
* @param Object translateDTO The object containing all the translations for this class
* @param SchoolCourses parent The parent
*
**/
var SchoolVariableCourseObject = Events.extend({
/**
* This is the initialization function
*
*/
initialize : function(courseDetails, translateDTO, listContainer, classNamePrefix, parent) {
this._translateDTO = translateDTO;
this._courseDetails = courseDetails;
this._parent = parent;
this._listContainer = listContainer;
this._classNameBase = classNamePrefix;
this._dateFormat = this._parent.getParent().getDateFormat();
this._monthsTranslations = this._parent.getParent().getMonthTranslations();
this._manager = this.getParent().getParent().getParent();
this._manager.addEvent('descriptionsUpdated', function(){
this.updateDescriptions();
}.bind(this));
this._courseStartDate = null;
this._courseEndDate = null;
this._courseDuration = null;
},
/**
* Return the course details DTO
*
* @return CourseDetailsDTO The course Details DTO
*/
getCourseDetails : function() {
return this._courseDetails;
},
/**
* Return true if the course is complete
*
* @return Boolean Return true if the course is complete
*/
isComplete : function() {
if (this._courseStartDate && this._courseEndDate && this._courseDuration) {
return true;
} else {
return false;
}
},
/**
* Generate the html structure of the course
* and add an event on the delete button
*
*/
createVisualCourse : function() {
this._container = new Element('div', {'class': this._classNameBase + 'ItemAdded'});
this._title = new Element('div', {'class': this._classNameBase + 'Section-Item-Title'});
this._subTitle = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle'});
this._moreInfo = new Element('div', {'class': this._classNameBase + 'Section-Item-SubTitle MoreInfos'});
this._moreInfo.setStyle('display','none');
this._startDateContainer = new Element('div',{'class': this._classNameBase + 'Section-Item-StartDate-Container'});
this._endDateContainer = new Element('div',{'class': this._classNameBase + 'Section-Item-EndDate-Container'});
this._startDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._startDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value ' + this._classNameBase + 'Section-Item-ToUpdate'});
this._endDate = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._endDateValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-ValueNotEditable'});
this._durationContainer = new Element('div',{'class': this._classNameBase + 'Section-Item-Duration-Container'});
this._duration = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Name'});
this._durationValue = new Element('div', {'class': this._classNameBase + 'Section-Item-Info-Value ' + this._classNameBase + 'Section-Item-ToUpdate'});
this._deleteButton = new Element('div', {'class': this._classNameBase + 'Section-Item-DeleteButton'});
this._duration.injectInside(this._durationContainer);
this._durationValue.injectInside(this._durationContainer);
this._startDate.injectInside(this._startDateContainer);
this._startDateValue.injectInside(this._startDateContainer);
this._endDate.injectInside(this._endDateContainer);
this._endDateValue.injectInside(this._endDateContainer);
this._title.injectInside(this._container);
this._moreInfo.injectInside(this._container);
this._subTitle.injectInside(this._container);
new Element('div',{'style':'clear:both'}).injectInside(this._container);
this._startDateContainer.injectInside(this._container);
this._endDateContainer.injectInside(this._container);
this._durationContainer.injectInside(this._container);
this._deleteButton.injectInside(this._container);
new Element('div',{'style':'clear:both'}).injectInside(this._container);
this._title.setHTML(this._courseDetails.name);
this._subTitle.setHTML(this._courseDetails.subtitle);
this._moreInfo.setHTML(this._translateDTO.moreInfos);
this._startDate.setHTML(this._translateDTO.startDate);
this._startDateValue.setHTML(this._translateDTO.dateSelect);
this._endDate.setHTML(this._translateDTO.endDate);
this._endDateValue.setHTML(this._translateDTO.endDateValue);
this._duration.setHTML(this._translateDTO.duration);
this._durationValue.setHTML(this._translateDTO.durationSelect);
this._deleteButton.setHTML(this._translateDTO.deleteButton);
this.updateDescriptions();
// add event listener
this._deleteButton.addEvent('click', function(e) {
this.removeCourse();
this.fireEvent('deleteCourse');
}.bind(this));
this._coursesValidList = new SchoolList(this._title, this._classNameBase);
this.getVisualValidCoursesList(this._coursesValidList);
this._coursesValidList.getHtml().injectInside(this._listContainer);
this._coursesValidList.initializeEvents();
this._schoolStartList = new SchoolList(this._startDateValue, this._classNameBase);
this.getVisualVariableCourseStartDates(this._courseDetails.startDates, this._schoolStartList);
this._schoolStartList.getHtml().injectInside(this._listContainer);
this._schoolStartList.initializeEvents();
this._schoolDurationList = new SchoolList(this._durationValue, this._classNameBase);
this.getVisualVariableCourseDurationList(this._courseDetails.duration, this._schoolDurationList);
this._schoolDurationList.getHtml().injectInside(this._listContainer);
this._schoolDurationList.initializeEvents();
this.refreshLists();
},
updateDescriptions : function(){
if (this._manager.getDescription && this._manager.getDescription('course', this._courseDetails.courseTypeId) && this._manager.getDescription('course', this._courseDetails.courseTypeId) != '') {
this._moreInfo.setAttribute('title', this._courseDetails.name + ' :: ' + this._manager.getDescription('course', this._courseDetails.courseTypeId));
this._moreInfo.setStyle('display','');
if(!this._descriptionToolTip ){
this._descriptionToolTip = new SynergeeTips(this._moreInfo, {'className':'PriceEstimationToolTip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
}else {
this._descriptionToolTip.build(this._moreInfo);
}
}else {
this._moreInfo.setStyle('display','none');
}
},
/**
* Returns the html Element of this course
*
* @return Element The HTML view of this course
*/
getHtml : function() {
return this._container;
},
/**
* return the course start date
*
* @return Date The course start date
*/
getCourseStartDate : function() {
return this._courseStartDate;
},
/**
* return the course start date
*
* @return Date The course start date
*/
getCourseEndDate : function() {
return this._courseEndDate;
},
/**
* return the accommodation end date for this course
*
* @return Date The accommodation end date date
*/
getAccommodationEndDate : function() {
var endDate = new Date(this._courseEndDate);
var endDateDay = endDate.getDay();
return endDate;
},
/**
* Return an object containing the informations for the calculation price
*
* @return Object The informations needed to calculate the price
*/
getDTO : function() {
var courseDTO = new Object();
courseDTO.id = this._courseDetails.id;
courseDTO.startDate = this._courseStartDate.toIso();
courseDTO.endDate = this._courseEndDate.toIso();
return courseDTO;
},
/**
* Populate the variable course from a dto
*
* @param Object The fixed course informations needed to populate
*/
populateFromDTO : function(toPopulateDTO) {
this._courseStartDate = (new Date()).fromIso(toPopulateDTO.startDate);
this._startDateValue.setHTML(this._courseStartDate.format(this._dateFormat , this._monthsTranslations));
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._courseEndDate = (new Date()).fromIso(toPopulateDTO.endDate);
this._courseDuration = this.getCalculatedDuration(this._courseStartDate, this._courseEndDate );
if(this._courseDetails.duration.length && this._courseDuration < parseInt(this._courseDetails.duration[0])) this._courseDuration = parseInt(this._courseDetails.duration[0]);
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
this._durationValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
// If the start and the duration are set,  the end date is calculated
if (this._courseStartDate && this._courseDuration) {
this._courseEndDate = this.getVariableCourseEndDate();
this._endDateValue.setHTML(this._courseEndDate.format(this._dateFormat , this._monthsTranslations));
}
// when the user selects only the start date, the duration is set with the minimal value
if (this._courseStartDate && !this._courseDuration) {
this._courseDuration = this._courseDetails.duration[0];
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
this._courseEndDate = this.getVariableCourseEndDate();
this._endDateValue.setHTML(this._courseEndDate.format(this._dateFormat , this._monthsTranslations));
}
},
/**
* Refresh all the lists of this course
*
*/
refreshLists : function() {
// add the list of courses that fit the start and end Date
this.refreshVisualValidCoursesList(this._coursesValidList);
// initialize the start date list and its event
this.refreshVisualVariableCourseStartDates(this._parent.getValidVariableCourseStartDate(this), this._schoolStartList);
// initialize the duration list and its event
this.refreshVisualVariableCourseDurationList(this._parent.getValidVariableCourseDuration(this), this._schoolDurationList);
// check if the buttons must be activated or not
if(this._schoolStartList.getValidListItems().length == 1 ){
this._startDateValue.addClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-Info-Value');
this._schoolStartList.removeButtonEvent();
if(this._courseStartDate != this._schoolStartList.getValidListItems()[0].getValue())this._schoolStartList.getValidListItems()[0].getHtml().fireEvent('click');
}else{
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._startDateValue.addClass(this._classNameBase + 'Section-Item-Info-Value');
this._schoolStartList.addButtonEvent();
}
if(this._schoolDurationList.getValidListItems().length == 1 ){
this._durationValue.addClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._durationValue.removeClass(this._classNameBase + 'Section-Item-Info-Value');
this._schoolDurationList.removeButtonEvent();
if(parseInt(this._courseDuration) != parseInt(this._schoolDurationList.getValidListItems()[0].getValue()))this._schoolDurationList.getValidListItems()[0].getHtml().fireEvent('click');
}else{
this._durationValue.addClass(this._classNameBase + 'Section-Item-Info-Value');
this._durationValue.removeClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this._schoolDurationList.addButtonEvent();
}
},
/**
* Generate all the lists of this course
*
*/
reGenerateLists : function() {
// remove old list if exists
if (this._coursesValidList._listItems.length) {
this._coursesValidList.getHtml().remove();
this._coursesValidList.clear();
}
if (this._schoolStartList._listItems.length) {
this._schoolStartList.getHtml().remove();
this._schoolStartList.clear();
}
if (this._schoolDurationList._listItems.length) {
this._schoolDurationList.getHtml().remove();
this._schoolDurationList.clear();
}
this.getVisualValidCoursesList(this._coursesValidList);
this._coursesValidList.getHtml().injectInside(this._listContainer);
this._coursesValidList.initializeEvents();
this.getVisualVariableCourseStartDates(this._courseDetails.startDates, this._schoolStartList);
this.refreshVisualVariableCourseStartDates(this._parent.getValidVariableCourseStartDate(this), this._schoolStartList);
this._schoolStartList.getHtml().injectInside(this._listContainer);
this._schoolStartList.initializeEvents();
this.getVisualVariableCourseDurationList(this._courseDetails.duration, this._schoolDurationList);
this.refreshVisualVariableCourseDurationList(this._parent.getValidVariableCourseDuration(this), this._schoolDurationList);
this._schoolDurationList.getHtml().injectInside(this._listContainer);
this._schoolDurationList.initializeEvents();
},
/**
* Refresh the course data
*
*/
refreshVariableCourseData : function() {
// If the start and the duration are set,  the end date is calculated
if (this._courseStartDate && this._courseDuration) {
this._durationValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._courseEndDate = this.getVariableCourseEndDate();
this._endDateValue.setHTML(this._courseEndDate.format(this._dateFormat , this._monthsTranslations));
}
// when the user selects only the start date
if (this._courseStartDate && !this._courseDuration) {
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
if(this._courseDuration){
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
this._courseEndDate = this.getVariableCourseEndDate();
this._endDateValue.setHTML(this._courseEndDate.format(this._dateFormat , this._monthsTranslations));
}else {
this.refreshVisualVariableCourseDurationList(this._parent.getValidVariableCourseDuration(this), this._schoolDurationList);
}
}
if (this.isComplete()) {
this._durationValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
this._startDateValue.removeClass(this._classNameBase + 'Section-Item-ToUpdate');
// refresh the course list
this._parent.fireEvent('refreshCourses');
this._parent.fireEvent('refreshPrice');
}
},
/**
*  Returns the endDate of a variable course
*
*  @return Date The variable course end date
*/
getVariableCourseEndDate : function() {
var endDate = new Date(this._courseStartDate.getFullYear(), this._courseStartDate.getMonth(), this._courseStartDate.getDate() + this._courseDuration * 7 + 2);
var endDateDay = endDate.getDay();
if (endDateDay == 0) endDateDay = 7;
while (endDateDay != this._courseDetails.courseEndDay) {
endDate.setDate(endDate.getDate() - 1);
endDateDay = endDate.getDay();
if (endDateDay == 0) endDateDay = 7;
}
return endDate;
},
/**
* Replace the courses and find the best possible dates
*
* @param Object The new course DTO
*/
replaceCourse : function(newCourse) {
this._durationValue.removeClass(this._classNameBase + 'Section-Item-Info-Value');
if (!this._parent.getIsFixedCourse(newCourse)) {
if (this.isComplete()) {
this._courseDetails = newCourse;
this._durationValue.addClass(this._classNameBase + 'Section-Item-Info-Value');
this.replaceVariableCourseDates(this._courseStartDate, this._courseDuration);
this._title.setHTML(this._courseDetails.name);
this._subTitle.setHTML(this._courseDetails.subtitle);
this.reGenerateLists();
this._parent.fireEvent('refreshCourses');
} else {
this._schoolStartList.getHtml().remove();
this._schoolDurationList.getHtml().remove();
this._coursesValidList.getHtml().remove();
this._parent.replaceCourse(this, newCourse);
}
} else {
this._schoolStartList.getHtml().remove();
this._schoolDurationList.getHtml().remove();
this._coursesValidList.getHtml().remove();
if (this.isComplete()) {
this._parent.replaceCourse(this, newCourse, this._courseStartDate);
} else {
this._parent.replaceCourse(this, newCourse);
}
}
this.updateDescriptions();
},
/**
* this method find the best dates and duration for the new variable course based on the old one
*
* @param Date oldStartDate the date of the replaced course
* @param number oldDuration the duration of the replaced course
*/
replaceVariableCourseDates : function(oldStartDate, oldDuration) {
// if the start date is already set
if (oldStartDate) {
var dateDifference = null;
var newDate;
this._courseDetails.startDates.each(function(item, index) {
if (dateDifference > Math.abs(oldStartDate.getTime() - item.getTime()) || dateDifference == null) {
dateDifference = Math.abs(oldStartDate.getTime() - item.getTime());
newDate = item;
}
});
// if there is already a duration set
if (oldDuration) {
var durationDifference = null;
var newDuration;
this._courseDetails.duration.each(function(item, index) {
if (durationDifference > Math.abs(oldDuration - item) || durationDifference == null) {
durationDifference = Math.abs(oldDuration - item);
newDuration = item;
}
});
this._courseDuration = newDuration;
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
}
this._courseStartDate = newDate;
this._startDateValue.setHTML(newDate.format(this._dateFormat , this._monthsTranslations));
this.refreshVariableCourseData();
}
},
/**
* Generate a list of valid course
*
* @param SchoolList list The valid courses list
*
*/
getVisualValidCoursesList : function(list) {
var validCourses = this._parent.getCourses();
// clearing the list
list.clear();
validCourses.each(function(item, index) {
list.addItem(item, item.name);
list.getListItems().getLast().getHtml().addClass(this._classNameBase + 'List-Item');
list.getListItems().getLast().getHtml().addEvent('click', function() {
this.replaceCourse(item);
}.bind(this));
}, this);
this.refreshVisualValidCoursesList(list);
},
/**
* Refresh a list of course that have possible dates between this courseStartDate and courseEndDate
*
* @param SchoolList list The courses list
*
*/
refreshVisualValidCoursesList : function(list) {
var validCourses = this._parent.getValidCourses(this);
list.getListItems().each(function(item, index) {
if (validCourses.indexOf(item.getValue()) != -1) {
item.setIsValid(true);
} else {
item.setIsValid(false);
}
}.bind(this));
},
/**
* This function set a formated list from an array of a course start dates
*
* @param Array startDates An array of Date containing all the possible startDates
* @param SchoolList list The valid courses list
*/
getVisualVariableCourseStartDates : function(startDates, list) {
// clearing the list
list.clear();
startDates.each(function(item, index) {
list.addItem(item, item.format(this._dateFormat , this._monthsTranslations));
index = list.getListItems().indexOf(list.getListItems().getLast());
list.getListItems().getLast().getHtml().addEvent('click', function() {
if (list.getListItems()[index].getIsSelectionnable()) {
// Set the variables for this course
this._courseStartDate = item;
// set the visual data of this course
this._startDateValue.setHTML(item.format(this._dateFormat , this._monthsTranslations));
this.refreshVariableCourseData();
}
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.noValidStartDates);
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* this function refresh a list from an array of a course start dates
*
* @param Array validStartDates an array of Date containing the validated startDates
* @param SchoolList list the valid courses list
*/
refreshVisualVariableCourseStartDates : function(validStartDate, list) {
var firstValid = true;
list.getListItems().each(function(item, index) {
if (validStartDate.indexOf(item.getValue()) != -1) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (firstValid) {
list.setSelectedItem(item);
}
if (this._courseStartDate == item.getValue()) {
list.setSelectedItem(item);
}
firstValid = false;
} else {
if (item.getValue == 'error') {
item.setIsValid(false);
}
item.setIsSelectionnable(false);
}
}.bind(this));
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* This function return a formated list from an array of duration
*
* @param Array durations An array of Date containing the startDates
* @param Array validDurations An array of number containing the validated durations
*/
getVisualVariableCourseDurationList : function(durations, list) {
// clearing the list
list.clear();
durations.each(function(item, index) {
if (item > 1) {
list.addItem(item, this._translateDTO.weeks.replace('%0', item));
} else {
list.addItem(item, this._translateDTO.week.replace('%0', item));
}
index = list.getListItems().indexOf(list.getListItems().getLast());
// adding the event on the valid courses
list.getListItems().getLast().getHtml().addEvent('click', function() {
if (list.getListItems()[index].getIsSelectionnable()) {
this._courseDuration = item;
if (this._courseDuration > 1) {
this._durationValue.setHTML(this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.setHTML(this._translateDTO.week.replace("%0", this._courseDuration));
}
this.refreshVariableCourseData();
}
}.bind(this));
}.bind(this));
list.addItem('error', this._translateDTO.noValidDuration);
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* This function return a formated list from an array of duration
*
* @param Array validDurations An array of number containing the validated durations
* @param SchoolList list The list to refresh
*/
refreshVisualVariableCourseDurationList : function(validDurations, list) {
var firstValid = true;
var lastValid = null;
list.getListItems().each(function(item, index) {
if (validDurations.indexOf(item.getValue()) != -1) {
item.setIsValid(true);
item.setIsSelectionnable(true);
if (firstValid)list.setSelectedItem(item);
if (this._courseDuration == item.getValue()) list.setSelectedItem(item);
firstValid = false;
lastValid = item;
} else {
if (item.getValue == 'error')item.setIsValid(false);
item.setIsSelectionnable(false);
if(this._courseDuration == item.getValue()){
if(lastValid)lastValid.getHtml().fireEvent('click');
}
}
}.bind(this));
if (list.getValidListItems().length > 0) {
list.getListItems().getLast().setIsValid(false);
} else {
list.getListItems().getLast().setIsValid(true);
}
},
/**
* Return the duration in weeks.
* To perform the calculation we count the number of time the week day of the start date
* can be repeated between the start date and the end date.
*
* @param date startDate The start date
* @param date endDate The end date
* @return integer the number of weeks
*/
getCalculatedDuration : function(startDate, endDate) {
startDate = startDate.getTime();
endDate = endDate.getTime() - (86400 * 2 * 1000);
var numberOfWeeks = 0;
while(startDate <= endDate) {
numberOfWeeks++;
startDate += (86400 * 7 * 1000);
}
return numberOfWeeks;
},
/**
*  Returns the available accommodations for this course
*
* @return Array of integer The Accommodation IDs
*/
getAvailableAccommodations : function() {
return this._courseDetails.availableAccommodations;
},
/**
*  return the course duration
*
* @return integer The course duration
*/
getCourseDuration : function() {
return this._courseDuration;
},
/**
* Returns false is it's not a fixed course
*
* @return Boolean Return false because it's a variable course
*/
getIsFixedCourse : function() {
return false;
},
/**
* return the parent
*
* @return SchoolCourses The parent
*/
getParent : function() {
return this._parent;
},
/**
* Remove the course from the list
*
*/
removeCourse : function() {
this._schoolStartList.getHtml().remove();
this._schoolDurationList.getHtml().remove();
this._coursesValidList.getHtml().remove();
this._container.remove();
}
});
var Lightbox={init:function(options){this.options=Object.extend({resizeDuration:400,resizeTransition:Fx.Transitions.sineInOut,initialWidth:250,initialHeight:250,animateCaption:true,defaultIframeWidth:500,defaultIframeHeight:300},options||{});if(window.ie6&&document.compatMode=="BackCompat"){this.options.animateCaption=false}this.anchors=[];$each(document.links,function(el){if(el.rel&&el.rel.test(/^lightbox/i)){el.onclick=this.click.pass(el,this);this.anchors.push(el)}},this);this.eventKeyDown=this.keyboardListener.bindAsEventListener(this);this.eventPosition=this.position.bind(this);this.overlay=new Element("div").setProperty("id","lbOverlay").injectInside(document.body);this.center=new Element("div").setProperty("id","lbCenter").setStyles({width:this.options.initialWidth+"px",height:this.options.initialHeight+"px",marginLeft:"-"+(this.options.initialWidth/2)+"px",display:"none"}).injectInside(document.body);this.canvas=new Element("div").setProperty("id","lbCanvas").injectInside(this.center);new Element("a").setProperties({id:"lbCloseLinkTop",href:"#"}).injectInside(this.canvas).onclick=this.overlay.onclick=this.close.bind(this);this.prevLink=new Element("a").setProperties({id:"lbPrevLink",href:"#"}).setStyle("display","none").injectInside(this.canvas);this.nextLink=this.prevLink.clone().setProperty("id","lbNextLink").injectInside(this.canvas);this.prevLink.onclick=this.previous.bind(this);this.nextLink.onclick=this.next.bind(this);this.bottomContainer=new Element("div").setProperty("id","lbBottomContainer").setStyle("display","none").injectInside(document.body);this.bottom=new Element("div").setProperty("id","lbBottom").injectInside(this.bottomContainer);new Element("a").setProperties({id:"lbCloseLink",href:"#"}).injectInside(this.bottom).onclick=this.overlay.onclick=this.close.bind(this);this.caption=new Element("div").setProperty("id","lbCaption").injectInside(this.bottom);this.number=new Element("div").setProperty("id","lbNumber").injectInside(this.bottom);new Element("div").setStyle("clear","both").injectInside(this.bottom);var nextEffect=this.nextEffect.bind(this);this.fx={overlay:this.overlay.effect("opacity",{duration:500}).hide(),resizeCenter:this.center.effects({duration:this.options.resizeDuration,transition:this.options.resizeTransition,onComplete:nextEffect}),image:this.canvas.effect("opacity",{duration:500,onComplete:nextEffect}),bottom:this.bottomContainer.effect("height",{duration:400,onComplete:nextEffect})};this.preloadPrev=new Image();this.preloadNext=new Image()},click:function(link){if(link.rel.length==8){return this.show(link.href,link.title,link.rev)}var j,itemNumber,items=[];this.anchors.each(function(el){if(el.rel==link.rel){for(j=0;j<items.length;j++){if(items[j][0]==el.href&&items[j][2]==el.rev){break}}if(j==items.length){items.push([el.href,el.title,el.rev]);if(el.href==link.href&&el.rev==link.rev){itemNumber=j}}}},this);return this.open(items,itemNumber)},show:function(url,title,rev){return this.open([[url,title,rev]],0)},open:function(items,itemNumber){this.items=items;this.position();this.setup(true);var wh=(window.getHeight()==0)?window.getScrollHeight():window.getHeight();var st=document.body.scrollTop||document.documentElement.scrollTop;var rev=this.items[0][2];var height=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),600);this.top=st+((wh-(height))/2)-30;this.center.setStyles({top:this.top+"px",display:""});this.fx.overlay.start(0.8);return this.changeItem(itemNumber)},position:function(){var ww=(window.getWidth()==0)?window.getScrollWidth()-22:window.getWidth();var wh=(window.getHeight()==0)?window.getScrollHeight():window.getHeight();var st=document.body.scrollTop||document.documentElement.scrollTop;this.overlay.setStyles({top:st+"px",height:wh+"px",width:ww+"px"})},setup:function(open){var elements=$A(document.getElementsByTagName("object"));if(window.ie){elements.extend(document.getElementsByTagName("select"))}elements.each(function(el){el.style.visibility=open?"hidden":""});var fn=open?"addEvent":"removeEvent";window[fn]("scroll",this.eventPosition)[fn]("resize",this.eventPosition);document[fn]("keydown",this.eventKeyDown);this.step=0},keyboardListener:function(event){switch(event.keyCode){case 27:case 88:case 67:this.close();break;case 37:case 80:this.previous();break;case 39:case 78:this.next()}},previous:function(){return this.changeItem(this.activeItem-1)},next:function(){return this.changeItem(this.activeItem+1)},changeItem:function(itemNumber){if(this.step||(itemNumber<0)||(itemNumber>=this.items.length)){return false}this.step=1;this.activeItem=itemNumber;this.bottomContainer.style.display=this.prevLink.style.display=this.nextLink.style.display="none";this.fx.image.hide();this.center.className="lbLoading";this.removeCurrentItem();var url=this.items[this.activeItem][0];var rev=this.items[this.activeItem][2];var re_imageURL=/\.(jpe?g|png|gif|bmp)/i;var re_flashURL=/\.(swf)/i;var re_youtubeURL=/http\:\/\/(?:www\.){0,1}youtube\.com\/watch\?v=(.*)?/i;var re_dailymotionURL=/^http\:\/\/(?:www\.){0,1}dailymotion\.com\/video\/(.*?)\_/i;var re_streamURL=/stream\.(php)/i;var re_externalStreamURL=/^http\:\/\/(.*).(mp4|flv)/i;var re_downloadURL=/download\.php\?ressource=(.*)\&filename=(.*)/i;var re_hiddenDivURL=/\{hiddenId\|(\w+)\}/i;var matches=null;if(url.match(re_imageURL)){this.preload=new Image();this.preload.datatype="image";this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+%?)","i"),-1);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+%?)","i"),-1);this.preload.onload=this.nextEffect.bind(this);this.preload.src=url}else{if(url.match(re_flashURL)){this.preload=new Object();this.preload.datatype="flash";this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+)","i"),425);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),355);this.preload.src=url;this.nextEffect()}else{if(url.match(re_streamURL)){this.preload=new Object();this.preload.datatype="stream";this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+)","i"),425);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),355);this.preload.src=url;this.nextEffect()}else{if(matches=url.match(re_downloadURL)){this.preload=new Object();if(matches[2].match(/\.flv/)||matches[2].match(/\.mp4/)){this.preload.src="stream.php?media="+matches[2];this.preload.datatype="stream"}else{this.preload.src="ressource.php?media="+matches[2];this.preload.datatype="iframe"}this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+)","i"),425);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),355);this.nextEffect()}else{if(matches=url.match(re_youtubeURL)){this.preload=new Object();this.preload.datatype="youtube";this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+)","i"),this.options.defaultIframeWidth);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),this.options.defaultIframeHeight);this.preload.src=matches[1];this.nextEffect()}else{if(matches=url.match(re_dailymotionURL)){this.preload=new Object();this.preload.datatype="dailymotion";this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+)","i"),this.options.defaultIframeWidth);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),this.options.defaultIframeHeight);this.preload.src=matches[1];this.nextEffect()}else{if(matches=url.match(re_hiddenDivURL)){this.preload=new Object();this.preload.datatype="hidden";this.preload.src=matches[1];this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+)","i"),this.options.defaultIframeWidth);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),this.options.defaultIframeHeight);this.nextEffect()}else{if(matches=url.match(re_externalStreamURL)){this.preload=new Object();this.preload.src=url;this.preload.datatype="stream";this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+)","i"),425);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),355);this.nextEffect()}else{this.preload=new Object();this.preload.datatype="iframe";this.preload.w=this.matchOrDefault(rev,new RegExp("width=(\\d+)","i"),this.options.defaultIframeWidth);this.preload.h=this.matchOrDefault(rev,new RegExp("height=(\\d+)","i"),this.options.defaultIframeHeight);this.preload.src=url;this.nextEffect()}}}}}}}}return false},nextEffect:function(){switch(this.step++){case 1:this.center.className="";if(this.preload.datatype=="image"){var ws=(this.preload.w==-1)?this.preload.width.toString():this.preload.w.toString();var hs=(this.preload.h==-1)?this.preload.height.toString():this.preload.h.toString();this.p_width=(q=ws.match(/(\d+)%/))?q[1]*this.preload.width*0.01:ws;this.p_height=(q=hs.match(/(\d+)%/))?q[1]*this.preload.height*0.01:hs;new Element("img").setProperties({id:"lbImage",src:this.preload.src,width:this.p_width,height:this.p_height}).injectInside(this.canvas);this.nextLink.style.right=""}else{if(this.preload.datatype=="youtube"){this.p_width=this.preload.w;this.p_height=this.preload.h;var so=new SWFObject("http://www.youtube.com/v/"+this.preload.src+"&rel=0&autoplay=1&enablejsapi=1&playerapiid=lbYoutube","lbYoutubePlayer",this.p_width,this.p_height,"8","#FFFFFF");new Element("div").setProperties({id:"lbYoutube"}).injectInside(this.canvas);so.write("lbYoutube")}else{if(this.preload.datatype=="dailymotion"){this.p_width=this.preload.w;this.p_height=this.preload.h;var so=new SWFObject("http://www.dailymotion.com/swf/"+this.preload.src+"&v3=1&related=0&autoplay=1","lbDailymotionPlayer",this.p_width,this.p_height,"8","#FFFFFF");new Element("div").setProperties({id:"lbDailymotion"}).injectInside(this.canvas);so.write("lbDailymotion")}else{if(this.preload.datatype=="stream"){this.p_width=this.preload.w;this.p_height=this.preload.h;var so=new SWFObject(window.getCurrentPageLocation()+"Themes/Default/Components/Video/Flash/mediaplayer.swf","lbStreamPlayer",this.p_width,this.p_height,"8","#FFFFFF");so.addParam("allowfullscreen","true");so.addVariable("type","flv");so.addVariable("displayheight",this.p_height);so.addVariable("file",this.preload.src);so.addVariable("enablejs","true");so.addVariable("overstretch","true");new Element("div").setProperties({id:"lbStream"}).injectInside(this.canvas);so.write("lbStream")}else{if(this.preload.datatype=="flash"){this.p_width=this.preload.w;this.p_height=this.preload.h;var so=new SWFObject(this.preload.src,"lbFlashPlayer",this.p_width,this.p_height,"8","#FFFFFF");new Element("div").setProperties({id:"lbFlash"}).injectInside(this.canvas);so.write("lbFlash")}else{if(this.preload.datatype=="googleMap"){this.p_width=this.preload.w;this.p_height=this.preload.h;this.iframeId="mapContainer";new Element("iframe").setProperties({id:this.iframeId,width:this.p_width,height:this.p_height,frameBorder:0,scrolling:"auto",src:this.preload.src+"&output=embed&s=AARTsJrrJfAezwFwvFA6u8OWSecjpwNIVw"}).injectInside(this.canvas);this.nextLinkscr.style.right="25px"}else{if(this.preload.datatype=="hidden"){this.p_width=this.preload.w;this.p_height=this.preload.h;this.iframeId=this.preload.src;$(this.iframeId).setStyles({left:"0px",top:"0px",height:this.p_height,width:this.p_width,display:"block"});$(this.preload.src).setProperties({width:this.p_width,height:this.p_height,frameBorder:0,scrolling:"auto"}).injectInside(this.canvas);this.nextLink.style.right="25px"}else{this.p_width=this.preload.w;this.p_height=this.preload.h;this.iframeId="lbFrame_"+new Date().getTime();try{new Element("iframe").setProperties({id:this.iframeId,width:this.p_width,height:this.p_height,frameBorder:0,scrolling:"auto",src:this.preload.src}).injectInside(this.canvas)}catch(ex){}this.nextLink.style.right="25px"}}}}}}}this.canvas.style.width=this.bottom.style.width=this.p_width+"px";this.canvas.style.height=this.prevLink.style.height=this.nextLink.style.height=this.p_height+"px";this.caption.setHTML(this.items[this.activeItem][1]||"");this.number.setHTML((this.items.length==1)?"":"Page "+(this.activeItem+1)+" of "+this.items.length);if(this.activeItem){this.preloadPrev.src=this.items[this.activeItem-1][0]}if(this.activeItem!=(this.items.length-1)){this.preloadNext.src=this.items[this.activeItem+1][0]}if(this.center.clientHeight!=this.canvas.offsetHeight){var oh=(this.p_height==this.canvas.clientHeight)?this.canvas.offsetHeight:eval(this.p_height)+18;this.fx.resizeCenter.start({height:oh});break}this.step++;case 2:if(this.center.clientWidth!=this.canvas.offsetWidth){var ow=(this.p_width==this.canvas.clientWidth)?this.canvas.offsetWidth:eval(this.p_width)+18;this.fx.resizeCenter.start({width:ow,marginLeft:-ow/2});break}this.step++;case 3:this.bottomContainer.setStyles({top:(this.top+this.center.clientHeight)+"px",height:"0px",marginLeft:this.center.style.marginLeft,width:this.center.style.width,display:""});this.fx.image.start(1);break;case 4:if(this.options.animateCaption){this.fx.bottom.start(0,this.bottom.offsetHeight+10);break}this.bottomContainer.style.height=(this.bottom.offsetHeight+10)+"px";case 5:if(this.activeItem){this.prevLink.style.display=""}if(this.activeItem!=(this.items.length-1)){this.nextLink.style.display=""}if(this.preload.datatype=="stream"){try{$("lbStreamPlayer").sendEvent("playpause")}catch(ex){}}else{if(this.preload.datatype=="youtube"){try{$("lbYoutube").playVideo()}catch(ex){}}}window.fireEvent("slimboxready");this.step=0}},close:function(){if(this.step<0){return}this.step=-1;this.removeCurrentItem();for(var f in this.fx){this.fx[f].stop()}this.center.style.display=this.bottomContainer.style.display="none";this.center.style.width=this.options.initialWidth+"px";this.center.style.height=this.options.initialHeight+"px";this.center.style.marginLeft="-"+(this.options.initialWidth/2)+"px";this.fx.overlay.chain(this.setup.pass(false,this)).start(0);return false},removeCurrentItem:function(){if(this.preload){if(this.preload.datatype=="image"){$("lbImage").remove();this.preload.onload=Class.empty}else{if(this.preload.datatype=="youtube"){$("lbYoutubePlayer").parentNode.removeChild($("lbYoutubePlayer"))}else{if(this.preload.datatype=="dailymotion"){$("lbDailymotionPlayer").parentNode.removeChild($("lbDailymotionPlayer"))}else{if(this.preload.datatype=="flash"){$("lbFlashPlayer").parentNode.removeChild($("lbFlashPlayer"))}else{if(this.preload.datatype=="stream"){$("lbStreamPlayer").parentNode.removeChild($("lbStreamPlayer"))}else{if(this.preload.datatype=="googleMap"){$(this.iframeId).remove()}else{if(this.preload.datatype=="hidden"){$(this.iframeId).setStyle("display","none")}else{$(this.iframeId).remove()}}}}}}}this.preload=null}},matchOrDefault:function(str,re,val){if(!str){return val}var hasQuery=str.match(re);return hasQuery?hasQuery[1]:val}};window.addEvent("domready",Lightbox.init.bind(Lightbox)); if(window.ie)window.addEvent("load",Lightbox.init.bind(Lightbox));/**
* SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
*
* SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
*/
if(typeof deconcept == "undefined") var deconcept = new Object();
if(typeof deconcept.util == "undefined") deconcept.util = new Object();
if(typeof deconcept.SWFObjectUtil == "undefined") deconcept.SWFObjectUtil = new Object();
deconcept.SWFObject = function(swf, id, w, h, ver, c, quality, xiRedirectUrl, redirectUrl, detectKey) {
if (!document.getElementById) { return; }
this.DETECT_KEY = detectKey ? detectKey : 'detectflash';
this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
this.params = new Object();
this.variables = new Object();
this.attributes = new Array();
if(swf) { this.setAttribute('swf', swf); }
if(id) { this.setAttribute('id', id); }
if(w) { this.setAttribute('width', w); }
if(h) { this.setAttribute('height', h); }
if(ver) { this.setAttribute('version', new deconcept.PlayerVersion(ver.toString().split("."))); }
this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion();
if (!window.opera && document.all && this.installedVer.major > 7) {
// only add the onunload cleanup if the Flash Player version supports External Interface and we are in IE
deconcept.SWFObject.doPrepUnload = true;
}
if(c) { this.addParam('bgcolor', c); }
var q = quality ? quality : 'high';
this.addParam('quality', q);
this.setAttribute('useExpressInstall', false);
this.setAttribute('doExpressInstall', false);
var xir = (xiRedirectUrl) ? xiRedirectUrl : window.location;
this.setAttribute('xiRedirectUrl', xir);
this.setAttribute('redirectUrl', '');
if(redirectUrl) { this.setAttribute('redirectUrl', redirectUrl); }
};
deconcept.SWFObject.prototype = {
useExpressInstall: function(path) {
this.xiSWFPath = !path ? "expressinstall.swf" : path;
this.setAttribute('useExpressInstall', true);
},
setAttribute: function(name, value){
this.attributes[name] = value;
},
getAttribute: function(name){
return this.attributes[name];
},
addParam: function(name, value){
this.params[name] = value;
},
getParams: function(){
return this.params;
},
addVariable: function(name, value){
this.variables[name] = value;
},
getVariable: function(name){
return this.variables[name];
},
getVariables: function(){
return this.variables;
},
getVariablePairs: function(){
var variablePairs = new Array();
var key;
var variables = this.getVariables();
for(key in variables){
variablePairs[variablePairs.length] = key +"="+ variables[key];
}
return variablePairs;
},
getSWFHTML: function() {
var swfNode = "";
if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { // netscape plugin architecture
if (this.getAttribute("doExpressInstall")) {
this.addVariable("MMplayerType", "PlugIn");
this.setAttribute('swf', this.xiSWFPath);
}
swfNode = '<embed type="application/x-shockwave-flash" src="'+ this.getAttribute('swf') +'" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'" style="'+ this.getAttribute('style') +'"';
swfNode += ' id="'+ this.getAttribute('id') +'" name="'+ this.getAttribute('id') +'" ';
var params = this.getParams();
for(var key in params){ swfNode += [key] +'="'+ params[key] +'" '; }
var pairs = this.getVariablePairs().join("&");
if (pairs.length > 0){ swfNode += 'flashvars="'+ pairs +'"'; }
swfNode += '/>';
} else { // PC IE
if (this.getAttribute("doExpressInstall")) {
this.addVariable("MMplayerType", "ActiveX");
this.setAttribute('swf', this.xiSWFPath);
}
swfNode = '<object id="'+ this.getAttribute('id') +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+ this.getAttribute('width') +'" height="'+ this.getAttribute('height') +'" style="'+ this.getAttribute('style') +'">';
swfNode += '<param name="movie" value="'+ this.getAttribute('swf') +'" />';
var params = this.getParams();
for(var key in params) {
swfNode += '<param name="'+ key +'" value="'+ params[key] +'" />';
}
var pairs = this.getVariablePairs().join("&");
if(pairs.length > 0) {swfNode += '<param name="flashvars" value="'+ pairs +'" />';}
swfNode += "</object>";
}
return swfNode;
},
write: function(elementId){
if(this.getAttribute('useExpressInstall')) {
// check to see if we need to do an express install
var expressInstallReqVer = new deconcept.PlayerVersion([6,0,65]);
if (this.installedVer.versionIsValid(expressInstallReqVer) && !this.installedVer.versionIsValid(this.getAttribute('version'))) {
this.setAttribute('doExpressInstall', true);
this.addVariable("MMredirectURL", escape(this.getAttribute('xiRedirectUrl')));
document.title = document.title.slice(0, 47) + " - Flash Player Installation";
this.addVariable("MMdoctitle", document.title);
}
}
if(this.skipDetect || this.getAttribute('doExpressInstall') || this.installedVer.versionIsValid(this.getAttribute('version'))){
var n = (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
n.innerHTML = this.getSWFHTML();
return true;
}else{
if(this.getAttribute('redirectUrl') != "") {
document.location.replace(this.getAttribute('redirectUrl'));
}
}
return false;
}
};
/* ---- detection functions ---- */
deconcept.SWFObjectUtil.getPlayerVersion = function(){
var PlayerVersion = new deconcept.PlayerVersion([0,0,0]);
if(navigator.plugins && navigator.mimeTypes.length){
var x = navigator.plugins["Shockwave Flash"];
if(x && x.description) {
PlayerVersion = new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split("."));
}
}else if (navigator.userAgent && navigator.userAgent.indexOf("Windows CE") >= 0){ // if Windows CE
var axo = 1;
var counter = 3;
while(axo) {
try {
counter++;
axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+ counter);
//				document.write("player v: "+ counter);
PlayerVersion = new deconcept.PlayerVersion([counter,0,0]);
} catch (e) {
axo = null;
}
}
} else { // Win IE (non mobile)
// do minor version lookup in IE, but avoid fp6 crashing issues
// see http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
try{
var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
}catch(e){
try {
var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
PlayerVersion = new deconcept.PlayerVersion([6,0,21]);
axo.AllowScriptAccess = "always"; // error if player version < 6.0.47 (thanks to Michael Williams @ Adobe for this code)
} catch(e) {
if (PlayerVersion.major == 6) {
return PlayerVersion;
}
}
try {
axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
} catch(e) {}
}
if (axo != null) {
PlayerVersion = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
}
}
return PlayerVersion;
};
deconcept.PlayerVersion = function(arrVersion){
this.major = arrVersion[0] != null ? parseInt(arrVersion[0]) : 0;
this.minor = arrVersion[1] != null ? parseInt(arrVersion[1]) : 0;
this.rev = arrVersion[2] != null ? parseInt(arrVersion[2]) : 0;
};
deconcept.PlayerVersion.prototype.versionIsValid = function(fv){
if(this.major < fv.major) return false;
if(this.major > fv.major) return true;
if(this.minor < fv.minor) return false;
if(this.minor > fv.minor) return true;
if(this.rev < fv.rev) return false;
return true;
};
/* ---- get value of query string param ---- */
deconcept.util = {
getRequestParameter: function(param) {
var q = document.location.search || document.location.hash;
if (param == null) { return q; }
if(q) {
var pairs = q.substring(1).split("&");
for (var i=0; i < pairs.length; i++) {
if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
return pairs[i].substring((pairs[i].indexOf("=")+1));
}
}
}
return "";
}
};
/* fix for video streaming bug */
deconcept.SWFObjectUtil.cleanupSWFs = function() {
var objects = document.getElementsByTagName("OBJECT");
for (var i = objects.length - 1; i >= 0; i--) {
objects[i].style.display = 'none';
for (var x in objects[i]) {
if (typeof objects[i][x] == 'function') {
objects[i][x] = function(){};
}
}
}
};
// fixes bug in some fp9 versions see http://blog.deconcept.com/2006/07/28/swfobject-143-released/
if (deconcept.SWFObject.doPrepUnload) {
if (!deconcept.unloadSet) {
deconcept.SWFObjectUtil.prepUnload = function() {
__flash_unloadHandler = function(){};
__flash_savedUnloadHandler = function(){};
window.attachEvent("onunload", deconcept.SWFObjectUtil.cleanupSWFs);
};
window.attachEvent("onbeforeunload", deconcept.SWFObjectUtil.prepUnload);
deconcept.unloadSet = true;
}
};
/* add document.getElementById if needed (mobile IE < 5) */
if (!document.getElementById && document.all) { document.getElementById = function(id) { return document.all[id]; }}
/* add some aliases for ease of use/backwards compatibility */
var getQueryParamValue = deconcept.util.getRequestParameter;
var FlashObject = deconcept.SWFObject; // for legacy support
var SWFObject = deconcept.SWFObject;
// Calendar: a Javascript class for Mootools that adds accessible and unobtrusive date pickers to your form elements <http://electricprism.com/aeron/calendar>
// Calendar RC4, Copyright (c) 2007 Aeron Glemann <http://electricprism.com/aeron>, MIT Style License.
var Calendar = new Class({
options: {
blocked: [], // blocked dates
classes: [], // ['calendar', 'prev', 'next', 'month', 'year', 'today', 'invalid', 'valid', 'inactive', 'active', 'hover', 'hilite']
days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // days of the week starting at sunday
direction: 0, // -1 past, 0 past + future, 1 future
draggable: true,
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
navigation: 1, // 0 = no nav; 1 = single nav for month; 2 = dual nav for month and year
offset: 0, // first day of the week: 0 = sunday, 1 = monday, etc..
onHideStart: Class.empty,
onHideComplete: Class.empty,
onShowStart: Class.empty,
onShowComplete: Class.empty,
maxYear : 2999,
pad: 1, // padding between multiple calendars
tweak: {x: 0, y: 0} // tweak calendar positioning
},
// initialize: calendar constructor
// @param obj (obj) a js object containing the form elements and format strings { id: 'format', id: 'format' etc }
// @param props (obj) optional properties
initialize: function(obj, options) {
// basic error checking
if (!obj) { return false; }
this.setOptions(options);
// create our classes array
var keys = ['calendar', 'prev', 'next', 'month', 'year', 'today', 'invalid', 'valid', 'inactive', 'active', 'hover', 'hilite'];
var values = keys.map(function(key, i) {
if (this.options.classes[i]) {
if (this.options.classes[i].length) { key = this.options.classes[i]; }
}
return key;
}, this);
this.classes = values.associate(keys);
// create cal element with css styles required for proper cal functioning
this.calendar = new Element('div', {
'styles': { left: '-1000px', opacity: 0, position: 'absolute', top: '-1000px', zIndex: 1000 }
}).addClass(this.classes.calendar).injectInside(document.body);
// iex 6 needs a transparent iframe underneath the calendar in order to not allow select elements to render through
if (window.ie6) {
this.iframe = new Element('iframe', {
'styles': { left: '-1000px', position: 'absolute', top: '-1000px', zIndex: 999 }
}).injectInside(document.body);
this.iframe.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';
}
// initialize fade method
this.fx = this.calendar.effect('opacity', {
onStart: function() {
if (this.calendar.getStyle('opacity') == 0) { // show
if (window.ie6) { this.iframe.setStyle('display', 'block'); }
this.calendar.setStyle('display', 'block');
this.fireEvent('onShowStart', this.element);
}
else { // hide
this.fireEvent('onHideStart', this.element);
}
}.bind(this),
onComplete: function() {
if (this.calendar.getStyle('opacity') == 0) { // hidden
this.calendar.setStyle('display', 'none');
if (window.ie6) { this.iframe.setStyle('display', 'none'); }
this.fireEvent('onHideComplete', this.element);
}
else { // shown
this.fireEvent('onShowComplete', this.element);
}
}.bind(this)
});
// initialize drag method
if (window.Drag && this.options.draggable) {
this.drag = new Drag.Move(this.calendar, {
onDrag: function() {
if (window.ie6) { this.iframe.setStyles({ left: this.calendar.style.left, top: this.calendar.style.top }); }
}.bind(this)
});
}
// create calendars array
this.calendars = [];
this._id = 0;
var d = new Date(); // today
d.setDate(d.getDate() + this.options.direction.toInt()); // correct today for directional offset
for (var i in obj) {
var cal = {
button: new Element('button').setProperties({'type': 'button'}),
el: $(i),
els: [],
id: this._id++,
month: d.getMonth(),
visible: false,
year: d.getFullYear()
};
// fix for bad element (naughty, naughty element!)
if (!this.element(i, obj[i], cal)) { continue; }
cal.el.addClass(this.classes.calendar);
// create cal button
cal.button.addClass(this.classes.calendar).addEvent('click', function(cal) { this.toggle(cal); }.pass(cal, this)).injectAfter(cal.el);
// read in default value
cal.val = this.read(cal);
$extend(cal, this.bounds(cal)); // abs bounds of calendar
$extend(cal, this.values(cal)); // valid days, months, years
if(cal.val)
this.rebuild(cal);
this.calendars.push(cal); // add to cals array
}
},
addElement: function(obj){
var d = new Date(); // today
d.setDate(d.getDate() + this.options.direction.toInt()); // correct today for directional offset
for (var i in obj) {
var cal = {
button: new Element('button').setProperties({'type': 'button'}),
el: $(i),
els: [],
id: this._id++,
month: d.getMonth(),
visible: false,
year: d.getFullYear()
};
// fix for bad element (naughty, naughty element!)
if (!this.element(i, obj[i], cal)) { continue; }
cal.el.addClass(this.classes.calendar);
// create cal button
cal.button.addClass(this.classes.calendar).addEvent('click', function(cal) { this.toggle(cal); }.pass(cal, this)).injectAfter(cal.el);
// read in default value
//	cal.val = this.read(cal);
$extend(cal, this.bounds(cal)); // abs bounds of calendar
$extend(cal, this.values(cal)); // valid days, months, years
//this.rebuild(cal);
this.calendars.push(cal); // add to cals array
}
},
// blocked: returns an array of blocked days for the month / year
// @param cal (obj)
// @returns blocked days (array)
blocked: function(cal) {
var blocked = [];
var offset = new Date(cal.year, cal.month, 1).getDay(); // day of the week (offset)
var last = new Date(cal.year, cal.month + 1, 0).getDate(); // last day of this month
this.options.blocked.each(function(date){
var values = date.split(' ');
// preparation
for (var i = 0; i <= 3; i++){
if (!values[i]){ values[i] = (i == 3) ? '' : '*'; } // make sure blocked date contains values for at least d, m and y
values[i] = values[i].contains(',') ? values[i].split(',') : new Array(values[i]); // split multiple values
var count = values[i].length - 1;
for (var j = count; j >= 0; j--){
if (values[i][j].contains('-')){ // a range
var val = values[i][j].split('-');
for (var k = val[0]; k <= val[1]; k++){
if (!values[i].contains(k)){ values[i].push(k + ''); }
}
values[i].splice(j, 1);
}
}
}
// execution
if (values[2].contains(cal.year + '') || values[2].contains('*')){
if (values[1].contains(cal.month + 1 + '') || values[1].contains('*')){
values[0].each(function(val){ // if blocked value indicates this month / year
if (val > 0){ blocked.push(val.toInt()); } // add date to blocked array
});
if (values[3]){ // optional value for day of week
for (var i = 0; i < last; i++){
var day = (i + offset) % 7;
if (values[3].contains(day + '')){
blocked.push(i + 1); // add every date that corresponds to the blocked day of the week to the blocked array
}
}
}
}
}
}, this);
return blocked;
},
// bounds: returns the start / end bounds of the calendar
// @param cal (obj)
// @returns obj
bounds: function(cal) {
// 1. first we assume the calendar has no bounds (or a thousand years in either direction)
// by default the calendar will accept a millennium in either direction
var start = new Date(1000, 0, 1); // jan 1, 1000
var end = new Date(2999, 11, 31); // dec 31, 2999
// 2. but if the cal is one directional we adjust accordingly
var date = new Date().getDate() + this.options.direction.toInt();
if (this.options.direction > 0) {
start = new Date();
start.setDate(date + this.options.pad * cal.id);
}
if (this.options.direction < 0) {
end = new Date();
end.setDate(date - this.options.pad * (this.calendars.length - cal.id - 1));
}
// 3. then we can further filter the limits by using the pre-existing values in the selects
cal.els.each(function(el) {
if (el.getTag() == 'select') {
if (el.format.test('(y|Y)')) { // search for a year select
var years = [];
el.getChildren().each(function(option) { // get options
var values = this.unformat(option.value, el.format);
if (!years.contains(values[0])) { years.push(values[0]); } // add to years array
}, this);
years.sort(this.sort);
if (years[0] > start.getFullYear()) {
d = new Date(years[0], start.getMonth() + 1, 0); // last day of new month
if (start.getDate() > d.getDate()) { start.setDate(d.getDate()); }
start.setYear(years[0]);
}
if (years.getLast() < end.getFullYear()) {
d = new Date(years.getLast(), end.getMonth() + 1, 0); // last day of new month
if (end.getDate() > d.getDate()) { end.setDate(d.getDate()); }
end.setYear(years.getLast());
}
}
if (el.format.test('(F|m|M|n)')) { // search for a month select
var months_start = [];
var months_end = [];
el.getChildren().each(function(option) { // get options
var values = this.unformat(option.value, el.format);
if ($type(values[0]) != 'number' || values[0] == years[0]) { // if it's a year / month combo for curr year, or simply a month select
if (!months_start.contains(values[1])) { months_start.push(values[1]); } // add to months array
}
if ($type(values[0]) != 'number' || values[0] == years.getLast()) { // if it's a year / month combo for curr year, or simply a month select
if (!months_end.contains(values[1])) { months_end.push(values[1]); } // add to months array
}
}, this);
months_start.sort(this.sort);
months_end.sort(this.sort);
if (months_start[0] > start.getMonth()) {
d = new Date(start.getFullYear(), months_start[0] + 1, 0); // last day of new month
if (start.getDate() > d.getDate()) { start.setDate(d.getDate()); }
start.setMonth(months_start[0]);
}
if (months_end.getLast() < end.getMonth()) {
d = new Date(start.getFullYear(), months_end.getLast() + 1, 0); // last day of new month
if (end.getDate() > d.getDate()) { end.setDate(d.getDate()); }
end.setMonth(months_end.getLast());
}
}
}
}, this);
return { 'start': start, 'end': end };
},
// caption: returns the caption element with header and navigation
// @param cal (obj)
// @returns caption (element)
caption: function(cal) {
// start by assuming navigation is allowed
var navigation = {
prev: { 'month': true, 'year': true },
next: { 'month': true, 'year': true }
};
// if we're in an out of bounds year
if (cal.year == cal.start.getFullYear()) {
navigation.prev.year = false;
if (cal.month == cal.start.getMonth() && this.options.navigation == 1) {
navigation.prev.month = false;
}
}
if (cal.year == cal.end.getFullYear()) {
navigation.next.year = false;
if (cal.month == cal.end.getMonth() && this.options.navigation == 1) {
navigation.next.month = false;
}
}
// special case of improved navigation but months array with only 1 month we can disable all month navigation
if ($type(cal.months) == 'array') {
if (cal.months.length == 1 && this.options.navigation == 2) {
navigation.prev.month = navigation.next.month = false;
}
}
var caption = new Element('caption');
//		var prev = new Element('a').addClass(this.classes.prev).appendText('\x3c'); // <
//		var next = new Element('a').addClass(this.classes.next).appendText('\x3e'); // >
var prev = new Element('a').addClass(this.classes.prev).setHTML('&nbsp;&nbsp;&nbsp;&nbsp;'); // <
var next = new Element('a').addClass(this.classes.next).setHTML('&nbsp;&nbsp;&nbsp;&nbsp;'); // >
if (this.options.navigation == 2) {
var month = new Element('span').addClass(this.classes.month).injectInside(caption);
if (navigation.prev.month) { prev.clone().addEvent('click', function(cal) { this.navigate(cal, 'm', -1); }.pass(cal, this)).injectInside(month); }
var monthSpan = new Element('span').setHTML(this.options.months[cal.month]);
monthSpan.setStyle('cursor','pointer');
monthSpan.addEvent('mouseenter', function(e){
monthSpan.setStyle('text-decoration', 'underline');
});
monthSpan.addEvent('mouseleave', function(e){
monthSpan.setStyle('text-decoration', 'none');
});
// create a list of month select menu
var monthsList = new Element('select', {'style': 'width:60px; font-size:11px;'});
for (var i = 0; i < this.options.months.length; i++) {
var option = new Element('option', {'style': 'font-size:11px;','value':i}).setHTML(this.options.months[i]);
if(cal.month == i){
option.setAttribute('selected', 'selected');
}
option.injectInside(monthsList);
}
monthsList.addEvent('change', function(e){
this.navigate(cal, 'm', monthsList.value-cal.month);
}.bind(this));
monthSpan.addEvent('click', function(e){
monthSpan.removeEvents('click');
monthSpan.empty();
monthsList.injectInside(monthSpan);
}.bind(this));
month.adopt(monthSpan);
if (navigation.next.month) { next.clone().addEvent('click', function(cal) { this.navigate(cal, 'm', 1); }.pass(cal, this)).injectInside(month); }
var year = new Element('span').addClass(this.classes.year).injectInside(caption);
if (navigation.prev.year) { prev.clone().addEvent('click', function(cal) { this.navigate(cal, 'y', -1); }.pass(cal, this)).injectInside(year); }
var yearSpan = new Element('span').appendText(cal.year);
yearSpan.setStyle('cursor','pointer');
yearSpan.addEvent('mouseenter', function(e){
yearSpan.setStyle('text-decoration', 'underline');
});
yearSpan.addEvent('mouseleave', function(e){
yearSpan.setStyle('text-decoration', 'none');
});
// create a list of years select menu
var yearsList = new Element('select', {'style': 'font-size:11px;'});
var currentYear = new Date().getFullYear();
for (var i = currentYear - 100; i < currentYear+1; i++) {
var option = new Element('option', {'style': 'font-size:11px;','value':i}).appendText(i);
if(cal.year == i){
option.setAttribute('selected', 'selected');
}
option.injectInside(yearsList);
}
yearsList.addEvent('change', function(e){
this.navigate(cal, 'y', yearsList.value-cal.year);
}.bind(this));
yearSpan.addEvent('click', function(e){
yearSpan.removeEvents('click');
yearSpan.empty();
yearsList.injectInside(yearSpan);
}.bind(this));
year.adopt(yearSpan);
if (navigation.next.year) { next.clone().addEvent('click', function(cal) { this.navigate(cal, 'y', 1); }.pass(cal, this)).injectInside(year); }
}
else { // 1 or 0
if (navigation.prev.month && this.options.navigation) { prev.clone().addEvent('click', function(cal) { this.navigate(cal, 'm', -1); }.pass(cal, this)).injectInside(caption); }
caption.adopt(new Element('span').addClass(this.classes.month).appendText(this.options.months[cal.month]));
caption.adopt(new Element('span').addClass(this.classes.year).appendText(cal.year));
if (navigation.next.month && this.options.navigation) { next.clone().addEvent('click', function(cal) { this.navigate(cal, 'm', 1); }.pass(cal, this)).injectInside(caption); }
}
return caption;
},
// changed: run when a select value is changed
// @param cal (obj)
changed: function(cal) {
cal.val = this.read(cal); // update calendar val from inputs
$extend(cal, this.values(cal)); // update bounds - based on curr month
this.rebuild(cal); // rebuild days select
if (!cal.val) { return; } // in case the same date was clicked the cal has no set date we should exit
if (cal.val.getDate() < cal.days[0]) { cal.val.setDate(cal.days[0]); }
if (cal.val.getDate() > cal.days.getLast()) { cal.val.setDate(cal.days.getLast()); }
cal.els.each(function(el) {	// then we can set the value to the field
el.value = this.format(cal.val, el.format);
}, this);
this.check(cal); // checks other cals
this.calendars.each(function(kal) { // update cal graphic if visible
if (kal.visible) { this.display(kal); }
}, this);
},
// check: checks other calendars to make sure no overlapping values
// @param cal (obj)
check: function(cal) {
/** this.calendars.each(function(kal, i) {
if (kal.val) { // if calendar has value set
var change = false;
if (i < cal.id) { // preceding calendar
var bound = new Date(Date.parse(cal.val));
bound.setDate(bound.getDate() - (this.options.pad * (cal.id - i)));
if (bound < kal.val) { change = true; }
}
if (i > cal.id) { // following calendar
var bound = new Date(Date.parse(cal.val));
bound.setDate(bound.getDate() + (this.options.pad * (i - cal.id)));
if (bound > kal.val) { change = true; }
}
if (change) {
if (kal.start > bound) { bound = kal.start; }
if (kal.end < bound) { bound = kal.end; }
kal.month = bound.getMonth();
kal.year = bound.getFullYear();
$extend(kal, this.values(kal));
// TODO - IN THE CASE OF SELECT MOVE TO NEAREST VALID VALUE
// IN THE CASE OF INPUT DISABLE
// if new date is not valid better unset cal value
// otherwise it would mean incrementally checking to find the nearest valid date which could be months / years away
kal.val = kal.days.contains(bound.getDate()) ? bound : null;
this.write(kal);
if (kal.visible) { this.display(kal); } // update cal graphic if visible
}
}
else {
kal.month = cal.month;
kal.year = cal.year;
}
}, this); **/
},
// clicked: run when a valid day is clicked in the calendar
// @param cal (obj)
clicked: function(td, day, cal) {
cal.val = (this.value(cal) == day) ? null : new Date(cal.year, cal.month, day); // set new value - if same then disable
this.write(cal);
// ok - in the special case that it's all selects and there's always a date no matter what (at least as far as the form is concerned)
// we can't let the calendar undo a date selection - it's just not possible!!
if (!cal.val) { cal.val = this.read(cal); }
if (cal.val) {
this.check(cal); // checks other cals
this.toggle(cal); // hide cal
}
else { // remove active class and replace with valid
td.addClass(this.classes.valid);
td.removeClass(this.classes.active);
}
},
// display: create calendar element
// @param cal (obj)
display: function(cal) {
// 1. header and navigation
this.calendar.empty(); // init div
this.calendar.className = this.classes.calendar + ' ' + this.options.months[cal.month].toLowerCase();
var div = new Element('div').injectInside(this.calendar); // a wrapper div to help correct browser css problems with the caption element
var table = new Element('table').injectInside(div).adopt(this.caption(cal));
// 2. day names
var thead = new Element('thead').injectInside(table);
var tr = new Element('tr').injectInside(thead);
for (var i = 0; i <= 6; i++) {
var th = this.options.days[(i + this.options.offset) % 7];
tr.adopt(new Element('th', { 'title': th }).appendText(th.substr(0, 1)));
}
// 3. day numbers
var tbody = new Element('tbody').injectInside(table);
var tr = new Element('tr').injectInside(tbody);
var d = new Date(cal.year, cal.month, 1);
var offset = ((d.getDay() - this.options.offset) + 7) % 7; // day of the week (offset)
var last = new Date(cal.year, cal.month + 1, 0).getDate(); // last day of this month
var prev = new Date(cal.year, cal.month, 0).getDate(); // last day of previous month
var active = this.value(cal); // active date (if set and within curr month)
var valid = cal.days; // valid days for curr month
var inactive = []; // active dates set by other calendars
var hilited = [];
/**	this.calendars.each(function(kal, i) {
if (kal != cal && kal.val) {
if (cal.year == kal.val.getFullYear() && cal.month == kal.val.getMonth()) { inactive.push(kal.val.getDate()); }
if (cal.val) {
for (var day = 1; day <= last; day++) {
d.setDate(day);
if ((i < cal.id && d > kal.val && d < cal.val) || (i > cal.id && d > cal.val && d < kal.val)) {
if (!hilited.contains(day)) { hilited.push(day); }
}
}
}
}
}, this);**/
var d = new Date();
var today = new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime(); // today obv
for (var i = 1; i < 43; i++) { // 1 to 42 (6 x 7 or 6 weeks)
if ((i - 1) % 7 == 0) { tr = new Element('tr').injectInside(tbody); } // each week is it's own table row
var td = new Element('td').injectInside(tr);
var day = i - offset;
var date = new Date(cal.year, cal.month, day);
var cls = '';
if (day === active) { cls = this.classes.active; } // active
else if (inactive.contains(day)) { cls = this.classes.inactive; } // inactive
else if (valid.contains(day)) { cls = this.classes.valid; } // valid
else if (day >= 1 && day <= last) { cls = this.classes.invalid; } // invalid
if (date.getTime() == today) { cls = cls + ' ' + this.classes.today; } // adds class for today
if (hilited.contains(day)) { cls = cls + ' ' + this.classes.hilite; } // adds class if hilited
td.addClass(cls);
if (valid.contains(day)) { // if it's a valid - clickable - day we add interaction
td.setProperty('title', this.format(date, 'D M jS Y'));
td.addEvents({
'click': function(td, day, cal) {
this.clicked(td, day, cal);
}.pass([td, day, cal], this),
'mouseover': function(td, cls) {
td.addClass(cls);
}.pass([td, this.classes.hover]),
'mouseout': function(td, cls) {
td.removeClass(cls);
}.pass([td, this.classes.hover])
});
}
// pad calendar with last days of prev month and first days of next month
if (day < 1) { day = prev + day; }
else if (day > last) { day = day - last; }
td.appendText(day);
}
},
// element: helper function
// @param el (string) element id
// @param f (string) format string
// @param cal (obj)
element: function(el, f, cal) {
if ($type(f) == 'object') { // in the case of multiple inputs per calendar
for (var i in f) {
if (!this.element(i, f[i], cal)) { return false; }
}
return true;
}
el = $(el);
if (!el) { return false; }
el.format = f;
if (el.getTag() == 'select') { // select elements allow the user to manually set the date via select option
el.addEvent('change', function(cal) { this.changed(cal); }.pass(cal, this));
}
else { // input (type text) elements restrict the user to only setting the date via the calendar
el.readOnly = true;
el.addEvent('focus', function(cal) { this.toggle(cal); }.pass(cal, this));
}
cal.els.push(el);
return true;
},
// format: formats a date object according to passed in instructions
// @param date (obj)
// @param f (string) any combination of punctuation / separators and d, j, D, l, S, m, n, F, M, y, Y
// @returns string
format: function(date, format) {
var str = '';
if (date) {
var j = date.getDate(); // 1 - 31
var w = date.getDay(); // 0 - 6
var l = this.options.days[w]; // Sunday - Saturday
var n = date.getMonth() + 1; // 1 - 12
var f = this.options.months[n - 1]; // January - December
var y = date.getFullYear() + ''; // 19xx - 20xx
for (var i = 0, len = format.length; i < len; i++) {
var cha = format.charAt(i); // format char
switch(cha) {
// year cases
case 'y': // xx - xx
y = y.substr(2);
case 'Y': // 19xx - 20xx
str += y;
break;
// month cases
case 'm': // 01 - 12
if (n < 10) { n = '0' + n; }
case 'n': // 1 - 12
str += n;
break;
case 'M': // Jan - Dec
f = f.substr(0, 3);
case 'F': // January - December
str += f;
break;
// day cases
case 'd': // 01 - 31
if (j < 10) { j = '0' + j; }
case 'j': // 1 - 31
str += j;
break;
case 'D': // Sun - Sat
l = l.substr(0, 3);
case 'l': // Sunday - Saturday
str += l;
break;
case 'N': // 1 - 7
w += 1;
case 'w': // 0 - 6
str += w;
break;
case 'S': // st, nd, rd or th (works well with j)
if (j % 10 == 1 && j != '11') { str += 'st'; }
else if (j % 10 == 2 && j != '12') { str += 'nd'; }
else if (j % 10 == 3 && j != '13') { str += 'rd'; }
else { str += 'th'; }
break;
default:
str += cha;
}
}
}
return str; //  return format with values replaced
},
// navigate: calendar navigation
// @param cal (obj)
// @param type (str) m or y for month or year
// @param n (int) + or - for next or prev
navigate: function(cal, type, n) {
switch (type) {
case 'm': // month
if ($type(cal.months) == 'array') {
var i = cal.months.indexOf(cal.month) + n; // index of current month
if (i < 0 || i == cal.months.length) { // out of range
if (this.options.navigation == 1) { // if type 1 nav we'll need to increment the year
this.navigate(cal, 'y', n);
}
i = (i < 0) ? cal.months.length - 1 : 0;
}
cal.month = cal.months[i];
}
else {
var i = cal.month + n;
if (i < 0 || i == 12) {
if (this.options.navigation == 1) {
this.navigate(cal, 'y', n);
}
i = (i < 0) ? 11 : 0;
}
cal.month = i;
}
break;
case 'y': // year
if ($type(cal.years) == 'array') {
var i = cal.years.indexOf(cal.year) + n;
cal.year = cal.years[i];
}
else {
cal.year += n;
}
break;
}
$extend(cal, this.values(cal));
if ($type(cal.months) == 'array') { // if the calendar has a months select
var i = cal.months.indexOf(cal.month); // and make sure the curr months exists for the new year
if (i < 0) { cal.month = cal.months[0]; } // otherwise we'll reset the month
}
this.display(cal);
},
// read: compiles cal value based on array of inputs passed in
// @param cal (obj)
// @returns date (obj) or (null)
read: function(cal) {
var arr = [null, null, null];
cal.els.each(function(el) {
// returns an array which may contain empty values
var values = this.unformat(el.value, el.format);
values.each(function(val, i) {
if ($type(val) == 'number') { arr[i] = val; }
});
}, this);
// we can update the cals month and year values
if ($type(arr[0]) == 'number') { cal.year = arr[0]; }
if ($type(arr[1]) == 'number') { cal.month = arr[1]; }
var val = null;
if (arr.every(function(i) { return $type(i) == 'number'; })) { // if valid date
var last = new Date(arr[0], arr[1] + 1, 0).getDate(); // last day of month
if (arr[2] > last) { arr[2] = last; } // make sure we stay within the month (ex in case default day of select is 31 and month is feb)
val = new Date(arr[0], arr[1], arr[2]);
}
return (cal.val == val) ? null : val; // if new date matches old return null (same date clicked twice = disable)
},
// rebuild: rebuilds days + months selects
// @param cal (obj)
rebuild: function(cal) {
cal.els.each(function(el) {
/*
if (el.getTag() == 'select' && el.format.test('^(F|m|M|n)$')) { // special case for months-only select
if (!cal.options) { cal.options = el.clone(); } // clone a copy of months select
var val = (cal.val) ? cal.val.getMonth() : el.value.toInt();
el.empty(); // initialize select
cal.months.each(function(month) {
// create an option element
var option = new Element('option', {
'selected': (val == month),
'value': this.format(new Date(1, month, 1), el.format);
}).appendText(day).injectInside(el);
}, this);
}
*/
if (el.getTag() == 'select' && el.format.test('^(d|j)$')) { // special case for days-only select
var d = this.value(cal);
if (!d) { d = el.value.toInt(); } // if the calendar doesn't have a set value, try to use value from select
el.empty(); // initialize select
var emptyOption = new Element('option', {
'selected':'true',
'value': '0'
}).injectInside(el);
cal.days.each(function(day) {
// create an option element
var option = new Element('option', {
'selected': (d == day),
'value': ((el.format == 'd' && day < 10) ? '0' + day : day)
}).appendText(day).injectInside(el);
}, this);
}
}, this);
},
// sort: helper function for numerical sorting
sort: function(a, b) {
return a - b;
},
// toggle: show / hide calendar
// @param cal (obj)
toggle: function(cal) {
document.removeEvent('mousedown', this.fn); // always remove the current mousedown script first
if (cal.visible) { // simply hide curr cal
cal.visible = false;
cal.button.removeClass(this.classes.active); // active
this.fx.start(1, 0);
}
else { // otherwise show (may have to hide others)
// hide cal on out-of-bounds click
this.fn = function(e, cal) {
var e = new Event(e);
var el = e.target;
var stop = false;
while (el != document.body && el.nodeType == 1) {
if (el == this.calendar) { stop = true; }
this.calendars.each(function(kal) {
if (kal.button == el || kal.els.contains(el)) { stop = true; }
});
if (stop) {
e.stop();
return false;
}
else { el = el.parentNode; }
}
this.toggle(cal);
}.create({ 'arguments': cal, 'bind': this, 'event': true });
document.addEvent('mousedown', this.fn);
this.calendars.each(function(kal) {
if (kal == cal) {
kal.visible = true;
kal.button.addClass(this.classes.active); // css c-icon-active
}
else {
kal.visible = false;
kal.button.removeClass(this.classes.active); // css c-icon-active
}
}, this);
var size = window.getSize().scrollSize;
var coord = cal.button.getCoordinates();
var x = coord.right + this.options.tweak.x;
var y = coord.top + this.options.tweak.y;
// make sure the calendar doesn't open off screen
if (!this.calendar.coord) { this.calendar.coord = this.calendar.getCoordinates(); }
if (x + this.calendar.coord.width > size.x) { x -= (x + this.calendar.coord.width - size.x); }
if (y + this.calendar.coord.height > size.y) { y -= (y + this.calendar.coord.height - size.y); }
this.calendar.setStyles({ left: x + 'px', top: y + 'px' });
if (window.ie6) {
this.iframe.setStyles({ height: this.calendar.coord.height + 'px', left: x + 'px', top: y + 'px', width: this.calendar.coord.width + 'px' });
}
this.display(cal);
this.fx.start(0, 1);
}
},
// unformat: takes a value from an input and parses the d, m and y elements
// @param val (string)
// @param f (string) any combination of punctuation / separators and d, j, D, l, S, m, n, F, M, y, Y
// @returns array
unformat: function(val, f) {
f = f.escapeRegExp();
var re = {
d: '([0-9]{2})',
j: '([0-9]{1,2})',
D: '(' + this.options.days.map(function(day) { return day.substr(0, 3); }).join('|') + ')',
l: '(' + this.options.days.join('|') + ')',
S: '(st|nd|rd|th)',
F: '(' + this.options.months.join('|') + ')',
m: '([0-9]{2})',
M: '(' + this.options.months.map(function(month) { return month.substr(0, 3); }).join('|') + ')',
n: '([0-9]{1,2})',
Y: '([0-9]{4})',
y: '([0-9]{2})'
};
var arr = []; // array of indexes
var g = '';
// convert our format string to regexp
for (var i = 0; i < f.length; i++) {
var c = f.charAt(i);
if (re[c]) {
arr.push(c);
g += re[c];
}
else {
g += c;
}
}
// match against date
var matches = val.match('^' + g + '$');
var dates = new Array(3);
if (matches) {
matches = matches.slice(1); // remove first match which is the date
arr.each(function(c, i) {
i = matches[i];
switch(c) {
// year cases
case 'y':
i = '19' + i; // 2 digit year assumes 19th century (same as JS)
case 'Y':
dates[0] = i.toInt();
break;
// month cases
case 'F':
i = i.substr(0, 3);
case 'M':
i = this.options.months.map(function(month) { return month.substr(0, 3); }).indexOf(i) + 1;
case 'm':
case 'n':
dates[1] = i.toInt() - 1;
break;
// day cases
case 'd':
case 'j':
dates[2] = i.toInt();
break;
}
}, this);
}
return dates;
},
// value: returns day value of calendar if set
// @param cal (obj)
// @returns day (int) or null
value: function(cal) {
var day = null;
if (cal.val) {
if (cal.year == cal.val.getFullYear() && cal.month == cal.val.getMonth()) { day = cal.val.getDate(); }
}
return day;
},
// values: returns the years, months (for curr year) and days (for curr month and year) for the calendar
// @param cal (obj)
// @returns obj
values: function(cal) {
var years, months, days;
cal.els.each(function(el) {
if (el.getTag() == 'select') {
if (el.format.test('(y|Y)')) { // search for a year select
years = [];
el.getChildren().each(function(option) { // get options
var values = this.unformat(option.value, el.format);
if (!years.contains(values[0])) { years.push(values[0]); } // add to years array
}, this);
years.sort(this.sort);
}
if (el.format.test('(F|m|M|n)')) { // search for a month select
months = []; // 0 - 11 should be
el.getChildren().each(function(option) { // get options
var values = this.unformat(option.value, el.format);
if ($type(values[0]) != 'number' || values[0] == cal.year) { // if it's a year / month combo for curr year, or simply a month select
if (!months.contains(values[1])) { months.push(values[1]); } // add to months array
}
}, this);
months.sort(this.sort);
}
if (el.format.test('(d|j)') && !el.format.test('^(d|j)$')) { // search for a day select, but NOT a days only select
days = []; // 1 - 31
el.getChildren().each(function(option) { // get options
var values = this.unformat(option.value, el.format);
// in the special case of days we dont want the value if its a days only select
// otherwise that will screw up the options rebuilding
// we will take the values if they are exact dates though
if (values[0] == cal.year && values[1] == cal.month) {
if (!days.contains(values[2])) { days.push(values[2]); } // add to days array
}
}, this);
}
}
}, this);
// we start with what would be the first and last days were there no restrictions
var first = 1;
var last = new Date(cal.year, cal.month + 1, 0).getDate(); // last day of the month
// if we're in an out of bounds year
if (cal.year == cal.start.getFullYear()) {
// in the special case of improved navigation but no months array, we'll need to construct one
if (months == null && this.options.navigation == 2) {
months = [];
for (var i = 0; i < 12; i ++) {
if (i >= cal.start.getMonth()) { months.push(i); }
}
}
// if we're in an out of bounds month
if (cal.month == cal.start.getMonth()) {
first = cal.start.getDate(); // first day equals day of bound
}
}
if (cal.year == cal.end.getFullYear()) {
// in the special case of improved navigation but no months array, we'll need to construct one
if (months == null && this.options.navigation == 2) {
months = [];
for (var i = 0; i < 12; i ++) {
if (i <= cal.end.getMonth()) { months.push(i); }
}
}
if (cal.month == cal.end.getMonth()) {
last = cal.end.getDate(); // last day equals day of bound
}
}
// let's get our invalid days
var blocked = this.blocked(cal);
// finally we can prepare all the valid days in a neat little array
if ($type(days) == 'array') { // somewhere there was a days select
days = days.filter(function(day) {
if (day >= first && day <= last && !blocked.contains(day)) { return day; }
});
}
else { // no days select we'll need to construct a valid days array
days = [];
for (var i = first; i <= last; i++) {
if (!blocked.contains(i)) { days.push(i); }
}
}
days.sort(this.sort); // sorting our days will give us first and last of month
return { 'days': days, 'months': months, 'years': years };
},
// write: sets calendars value to form elements
// @param cal (obj)
write: function(cal) {
this.rebuild(cal);	 // in the case of options, we'll need to make sure we have the correct number of days available
cal.els.each(function(el) {	// then we can set the value to the field
el.value = this.format(cal.val, el.format);
}, this);
}
});
Calendar.implement(new Events, new Options);/**
*  Create a drop-down menu for navigation
*
*/
var DropDownMenu = Options.extend({
options: {
onComplete: Class.empty,
onStart: Class.empty,
delay:500
},
initialize: function(el, options) {
this.el = $(el);
this.setOptions(options);
var elementToHide;
this.el.getElements('li').each(function(li, index) {
if(li.getElements('a')[0])li.getElements('a')[0].removeAttribute('title');
if(li.getElements('ul').length){
li.addClass('HasChild');
}
li.menu = this;
li.addEvent('mouseenter', function() {
this.addClass('iehover');
$clear(this._myTimer);
if(elementToHide && !this.getElements('ul').contains(elementToHide)){
elementToHide.removeClass('ulhover');
}
elementToHide = null;
if(this.getElements('ul')[0]) {
this.getElements('ul')[0].addClass('ulhover');
}
});
li.addEvent('mouseleave', function() {
this.removeClass('iehover');
if(this.getElements('ul')[0]) {
elementToHide = this.getElements('ul')[0];
this._myTimer = this.getElements('ul')[0].removeClass.delay(this.menu.options.delay ,this.getElements('ul')[0], 'ulhover');
}
});
}.bind(this));
},
hide : function(){
this.el.getElements('ul').each(function(item,index){
item.removeClass('ulhover');
});
}
});
var SynergeeNews = new Class({
initialize: function(el, elementClass, timer, className) {
this.el = el;
this.elementClass = elementClass;
this._timer = timer;
this._className = ' ';
if(className){
this._className += className;
}
this.items = this.el.getElements(this.elementClass);
// create the nav div
var nav = new Element('ul', {'class': 'Synergee-Web-Page-TextTicker-Nav-Container' + this._className});
this.navButtons = new Array();
for (var i = 0; i < this.items.length; i++) {
this.navButtons[i] = new Element('li', {'class': 'Synergee-Web-Page-TextTicker-NavButton' + this._className});
this.navButtons[i].position = i;
nav.appendChild(this.navButtons[i]);
this.navButtons[i].addEvent('click', function(event) {
event = new Event(event);
this.goto(event.target.position);
}.bind(this));
}
this.el.getParent().appendChild(nav);
if (this.items.length) {
var w = 0;
this.items.each(function(item, index) {
w += item.getSize().size.x;
item.addEvent('mouseenter', function() {
$clear(this.delayedFunction);
}.bind(this));
item.addEvent('mouseleave', function() {
$clear(this.delayedFunction);
this.delayedFunction = this.next.bind(this).delay(this._timer);
}.bind(this));
}.bind(this));
this.el.setStyles({
position: 'absolute',
top: 0,
left: 0,
width: w
});
this.fx = new Fx.Styles(this.el, {duration:800, transition: Fx.Transitions.Quint.easeInOut,
onStart: function(){
var i = (this.current == 0) ? this.items.length : this.current;
this.navButtons[this.current].addClass('Active');
for (var j = 0; j < this.navButtons.length; j ++) {
if (j != this.current)this.navButtons[j].removeClass('Active');
}
this.el.fireEvent('onstart', this.items[this.current]);
}.bind(this),
onCancel :function() {
this.el.fireEvent('oncancel', this.items[this.current]);
},
onComplete:function() {
this.el.fireEvent('itemchanged', this.items[this.current]);
}.bind(this)});
this.current = this.items.length;
this.next();
}
},
next : function() {
this.current++;
if (this.current >= this.items.length) this.current = 0;
this.fx.stop();
this.fx.start({
top: this.items[this.current].offsetTop,
left: -this.items[this.current].offsetLeft
});
this.delayedFunction = this.next.bind(this).delay(this._timer );
},
goto : function(to) {
$clear(this.delayedFunction);
this.current = to;
this.fx.start({
top: this.items[to].offsetTop,
left: -this.items[to].offsetLeft
});
this.delayedFunction = this.next.bind(this).delay(this._timer);
}
});var TextSplitter = new Class({
initialize: function(component, splitterElements, titleElement) {
if (component.getElement) {
this.el = component.getElement('div');
var elements = new Array();
if(!(splitterElements instanceof Array)){
splitterElements = new Array(splitterElements);
}
for(var i = 0; i < splitterElements.length; i++){
elements = this.el.getElement(splitterElements[i]);
if(elements.length)break;
}
// retrieve the blocks
if (elements) {
var children = this.el.childNodes;
this.blocks = new Array();
this.titles = new Array();
this.blocks.push(new Element('div', {"class": "Synergee-Web-Page-TextSplitter-Content"}));
for (var i = 0; i < children.length; i++) {
if ($type(children[i]) == 'element' && splitterElements.contains(children[i].tagName.toLowerCase())) {
this.blocks.push(new Element('div', {"class": "Synergee-Web-Page-TextSplitter-Content"}));
} else if (this.blocks.length) {
if ($type(children[i]) == 'element') {
this.blocks[this.blocks.length - 1].appendChild(children[i]);
} else {
this.blocks[this.blocks.length - 1].appendChild(children[i]);
}
i--;
}
}
this.el.empty();
if (titleElement) {
for (var i = 0; i < this.blocks.length; i++) {
if (this.blocks[i].getElement(titleElement)) {
this.titles[i] = this.blocks[i].getElement(titleElement);
this.titles[i].addClass('Synergee-Web-Page-TextSplitter-Title');
} else {
this.titles[i] = new Element(titleElement, {'class': 'Synergee-Web-Page-TextSplitter-Title'});
this.titles[i].setHTML('"' + titleElement + '" title missing');
}
}
if (this.titles.length) {
this.titles[this.titles.length - 1].addClass('Synergee-Web-Page-TextSplitter-Title-Last');
}
this.titlesContainer = new Element('div', {"class": "Synergee-Web-Page-TextSplitter-Title-Container"});
this.el.appendChild(this.titlesContainer);
}
this.contentsContainer = new Element('div', {"class": "Synergee-Web-Page-TextSplitter-Content-Container"});
this.el.appendChild(this.contentsContainer);
for (var i = 0; i < this.titles.length; i ++) {
this.titlesContainer.appendChild(this.titles[i]);
}
for (var i = 0; i < this.blocks.length; i ++) {
this.contentsContainer.appendChild(this.blocks[i]);
}
}
}
},
getContentContainer : function() {
return this.contentsContainer;
},
getTitleContainer :  function() {
if(this.titlesContainer)return this.titlesContainer;
return null;
},
getTitles : function() {
return this.titles;
},
getContents : function(){
return this.blocks;
}
});var SynergeeTips = Tips.extend({
options: {
onShow: function(tip){
tip.setStyle('visibility', 'visible');
},
onHide: function(tip){
tip.setStyle('visibility', 'hidden');
},
maxTitleChars: 30,
showDelay: 100,
hideDelay: 100,
className: 'tool',
offsets: {'x': 16, 'y': 16},
fixed: false,
maxHeight : 0,
closeButton : false,
eventType : 'click'
},
build: function(el){
el.$tmp.myTitle = (el.href && el.getTag() == 'a') ? el.href.replace('http://', '') : (el.rel || false);
if (el.title){
var dual = el.title.split('::');
if (dual.length > 1) {
el.$tmp.myTitle = dual[0].trim();
el.$tmp.myText = dual[1].trim();
} else {
el.$tmp.myText = el.title;
}
el.removeAttribute('title');
} else {
el.$tmp.myText = false;
}
if (el.$tmp.myTitle && el.$tmp.myTitle.length > this.options.maxTitleChars) el.$tmp.myTitle = el.$tmp.myTitle.substr(0, this.options.maxTitleChars - 1) + "&hellip;";
el.addEvent(this.options.eventType, function(event){
this.start(el);
if (this.options.maxHeight) {
if(this.text && this.options.maxHeight < this.text.getParent().getCoordinates().height){
this.text.getParent().setStyle('max-height', this.options.maxHeight);
this.text.getParent().setStyle('overflowY', 'scroll');
}
}
if (!this.options.fixed) this.locate(event);
else this.position(el);
}.bind(this));
if (!this.options.fixed) el.addEvent('mousemove', this.locate.bindWithEvent(this));
var end = this.end.bind(this);
el.addEvent('mouseleave', end);
el.addEvent('trash', end);
this.toolTip.addEvent('mouseleave', end);
this.toolTip.addEvent('mouseenter', function(event){
$clear(this.timer);
}.bind(this));
},
start: function(el){
this.wrapper.empty();
if (el.$tmp.myTitle){
this.title = new Element('span').inject(
new Element('div', {'class': this.options.className + '-title'}).inject(this.wrapper)
).setHTML(el.$tmp.myTitle);
if(this.options.closeButton){
this.closeButton = new Element('div',{'class':this.options.className + '-Close'});
var end = this.hide.bind(this);
this.closeButton.injectInside(this.title.getParent());
this.closeButton.addEvent('click',end);
}
}
if (el.$tmp.myText){
this.text = new Element('span').inject(
new Element('div', {'class': this.options.className + '-text'}).inject(this.wrapper)
).setHTML(el.$tmp.myText);
}
$clear(this.timer);
this.timer = this.show.delay(this.options.showDelay, this);
}
});
/**
* The synergee form javascript code.
* This file contains all the necessary code used by the form widget.
*
* Copyright (c) 2007 Pyrameed all right reserved (http://www.pyrameed.com)
*/
/**
* The field validator.
* This class is used to validate a form field
*/
var SynergeeFieldValidator = new Class({
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
return true;
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
throw Error('The method "getValidatorName" has to be defined for the field validator classes.');
}
});
/**
* The not empty field validator
*/
var SynergeeFieldValidatorNotEmpty = SynergeeFieldValidator.extend({
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
return (field.tagName.toLowerCase() == 'div' || field.getValue() != '');
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorNotEmpty';
}
});
/**
* The email field validator
*/
var SynergeeFieldValidatorEmail = SynergeeFieldValidator.extend({
_emailRegex : new RegExp("^([_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3}))?$"),
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
return this._emailRegex.test(field.getValue());
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorEmail';
}
});
/**
* The list field validator
*/
var SynergeeFieldValidatorList = SynergeeFieldValidator.extend({
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
var inputElements = field.getElementsByTagName('input');
for (var i = 0; i < inputElements.length; i++) {
if (inputElements[i].checked) {
return true;
}
}
return false;
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorList';
}
});
/**
* The alpha field validator
*/
var SynergeeFieldValidatorAlpha = SynergeeFieldValidator.extend({
_alphaRegex : new RegExp("^([a-zA-Z])*?$"),
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
return this._alphaRegex.test(field.getValue());
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorAlpha';
}
});
/**
* The numeric field validator
*/
var SynergeeFieldValidatorNum = SynergeeFieldValidator.extend({
_numRegex : new RegExp("^([0-9])*?$"),
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
return this._numRegex.test(field.getValue());
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorNum';
}
});
/**
* The alphanumeric field validator
*/
var SynergeeFieldValidatorAlnum = SynergeeFieldValidator.extend({
_alnumRegex : new RegExp("^([a-zA-Z0-9])*?$"),
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
return this._alnumRegex.test(field.getValue());
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorAlnum';
}
});
/**
* The date field validator
*/
var SynergeeFieldValidatorDate = SynergeeFieldValidator.extend({
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
return (field.tagName.toLowerCase() == 'input' || field.getValue() != '');
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorDate';
}
});
/**
* The Birthdate field validator
*/
var SynergeeFieldValidatorBirthdate = SynergeeFieldValidator.extend({
initialize : function(minDate, maxDate, format) {
if(minDate){
this._minDate = (new Date()).fromIso(minDate);
}   else{
this._minDate = null;
}
if(maxDate){
this._maxDate = (new Date()).fromIso(maxDate);
}   else{
this._maxDate = null;
}
if(format) this._format = format;
},
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
// always return true, the backend check the right dates
////
//        var fieldValue = field.getValue();
//        if(fieldValue != '' && (new Date()).fromIso(fieldValue)){
//            fieldValue = (new Date()).fromIso(fieldValue);
//            if(this._maxDate && this._maxDate.getTime() < fieldValue){
//                return false;
//
//            }
//            if(this._minDate && this._minDate.getTime() > fieldValue){
//                return false;
//            }
//        }
return true;
},
/**
* Return the vaidator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorBirthdate';
}
});
/**
* The Birthdate field validator
*/
var SynergeeFieldValidatorLevel = SynergeeFieldValidator.extend({
initialize : function(minimumLevel, maximumLevel) {
if(minimumLevel){
this._minimumLevel = minimumLevel;
}   else{
this._minimumLevel = 1;
}
if(maximumLevel){
this._maximumLevel = maximumLevel;
}   else{
this._maximumLevel = 7;
}
},
/**
* The validation method
*
* @param Element field The field element to validate
* @return boolean True if the field is valid
*/
isValid : function(field) {
var selIndex = field.selectedIndex;
var comboValue = field.options[selIndex].value;
if(comboValue){
if(comboValue >= this._minimumLevel && comboValue <= this._maximumLevel){
return true;
}
return false;
}
return true;
},
/**
* Return the validator name
*
* @return string The validator name
*/
getValidatorName : function() {
return 'SynergeeFieldValidatorLevel';
}
});
/**
* The form validator.
* This class is used to validate the fields of a specific form
*/
var SynergeeFormValidator = new Class({
_formElement : null,
_onComplete : null,
_fields : [],
_submitButton : null,
/**
* The constructor
*
* @param Element formElement The form element
* @param function onComplete The function called once the form has been submitted (this function is called by the ajax component)
*/
initialize: function(formElement, onComplete) {
this._fields = [];
this._formElement = formElement;
this._scroller = new Fx.Scroll(window, {offset: {'x': 0, 'y': -50}});
if (typeof(onComplete) == 'function') {
this._onComplete = onComplete;
} else {
this._onComplete = eval(onComplete);
}
this._formElement.addEvent('submit', function(e) {
new Event(e).stop();
});
// The error message functions are added to the form
this._formElement._errorMessage = new Fx.Slide(this._formElement.getElementsByTagName('div')[0]);
this._formElement.getElementsByTagName('div')[0].setStyle('clear', 'both');
this._formElement._errorMessage.hide();
this._formElement.displayErrorMessage = function() {
if (this._errorMessage) {
this._errorMessage.stop();
this._errorMessage.slideIn();
}
};
this._formElement.hideErrorMessage = function() {
if (this._errorMessage) {
this._errorMessage.stop();
this._errorMessage.slideOut();
}
};
},
/**
* This method is called when the response of the form has been received.
* The goal of this method is to analyse the response and if some fields were
* invalid the error message is displayed again.
* If no invalidate fields are returned, the user defined function (set on the onComplete
* attribute of the form tag) is called with the response as parameter.
*
* @param string response The response returned by the server
*/
onComplete : function(response) {
// The submit button is ungrayed
if (this._submitButton) {
this._submitButton.removeProperty('disabled');
}
// We check if the invalidateFields is empty or not
try {
var response = Json.evaluate(response);
if (response.invalidFields && response.invalidFields.length) {
try {
if ($(response.invalidFields[0])) {
$(response.invalidFields[0]).focus();
} else {
$('id_' + response.invalidFields[0]).focus();
}
}catch(ex){
// if the element is not focusable (it's hidden or something)
}
response.invalidFields.each(function(fieldName) {
if ($(fieldName)) {
$(fieldName).displayErrorMessage();
} else {
$('id_' + fieldName).displayErrorMessage();
}
});
try {
if(response.invalidFields[0]){
if ($(response.invalidFields[0])) {
if($(response.invalidFields[0]).getStyle('display') == 'none'){
var element = $(response.invalidFields[0]).getParent();
}else {
var element = $(response.invalidFields[0]);
}
this._scroller.toElement(element);
} else {
if($('id_' + response.invalidFields[0]).getStyle('display') == 'none'){
var element = $('id_' + response.invalidFields[0]).getParent();
}else {
var element = $('id_' + response.invalidFields[0]);
}
this._scroller.toElement(element);
}
}
}catch (ex){}
this._formElement.fireEvent('invalidfield');
} else if (response.isValid) {
// The user defined on complete method is called with the response as parameter
this._onComplete(response.response);
} else {
// The request wasn't valid, then a global message has to be send
this._formElement.displayErrorMessage();
}
} catch(ex) {
// The response is not a valid JSON encoded one
this._formElement.displayErrorMessage();
this._formElement.fireEvent('invalidfield');
}
},
/**
* Validate the fields of the form
*
* @param boolean ajaxCall True if an ajax call has to be done
*/
validate : function(ajaxCall) {
// The submit button is grayed
if (this._submitButton) {
this._submitButton.addClass('WaitingButton');
this._submitButton.setProperty('disabled', 'disabled');
}
// The error message of the form is hidden
this._formElement.hideErrorMessage();
var valid = true;
var invalidFields = new Array();
for (var i = 0; i < this._fields.length; i++) {
for (var j = 0; j < this._fields[i].getValidators().length; j++) {
if (!this._fields[i].getValidators()[j].isValid(this._fields[i])) {
invalidFields.push(this._fields[i]);
}
}
}
// The valid fields error message are hidden
for (var i = 0; i < this._fields.length; i++) {
if (!invalidFields.contains(this._fields[i])) {
this._fields[i].hideErrorMessage();
}
}
// The invalidate fields error message are displayed
if (invalidFields.length) {
invalidFields[0].focus();
// The page is scrolled to the first error message
this._scroller.toElement(invalidFields[0]);
for (var i = 0; i < invalidFields.length; i++) {
invalidFields[i].displayErrorMessage();
}
// The submit button is ungrayed
if (this._submitButton) {
this._submitButton.removeClass('WaitingButton');
this._submitButton.removeProperty('disabled');
}
return false;
} else {
if (ajaxCall) {
// The right page location is set to the action attribute of the form
this._formElement.setProperty('action', window.getCurrentPageUrl());
// The componentName and componentId fields are populated
if (!this._formElement.getChildren().contains($('id_componentName'))) {
if ($('id_componentName')) {
$('id_componentName').remove();
}
(new Element('input').setProperties({name:'componentName',id:'id_componentName',type:'hidden'})).injectBefore(this._formElement.getChildren()[0]);
}
$('id_componentName').setProperty('value', this._formElement.getComponentName());
if (!this._formElement.getChildren().contains($('id_componentId'))) {
if ($('id_componentId')) {
$('id_componentId').remove();
}
(new Element('input').setProperties({name:'componentId',id:'id_componentId',type:'hidden'})).injectBefore(this._formElement.getChildren()[1]);
}
$('id_componentId').setProperty('value', this._formElement.getComponentId());
// The validationInformation field is populated with all the validation information
if (!this._formElement.getChildren().contains($('id_validationInformation'))) {
if ($('id_validationInformation')) {
$('id_validationInformation').remove();
}
(new Element('input').setProperties({name:'validationInformation',id:'id_validationInformation',type:'hidden'})).injectBefore(this._formElement.getChildren()[2]);
}
$('id_validationInformation').setProperty('value', this.getValidationInformation());
// All the fields are ok, then the form is sent
this._formElement.fireEvent('ajaxcall');
this._formElement.send({onComplete:this.onComplete.bind(this)});
return false;
} else {
return true;
}
}
},
createTips : function(field) {
},
/**
* Add a field to the validator
*
* @param Element field The field to validate
* @optionalParam string[] validators The list of validators to apply to the field
*/
addField : function(field, validators) {
var validatorObjects = [];
if (validators && validators.length) {
for (var i = 0; i < validators.length; i++) {
validatorObjects.push(validators[i]);
}
if (field.getStyle('position') == "absolute") {
if (field.parentNode.getElementsByTagName('div').length) {
field._errorImage = field.getParent().getElementsByTagName('div')[0];
field._errorMessage = new Tips(field._errorImage);
}
} else {
if (field.parentNode.getElementsByTagName('div').length) {
if (field.parentNode.getElementsByTagName('div').length) {
// The error fx object is created
field._errorMessage = new Fx.Slide(field.parentNode.getElementsByTagName('div')[0]);
field._errorMessage.hide();
}
}
}
}
field._validators = validatorObjects;
field.getValidators = function() {
return this._validators;
};
field.displayErrorMessage = function() {
if (this._errorMessage) {
if (this.getStyle('position') == "absolute") {
this._errorImage.setStyle('display', 'block');
} else {
this._errorMessage.stop();
this.setStyle('margin-top', '2px');
this._errorMessage.slideIn();
}
}
};
field.hideErrorMessage = function() {
if (this._errorMessage) {
if (this.getStyle('position') == "absolute") {
this._errorImage.setStyle('display', 'none');
} else {
this._errorMessage.stop();
this.setStyle('margin-top', '0px');
this._errorMessage.slideOut();
}
}
};
this._fields.push(field);
// A check to determine if this is the submit button
if (field && field.getProperty('type') && field.getProperty('type').toLowerCase() == 'submit') {
this._submitButton = field;
}
},
/**
* Return the validation information encoded in JSON.
* This is a hash table that have the field name as key and a coma separated validator name as values.
*
* @return string
*/
getValidationInformation : function() {
var validationInformation = {};
this._fields.each(function(field) {
var validators = new Array();
field.getValidators().each(function(validator) {
validators.push(validator.getValidatorName());
});
validationInformation[field.getProperty('name')] = validators.join(',');
});
return Json.toString(validationInformation);
}
});
/**
* The synergee general javascript code.
* This file contains all the necessary code used by the form widget.
*
* Copyright (c) 2007 Pyrameed all right reserved (http://www.pyrameed.com)
*/
/**
* Add two usefull method to the Element objects in order to determine
* its synergee web page parent component name and id.
* Those informations are usefull when dealing with AJAX requests.
*/
Element.extend({
/**
* Return the first synergee web page component name
*
* @return string The first synergee web page component name
*/
getComponentName : function() {
var currentElement = this;
while(!(currentElement.className && currentElement.className.test('Synergee-Web-Page-Component-(.*)-Container', 'i'))) {
currentElement = currentElement.getParent();
}
var regex = new RegExp('Synergee-Web-Page-Component-(.*)-Container', 'i');
var values = regex.exec(currentElement.className);
if (values && values.length == 2) {
return values[1];
} else {
return null;
}
},
/**
* Return the first synergee web page component id
*
* @return string The first synergee web page component id
*/
getComponentId : function() {
var currentElement = this;
while(!(currentElement.className && currentElement.className.test('Synergee-Web-Page-Component-(.*)-Container', 'i'))) {
currentElement = currentElement.getParent();
}
var regex = new RegExp('Synergee-Web-Page-Component-(.*)-Container', 'i');
var values = regex.exec(currentElement.className);
if (values && values.length == 2) {
return currentElement.getParent().id;
} else {
return null;
}
}
});
/**
* The getUrl method is added to the window object in order to be able to get the current page url easily
*/
window.extend({
/**
* Bookmark the current web page
*
* @param string title The page title
* @param string url The web page url
*/
bookmark : function(title, url) {
if (document.all) {
window.external.AddFavorite(url, title);
} else if (window.sidebar) {
window.sidebar.addPanel(title, url, "");
}
},
/**
* Return the current web page url
*
* @return string The current web page url
*/
getCurrentPageUrl : function() {
if (window.location.href.indexOf('?') != -1) {
return window.location.href.substr(0, window.location.href.indexOf('?'));
}
return window.location.href;
},
/**
* Return the current JSON url.
* This url is used by all the JSON invokations
*
* @param Element element The component element
* @return string The current JSON url
*/
getCurrentJsonUrl : function(element) {
var htmlElement = $E('html');
var windowUrl = window.getCurrentPageUrl();
//        if(windowUrl.indexOf('#')){
//            windowUrl = windowUrl.slice(0, windowUrl.indexOf('#'));
//        }
if (htmlElement.getAttribute('designmode') == 'on') {
var webPageId = /webPageId=([0-9]*)/.exec(window.location.href);
return windowUrl + '?webPageId=' + webPageId[1] + '&componentName=' + element.getComponentName() + '&componentId=' + element.getComponentId();
} else {
return windowUrl + '?componentName=' + element.getComponentName() + '&componentId=' + element.getComponentId();
}
},
/**
* Return the currrent page location (the url without the page name)
*
* @return string The current page location
*/
getCurrentPageLocation : function() {
return window.getCurrentPageUrl().substr(0, window.getCurrentPageUrl().lastIndexOf('/')) + '/';
}
});
/**
* Docucment is extended to add the isInDesignMode method.
*/
document.extend({
/**
* This method return true when the page is displayed in the designer
* @return boolean True if the page is displayed in the designer
*/
isInDesignMode : function() {
var htmlElement = $E('html');
return (htmlElement.getAttribute('designmode') == 'on');
}
});
/**
* Decode the html entities
*
* @param String sa
* @return String
*/
function decodeHtmlEntities(sa) {
var ta=document.createElement("textarea");
ta.innerHTML=sa.replace(/</g,"&lt;").replace(/>/g,"&gt;");
return ta.value;
};
/**
* Pad a number regarding the number passed to the pad. By default 2
* @param number valueToPad The value to pad
* @param number pad The pad value
* @return string the padded number
*/
Number.padTo = function(valueToPad, pad) {
pad = pad ? pad : 2;
pad = Math.pow(10, pad-1);
return (valueToPad < pad) ? ("0" + valueToPad) : valueToPad;
};
/**
* Populate the date from an iso formatted string that represent a date
*
* @param string The iso formatted date
*/
Date.prototype.fromIso = function(isoFormattedDate) {
var dateTimeRegex = new RegExp('^([0-9]{4})-([0-9]{2})-([0-9]{2})[T ]([0-9]{2}):([0-9]{2}):([0-9]{2})(([+-])([0-9]{2})(:([0-9]{2}))?)?$');
var dateRegex = new RegExp('^([0-9]{4})-([0-9]{2})-([0-9]{2})$');
var timeRegex = new RegExp('^([0-9]{2}):([0-9]{2}):([0-9]{2})$');
if (dateTimeRegex.test(isoFormattedDate)) {
var values = dateTimeRegex.exec(isoFormattedDate);
var tmpDate = new Date(values[1], values[2] - 1, values[3], values[4], values[5], values[6]);
this.setTime(tmpDate.getTime());
//this.setTime(Date.parse(values[1] + ' ' + values[2] + ' ' + values[3] + ' ' + values[4] + ':' + values[5] + ':' + values[6]));
// The time zone is calculated
if(values[9]){
var timeZoneOffset = -1 * (values[9]*60 + (values[11]?values[11]*1:0)) * (values[8]=='-'?-1:1);
var currentTimeZoneOffset = this.getTimezoneOffset();
this.setTime(this.getTime() + (timeZoneOffset - currentTimeZoneOffset) * 60000);
}
} else if (dateRegex.test(isoFormattedDate)) {
var values = dateRegex.exec(isoFormattedDate);
var tmpDate = new Date(values[1], values[2] - 1, values[3]);
this.setTime(tmpDate.getTime());
//this.setTime(Date.parse(values[1] + ' ' + values[2] + ' ' + values[3]));
} else if (timeRegex.test(isoFormattedDate)) {
var values = timeRegex.exec(isoFormattedDate);
this.setHours(values[1]);
this.setMinutes(values[2]);
this.setSeconds(values[3]);
}
return this;
};
/**
* Return the iso formatted representation of the date
*
* @return string The iso formatted date
*/
Date.prototype.toIso = function() {
var formattedDate = this.getFullYear() + '-' + Number.padTo(this.getMonth()+1) + '-' + Number.padTo(this.getDate());
formattedDate = formattedDate + 'T' + Number.padTo(this.getHours()) + ':' + Number.padTo(this.getMinutes()) + ':' + Number.padTo(this.getSeconds());
return formattedDate;
};
/**
* Return formatted date
*
* @param string format The date output format
* @optionalparam string[] months The translated months
* @return string The formatted date
*/
Date.prototype.format = function(format, months) {
// The date is formatted
format = format.replace('dddd','dd');
format = format.replace('ddd', 'dd');
format = format.replace('dd', Number.padTo(this.getDate()));
format = format.replace('d', this.getDate());
format = format.replace('yyyy', this.getFullYear());
format = format.replace('yy', (new String(this.getFullYear())).substr(2,2));
format = format.replace('y', (new String(this.getFullYear())).substr(2,2));
// The time is formatted
format = format.replace('HH', Number.padTo(this.getHours()));
format = format.replace('H', this.getHours());
format = format.replace('mm', Number.padTo(this.getMinutes()));
format = format.replace('m', this.getMinutes());
format = format.replace('ss', Number.padTo(this.getSeconds()));
format = format.replace('s', this.getSeconds());
if(format.indexOf('MMMM') != -1 && months && months.length && months[this.getMonth()]){
format = format.replace('MMMM', months[this.getMonth()]);
}else{
format = format.replace('MMMM','MM');
format = format.replace('MMM', 'MM');
format = format.replace('MM', Number.padTo(this.getMonth()+1));
format = format.replace('M', this.getMonth()+1);
}
format = format.replace(/['"]/g,'');
return format;
};
/**
* Returns the week number for this date.
* @return int
*/
Date.prototype.getWeek = function() {
var onejan = new Date(this.getFullYear(),0,1);
return Math.ceil((((this - onejan) / 86400000) + onejan.getDay())/7);
};
var BookingCalendar = new Class({
options: {
days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // days of the week starting at sunday
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
offset: 0, // first day of the week: 0 = sunday, 1 = monday, etc..
onHideStart: Class.empty,
onHideComplete: Class.empty,
onShowStart: Class.empty,
onShowComplete: Class.empty
},
// initialize: calendar constructor
// @param props (obj) optional properties
initialize: function(options) {
if(options.days && !options.days.length){
options.days = this.options.days;
}
if(options.months && !options.months.length){
options.months = this.options.months;
}
this.setOptions(options);
this._validDates = new Array();
this._selectedDate = null;
this._linkedElement = null;
this._maxMonth = null;
this._minMonth = null;
var today = new Date();
today.setHours(0);
today.setMinutes(0);
today.setSeconds(0);
today.setMilliseconds(0);
this._todayTime = today.getTime();
// create cal element with css styles required for proper cal functioning
this.calendar = new Element('div', {
'styles': { left: '-1000px', opacity: 0, display:'none', position: 'absolute', top: '-1000px', zIndex: 1000 }
}).addClass('BookingCalendar Synergee-Web-Page-Component-SchoolPriceEstimation-List').injectInside(document.body);
// initialize fade method
this.fx = this.calendar.effect('opacity', {
onStart: function() {
if (this.calendar.getStyle('opacity') == 0) { // show
this.calendar.setStyle('display', 'block');
this.fireEvent('onShowStart', this.element);
}
else { // hide
this.fireEvent('onHideStart', this.element);
}
}.bind(this),
onComplete: function() {
if (this.calendar.getStyle('opacity') == 0) { // hidden
this.calendar.setStyle('display', 'none');
this.fireEvent('onHideComplete', this.element);
}
else { // shown
this.fireEvent('onShowComplete', this.element);
}
}.bind(this)
});
this.calendarPreviousMenu = new Element('input').setProperties({'type':'button', value: '<'}).addClass('NavButton PrevMonth Synergee-Web-Page-Component-SchoolPriceEstimation-List-Item Synergee-Web-Page-Component-ShoppingCart-List-Item').injectInside(this.calendar);
this.calendarNextMenu = new Element('input').setProperties({'type':'button' , value: '>'}).addClass('NavButton NextMonth Synergee-Web-Page-Component-SchoolPriceEstimation-List-Item Synergee-Web-Page-Component-ShoppingCart-List-Item').injectInside(this.calendar);
this.calendarInner = new Element('div',{}).addClass('CalendarInner').injectInside(this.calendar);
this.calendarFirstMonthContainer = new SynergeeCalendarMonth(this.options, this);
this.calendarFirstMonthContainer.getContainer().injectInside(this.calendarInner);
this.calendarSecondMonthContainer = new SynergeeCalendarMonth(this.options, this);
this.calendarSecondMonthContainer.getContainer().injectInside(this.calendarInner);
this.calendarPreviousMenu.addEvent('click', this.prevMonth.bind(this));
this.calendarNextMenu.addEvent('click', this.nextMonth.bind(this));
if(window.ie){
this.calendarPreviousMenu.addEvent('dblclick', this.prevMonth.bind(this));
this.calendarNextMenu.addEvent('dblclick', this.nextMonth.bind(this));
}
document.addEvent('click', function(event){
this.hide();
}.bind(this));
this.calendar.addEvent('click', function(e){
if(window.ie){
window.event.cancelBubble = true;
}else {
e.stopPropagation();
}
}.bind(this));
this.calendar.addEvent('mouseleave', function(){
this._hideDelay = this.hide.delay(2500, this);
}.bind(this));
this.calendar.addEvent('mouseenter', function(){
$clear(this._hideDelay);
}.bind(this));
this.calendarFirstMonthContainer.addEvent('dateselected', this._onDateSelected.bind(this));
this.calendarSecondMonthContainer.addEvent('dateselected', this._onDateSelected.bind(this));
var id = 0;
var d = new Date(); // today
d.setDate(1);
this.displayMonths(d.getMonth(), d.getFullYear());
},
/**
* Display the given month
*
* @param integer month The month 0-11
* @param integer year the year
*/
displayMonths : function(month, year) {
if(parseInt(year + (month > 9 ? '' : '0') + month) > parseInt(this.calendarFirstMonthContainer.year + (this.calendarFirstMonthContainer.month > 9 ? '' : '0') + this.calendarFirstMonthContainer.month)){
this._direction = 1;
} else {
this._direction = 0;
}
$clear(this._updateFirstCalendarTimer);
$clear(this._updateSecondCalendarTimer);
if(this._minMonth && parseInt(this._minMonth) < parseInt(year + (month > 9 ? '' : '0') + month)){
this.calendarPreviousMenu.setStyle('display', '');
}else {
this.calendarPreviousMenu.setStyle('display', 'none');
}
this.calendarFirstMonthContainer.month = month;
this.calendarFirstMonthContainer.year = year;
this.calendarFirstMonthContainer.calendarTitle.setHTML(this.options.months[month] + ' ' + year);
month = this.calendarFirstMonthContainer.month;
year = this.calendarFirstMonthContainer.year;
if (month == 11) {
month = 0;
year++;
} else {
month++;
}
this.calendarSecondMonthContainer.month = month;
this.calendarSecondMonthContainer.year = year;
this.calendarSecondMonthContainer.calendarTitle.setHTML(this.options.months[month] + ' ' + year);
if(this._maxMonth && parseInt(this._maxMonth) > parseInt(year + (month > 9 ? '' : '0') + month)){
this.calendarNextMenu.setStyle('display', '');
}else {
this.calendarNextMenu.setStyle('display', 'none');
}
this._updateFirstCalendarTimer = this.calendarFirstMonthContainer.updateCalendar.delay(100, this.calendarFirstMonthContainer, this._direction);
this._updateSecondCalendarTimer = this.calendarSecondMonthContainer.updateCalendar.delay(100, this.calendarSecondMonthContainer, this._direction);
},
/**
* go to the next month
*/
nextMonth : function(){
var month = this.calendarFirstMonthContainer.month;
var year = this.calendarFirstMonthContainer.year;
if(month == 11){
month= 0;
year++;
}else {
month++;
}
this.displayMonths(month, year);
},
/**
* Go to the previous month
*/
prevMonth : function(){
var month = this.calendarFirstMonthContainer.month;
var year = this.calendarFirstMonthContainer.year;
if(month == 0){
month = 11;
year--;
}else {
month--;
}
this.displayMonths(month, year);
},
/**
* Show the calendar
*
* @param element
*/
show : function(element){
this._linkedElement = element;
var ec = element.getCoordinates();
this.calendar.setStyles({
opacity : 0,
display : 'none',
left : ec.left + ec.width,
top : ec.top
});
this.fx.start(0,1);
},
/**
* Hide the calendar
*/
hide : function(){
if(this.calendar.getStyle('opacity') != 0)
this.fx.start(1,0);
},
/**
* When a date is selected
*
* @param date
*/
_onDateSelected : function(date){
this._selectedDate = date.value;
this.fireEvent('dateselected');
},
/**
* Return the selected date
*/
getSelectedDate : function() {
return this._selectedDate;
},
/**
* set the selected date
* @param date
* @param before
* @param after
*/
setSelectedDate : function(date, before, after) {
var year = date.getFullYear();
var month = date.getMonth();
var dateDay = date.getDate();
this._validDates.each(function(item, index){
if(item.year == year && item.month == month && item.date == dateDay && before == item.additionalNightsBefore && after == item.additionalNightsAfter){
this._selectedDate = item;
}
}.bind(this));
this.displayMonths(month, year);
},
/**
* Set the valid dates
*
* @param date[] validDates The valid date
* @param integer additionalNightsBefore the valid days before the dates
* @param integer additionalNightsAfter The valid days after the dates
* @param boolean onBoundsOnly True if the days before and after are only valid on the boundary dates
*/
setValidDates : function(validDates, additionalNightsBefore, additionalNightsAfter, onBoundsOnly){
if(!additionalNightsBefore)additionalNightsBefore = 0;
if (!additionalNightsAfter)additionalNightsAfter = 0;
this._validDates = new Array();
if (validDates.length) {
this._additionalNightsBefore = additionalNightsBefore;
this._additionalNightsAfter = additionalNightsAfter;
var dateIndex = new Date();
dateIndex.setHours(12);
dateIndex.setMinutes(0);
dateIndex.setSeconds(0);
dateIndex.setMilliseconds(0);
var dayTime = (86400) * 1000; // ms
var firstDate = validDates[0];
validDates.each(function(item, index) {
if (this._additionalNightsBefore && (index == 0 || !onBoundsOnly)) {
dateIndex.setYear(item.getFullYear());
dateIndex.setMonth(item.getMonth());
dateIndex.setDate(item.getDate());
for (var i = 1; i <= this._additionalNightsBefore; i++) {
dateIndex.setTime(dateIndex.getTime() - dayTime);
if(this._todayTime <= dateIndex.getTime()){
var dateObject = new Object();
dateObject.relativeDate = item;
dateObject.additionalNightsBefore = i;
dateObject.additionalNightsAfter = 0;
dateObject.year = dateIndex.getFullYear();
dateObject.month = dateIndex.getMonth();
dateObject.date = dateIndex.getDate();
dateObject.time = dateIndex.getTime();
this._validDates.push(dateObject);
}
}
this._validDates.reverse();
}
var dateObject = new Object();
dateObject.relativeDate = item;
dateObject.additionalNightsBefore = 0;
dateObject.additionalNightsAfter = 0;
dateObject.year = item.getFullYear();
dateObject.month = item.getMonth();
dateObject.date = item.getDate();
dateObject.time = item.getTime();
this._validDates.push(dateObject);
if (this._additionalNightsAfter && (index == validDates.length - 1 || !onBoundsOnly)) {
dateIndex.setYear(item.getFullYear());
dateIndex.setMonth(item.getMonth());
dateIndex.setDate(item.getDate());
for (var i = 1; i <= this._additionalNightsAfter; i++) {
dateIndex.setTime(dateIndex.getTime() + dayTime);
var dateObject = new Object();
dateObject.relativeDate = item;
dateObject.additionalNightsBefore = 0;
dateObject.additionalNightsAfter = i;
dateObject.year = dateIndex.getFullYear();
dateObject.month = dateIndex.getMonth();
dateObject.date = dateIndex.getDate();
dateObject.time = dateIndex.getTime();
this._validDates.push(dateObject);
}
}
if (index == 0) {
firstDate = this._validDates[0];
}
}.bind(this));
}
if(this._validDates.length){
this._maxMonth = this._validDates.getLast().year  + (this._validDates.getLast().month > 9 ? '' : '0') + this._validDates.getLast().month;
this._minMonth = firstDate.year + (firstDate.month > 9 ? '' : '0') + firstDate.month;
}else {
this._maxMonth = null;
this._minMonth = null;
}
this.displayMonths(this.calendarFirstMonthContainer.month, this.calendarFirstMonthContainer.year);
},
/**
* Return the valid dates
*/
getValidDates : function () {
return this._validDates;
},
/**
* Return the valid days before
*/
getValidDaysBefore : function () {
return this._additionalNightsBefore;
},
/**
* Return the linked element
*/
getLinkedElement : function () {
return this._linkedElement;
},
/**
* Return the valid days after
*/
getValidDaysAfter : function () {
return this._additionalNightsAfter;
}
});
BookingCalendar.implement(new Events, new Options);
var SynergeeCalendarMonth = new Class({
options: {
days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // days of the week starting at sunday
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
offset: 1 // first day of the week: 0 = sunday, 1 = monday, etc..
},
initialize: function(options, parent) {
this.setOptions(options);
this._parent = parent;
this.calendarFirstMonthContainer = new Element('div', {}).addClass('MonthContainer');
this.calendarHeaders = new Element('div',{}).addClass('CalendarHeader').injectInside(this.calendarFirstMonthContainer);
this.calendarTitleRow = new Element('div',{}).addClass('CalendarTitleRow').injectInside(this.calendarHeaders);
this.calendarTitle  = new Element('div',{}).addClass('CalendarTitle').injectInside(this.calendarTitleRow);
this.calendarWeekDaysHeader = new Element('div').addClass('WeekDaysHeader').injectInside(this.calendarHeaders);
this.calendarContent = new Element('div',{}).addClass('CalendarContent').injectInside(this.calendarFirstMonthContainer);
this.calendarContentScroller = new Element('div', {}).addClass('CalendarContentScroller').injectInside(this.calendarContent);
this.calendarContent.addEvent('click', this._onClick.bind(this));
this.fxScroll = new Fx.Styles(this.calendarContentScroller,  {duration: 100, transition: Fx.Transitions.linear});
if(!this.options.offset)
this.options.offset = 0;
for(var i = 0; i < 7; i++){
var dayNumber = i+this.options.offset;
if(dayNumber > 6)dayNumber = dayNumber-7;
var dayName = this.options.days[dayNumber];
var dayTitle = new Element('div').addClass('WeekDayHeader').injectInside(this.calendarWeekDaysHeader);
dayTitle.setHTML(dayName.substr(0,2));
}
for(var l = 0; l < 6; l++){
var line = new Element('div').addClass('WeekElement').injectInside(this.calendarContentScroller);
for(i = 0; i < 7; i++){
var day = new Element('div').addClass('DayElement').injectInside(line);
}
}
},
getContainer : function(){
return this.calendarFirstMonthContainer;
},
updateCalendar : function(direction){
var d = new Date(); // today
d.setDate(1);
d.setMonth(this.month);
d.setYear(this.year);
// find the start date
while (d.getDay() != this.options.offset) {
d.setDate(d.getDate() - 1);
}
if (direction) {
this.fxScroll.start({
'margin-left' : [0, -150]
}).chain(function() {
this.start({
'margin-left' : [150, 0]
});
});
} else {
this.fxScroll.start({
'margin-left' : [0, 150]
}).chain(function() {
this.start({
'margin-left' : [-150, 0]
});
});
}
// filter the date concerned by the current month
var validDates = new Hash();
if (this._parent.getValidDates().length) {
this._parent.getValidDates().each(function(item, index) {
// if we are on the current month
if(true || (item.month == this.month && item.year == this.year)){
// if there is already an entry for this date
if(validDates.hasKey(item.year + '-' + item.month + '-' + item.date)){
var currentEntry = validDates.get(item.year + '-' + item.month + '-' + item.date);
// if the space between the real date and the new date is bigger than the new one we replace it
if((currentEntry.additionalNightsBefore + currentEntry.additionalNightsAfter) > (item.additionalNightsBefore + item.additionalNightsAfter)){
validDates.set(item.year + '-' + item.month + '-' + item.date, item);
}
}else {
validDates.set(item.year + '-' + item.month + '-' + item.date, item);
}
}
}.bind(this));
}
for (var l = 0; l < 6; l++) {
var line = this.calendarContentScroller.getChildren()[l];
for (var i = 0; i < 7; i++) {
var dayElement = line.getChildren()[i];
dayElement.valid = true;
dayElement.date = d.getDate();
dayElement.year = d.getFullYear();
dayElement.month = d.getMonth();
dayElement.removeClass('Selected');
dayElement.setHTML(dayElement.date);
dayElement.removeClass('MainDate');
dayElement.removeClass('NotCurrentMonth');
if ((validDates.hasKey(dayElement.year + '-' +  dayElement.month + '-' + dayElement.date) )) {
dayElement.addClass('Synergee-Web-Page-Component-SchoolPriceEstimation-List-Item');
dayElement.addClass('Synergee-Web-Page-Component-ShoppingCart-List-Item');
dayElement.removeClass('Component-NotSelectionable');
dayElement.removeClass('Synergee-Web-Page-Component-SchoolPriceEstimation-NotSelectionable');
dayElement.removeClass('Synergee-Web-Page-Component-ShoppingCart-NotSelectionable');
dayElement.value = validDates.get(dayElement.year + '-' +  dayElement.month + '-' + dayElement.date);
if(dayElement.value.additionalNightsBefore == 0 && dayElement.value.additionalNightsAfter == 0){
dayElement.addClass('MainDate');
}
if(this._parent.getSelectedDate() && this._parent.getSelectedDate().time == dayElement.value.time){
dayElement.addClass('Selected');
}
} else {
dayElement.addClass('Component-NotSelectionable Synergee-Web-Page-Component-SchoolPriceEstimation-NotSelectionable');
dayElement.addClass('Component-NotSelectionable Synergee-Web-Page-Component-ShoppingCart-NotSelectionable');
dayElement.removeClass('Synergee-Web-Page-Component-SchoolPriceEstimation-List-Item');
dayElement.removeClass('Synergee-Web-Page-Component-ShoppingCart-List-Item');
dayElement.valid = false;
}
if(dayElement.month != this.month){
dayElement.addClass('NotCurrentMonth');
}
d.setDate(d.getDate() + 1);
}
}
},
_onClick : function(e){
if(window.ie){
window.event.cancelBubble = true;
}else {
e.stopPropagation();
}
var target = e.target || e.srcElement;
if(target.hasClass('DayElement') && target.valid){
$$('.DayElement').removeClass('Selected');
target.addClass('Selected');
this.fireEvent('dateselected', target);
}
},
getSelectedDate : function(){
return this._parent.getSelectedDate();
}
});
SynergeeCalendarMonth.implement(new Events, new Options);
var Ticker = new Class({
setOptions: function(options) {
this.options = Object.extend({
speed: 1000,
delay: 5000,
onComplete: Class.empty,
onStart: Class.empty
}, options || {});
},
initialize: function(el,options){
this.setOptions(options);
this.el = $(el).getElement('div');
if (this.el.getElement('hr')) {
var children = this.el.childNodes;
var news = new Array();
news.push(new Element('div'));
for (var i = 0; i < children.length; i++) {
if ($type(children[i]) == 'element' && children[i].tagName.toLowerCase() == 'hr') {
news.push(new Element('div'));
} else if (news.length) {
if ($type(children[i]) == 'element') {
news[news.length - 1].appendChild(children[i]);
} else {
news[news.length - 1].appendChild(children[i]);
}
i--;
}
}
this.el.empty();
for(var i = 0; i < news.length; i ++){
this.el.appendChild(news[i]);
}
this.items = this.el.getElements('div');
if (this.items.length) {
var w = 0;
this.items.each(function(item, index) {
w += item.getSize().size.x;
item.addEvent('mouseenter', function(){
$clear(this.delayedFunction);
}.bind(this));
item.addEvent('mouseleave', function(){
this.next();
}.bind(this));
}.bind(this));
this.el.setStyles({
position: 'absolute',
top: 0,
left: 0,
width: w
});
this.periodical =
this.fx = new Fx.Styles(this.el, {duration:this.options.speed,onComplete:function() {
var i = (this.current == 0) ? this.items.length : this.current;
this.items[i - 1].injectInside(this.el);
this.el.setStyle('left', 0);
}.bind(this)});
this.current = this.items.length;
this.next();
}
}
},
next: function() {
this.current++;
if (this.current >= this.items.length) this.current = 0;
this.fx.start({
top: this.items[this.current].offsetTop,
left: -this.items[this.current].offsetLeft
});
this.delayedFunction = this.next.bind(this).delay(this.options.delay);
}
});/**
*  Create a waiting panel object
*
*/
var WaitingPanel = Events.extend({
initialize: function(el) {
if($(el).waitingPanel){
return $(el).waitingPanel;
}
this.el = $(el);
this.el.waitingPanel = this;
},
buildObjects : function() {
// the waiting panel layer and fx style are created
this._waitingPanelLayer = new Element('div', {'class': 'WaitingPanel-AjaxLoading','id':'waitingPanel'});
this._waitingFxStyle = new Fx.Style(this._waitingPanelLayer, 'opacity', {duration:100});
this._waitingPanelLayer.injectAfter(document.getElementsByTagName('div')[0]);
this._waitingPanelLayer.setStyle('position', 'absolute');
this._waitingPanelLayer.setStyles({
opacity : 0
});
this._waitingImageLayer = new Element('div', {'class': 'WaitingPanel-AjaxLoadingImage','id':'waitingPanel'});
this._waitingImageFxStyle = new Fx.Style(this._waitingImageLayer, 'opacity', {duration:100});
this._waitingImageLayer.injectAfter(this._waitingPanelLayer);
this._waitingImageLayer.setStyle('position', 'absolute');
this._waitingImageLayer.setStyles({
opacity : 0
});
},
/**
*  Display a waiting panel layer over the element
*/
display : function() {
if (!this._waitingPanelLayer) {
this.buildObjects();
}
// refresh the height of the waiting panel layer
var coordinates = this.el.getCoordinates();
this._waitingPanelLayer.elementTo = this.el;
this._waitingPanelLayer.setStyles({
height : (coordinates.height + 2),
width : (coordinates.width + 2),
left : (coordinates.left - 2),
top : (coordinates.top - 2)
});
this._waitingImageLayer.setStyles({
height : (coordinates.height + 2),
width : (coordinates.width + 2),
left : (coordinates.left - 2),
top : (coordinates.top - 2)
});
this._waitingFxStyle.start(0, 0.5);
this._waitingImageFxStyle.start(0, 1);
},
/**
* Hide the waiting panel
*/
hide : function() {
if (this._waitingPanelLayer && this._waitingPanelLayer.getStyle('opacity') != 0) {
this._waitingFxStyle.start(0.5, 0);
this._waitingImageFxStyle.start(1, 0);
}
}
});/**
*  Create a message panel object
*
*/
var WindowMessagePanel = Events.extend({
initialize: function(el) {
if ($(el).messagePanel) {
return $(el).messagePanel;
}
this.el = $(el);
this.el.messagePanel = this;
},
/**
* Display a given message
* @param string message The message
* @param integer autoClose The autoclose timer in milliseconds
*/
displayMessage : function(message, title ,autoClose) {
$clear(this.autoClose);
if (!this._messageContainer) {
this._container = new Element('div',{'class': 'Synergee-Web-Page-Component-MessagePanel-Container'});
this._messageContainer = new Element('div', {'class': 'Synergee-Web-Page-Component-MessagePanel'});
this._messageTitle = new Element('div', {'class': 'Synergee-Web-Page-Component-MessagePanel-Title'});
this._messageContainerClose = new Element('div', {'class': 'Synergee-Web-Page-Component-MessagePanel-Close'});
this._messageContainerClose.addEvent('click', this.hideMessage.bind(this));
this._messageContainerClose.setHTML('x');
this._messageTitle.setHTML(title);
this._messageContainerFx = new Fx.Style(this._container, 'opacity', {duration:300});
this._container.injectInside(this.el);
this._messageTitle.injectInside(this._container);
this._messageContainer.injectInside(this._container);
this._messageContainerClose.injectInside(this._container);
this._container.setStyle('position', 'absolute');
this._container.setOpacity(0);
}
this._messageContainer.setHTML(message);
// the waiting panel layer and fx style are created
var containerCoord = this.el.getCoordinates();
this._messageContainerFx.stop();
this._container.setStyles({
'top': (this.el.getCoordinates().height - this._container.getCoordinates().height ) / 2,
'left': (containerCoord.width - 300) / 2,
'width':300,
'min-height':20,
'z-index':10000
});
this._messageContainerFx.start(0, 1);
if (autoClose) {
this.autoClose =  this.hideMessage.delay(autoClose, this);
}
},
getContent : function(){
return this._messageContainer;
},
hideMessage : function() {
$clear(this.autoClose);
this._messageContainerFx.stop();
this._messageContainerFx.start(1, 0);
}
});
var QuickSearch = Events.extend({
initialize : function(resultContainer, containerType) {
if (containerType) {
this._resultContainer =  $(resultContainer);
}
else {
if($$('.'+resultContainer) && $$('.'+resultContainer).length){
this._resultContainer = $$('.'+resultContainer)[0];
}
}
if (this._resultContainer) {
var defaultValue = $('idQuickSearchTextField').getProperty('value');
function onQuickSearchTextFieldClick() {
if($('idQuickSearchTextField').getProperty('value') == defaultValue)
$('idQuickSearchTextField').setProperty('value', '');
};
function onQuickSearchTextFieldClickOut() {
if($('idQuickSearchTextField').getProperty('value') == '')
$('idQuickSearchTextField').setProperty('value', defaultValue);
};
$('idQuickSearchTextField').addEvent('focus', onQuickSearchTextFieldClick);
$('idQuickSearchTextField').addEvent('blur', onQuickSearchTextFieldClickOut);
$('idQuickSearchTextField').addClass('QuickSearchText');
this._waitingPanel = new WaitingPanel(this._resultContainer);
$('id_QuickSearchForm').addEvent('submit', function(){
this._waitingPanel.display();
}.bind(this));
}
},
highlight : function (oElements, sSearch) {
if (sSearch) {
var searchParts = sSearch.split(' ');
if (oElements && oElements.length) {
for (var i = 0; i < oElements.length; i++) {
for (var j = 0; j < searchParts.length; j++) {
oElements[i].setHTML(oElements[i].innerHTML.replace(new RegExp('(' + searchParts[j] + ')', 'ig'), '<span class="highlighted">$1</span>'));
}
}
}
}
},
handleResponse : function (response) {
if(this._resultContainer){
var recherche = $("idQuickSearchTextField").value;
this._resultContainer.setHTML(response);
this.highlight(this._resultContainer.getElements(".Synergee-Web-Page-Component-QuickSearch-Results-Page-Title a"), recherche);
this.highlight(this._resultContainer.getElements(".Synergee-Web-Page-Component-QuickSearch-Results-Page-Description"), recherche);
this.highlight(this._resultContainer.getElements(".Synergee-Web-Page-Component-QuickSearch-Results-Page-Url a"), recherche);
this._waitingPanel.hide();
var nbResults = $$('.Synergee-Web-Page-Component-QuickSearch-Item').length;
if (nbResults > 10 && nbResults <= 100) {
var resultsHelper = new ResultHelper(10, nbResults);
resultsHelper.injectNavBar('Synergee-Web-Page-Component-QuickSearch-NavigationBars', 'button', 'QuickSearchNav', '');
$$('.QuickSearchNavNext').addEvent('click', function (e) {
resultsHelper.nextPage();
if (e.target) e.target.blur();
else e.srcElement.blur();
});
$$('.QuickSearchNavPrevious').addEvent('click', function (e) {
resultsHelper.previousPage();
if (e.target) e.target.blur();
else e.srcElement.blur();
});
resultsHelper.addEvent('onPageChangeBefore', function () {
$$('.Synergee-Web-Page-Component-QuickSearch-Page' + resultsHelper.getCurrentPage()).setStyle('display','none');
$$('.QuickSearchNav' + resultsHelper.getCurrentPage()).removeClass('Synergee-Web-Page-Component-QuickSearch-NavigationBars-Selected');
$$('.QuickSearchNav' + resultsHelper.getCurrentPage()).addClass('Synergee-Web-Page-Component-QuickSearch-NavigationBars-Default');
$$('.QuickSearchNav' + resultsHelper.getCurrentPage()).removeClass('QuickSearchNavButtonSelectedColor');
$$('.QuickSearchNav' + resultsHelper.getCurrentPage()).addClass('QuickSearchNavButtonDefaultColor');
$$('.QuickSearchNavNext').removeClass('QuickSearchNavButtonSelectedColor');
});
resultsHelper.addEvent('onPageChangeAfter', function () {
$$('.Synergee-Web-Page-Component-QuickSearch-Page' + resultsHelper.getCurrentPage()).setStyle('display','block');
$$('.QuickSearchNav' + resultsHelper.getCurrentPage()).removeClass('Synergee-Web-Page-Component-QuickSearch-NavigationBars-Default');
$$('.QuickSearchNav' + resultsHelper.getCurrentPage()).addClass('Synergee-Web-Page-Component-QuickSearch-NavigationBars-Selected');
$$('.QuickSearchNav' + resultsHelper.getCurrentPage()).removeClass('QuickSearchNavButtonDefaultColor');
$$('.QuickSearchNav' + resultsHelper.getCurrentPage()).addClass('QuickSearchNavButtonSelectedColor');
$$('.QuickSearchNavPrevious').removeClass('QuickSearchNavButtonSelectedColor');
});
resultsHelper.addEvent('onPageChangeLowerLimit', function () {
$$('.QuickSearchNavPrevious').addClass('QuickSearchNavButtonSelectedColor');
});
resultsHelper.addEvent('onPageChangeUpperLimit', function () {
$$('.QuickSearchNavNext').addClass('QuickSearchNavButtonSelectedColor');
});
for (var i=0; i < resultsHelper.getCountPages(); i++) {
$$('.QuickSearchNav'+i).each(function (e) { e.pageNumber = i; });
$$('.QuickSearchNav'+i).addClass('Synergee-Web-Page-Component-QuickSearch-NavigationBars-Default');
$$('.QuickSearchNav'+i).addClass('QuickSearchNavButtonDefaultColor');
$$('.QuickSearchNav'+i).addEvent('click', function (e) {
if (e.target) {
resultsHelper.selectPage(e.target.pageNumber);
e.target.blur();
}
else {
resultsHelper.selectPage(e.srcElement.pageNumber);
e.srcElement.blur();
}
});
}
$$('.QuickSearchNav0').removeClass('Synergee-Web-Page-Component-QuickSearch-NavigationBars-Default');
$$('.QuickSearchNav0').removeClass('QuickSearchNavButtonDefaultColor');
$$('.QuickSearchNav0').addClass('Synergee-Web-Page-Component-QuickSearch-NavigationBars-Selected');
$$('.QuickSearchNav0').addClass('QuickSearchNavButtonSelectedColor');
// comment/uncomment the following 2 lines to put/remove a results nav bar on top (also comment/uncomment relevant part in QuickSearch.xsl)
//            $('idQuickSearchNavPreviousTop').setStyle('display','inline');
//            $('idQuickSearchNavNextTop').setStyle('display','inline');
// comment/uncomment the following 2 lines to put/remove a results nav bar on bottom (also comment/uncomment relevant part in QuickSearch.xsl)
//            $('idQuickSearchNavPreviousBottom').setStyle('display','inline');
//            $('idQuickSearchNavNextBottom').setStyle('display','inline');
$$('.QuickSearchNavPrevious').addClass('QuickSearchNavButtonSelectedColor');
}
}
}
});
var WebsiteSelector = Options.extend({
initialize: function(componentId) {
this._componentId = componentId;
this._websiteList = $(this._componentId + '_siteSelectorLanguageListId');
this._textLink = $(this._componentId + '_siteSelectorLanguageText');
this._websiteList.setStyle('margin-top', '-540000px');
window.addEvent('load', function(){
this._height = this._websiteList.getCoordinates().height;
$(this._componentId + '_siteSelectorCurrentSelectionId').addEvent('mouseover', this.displaySiteSelector.bind(this));
$(this._componentId + '_siteSelectorCurrentSelectionId').getParent().addEvent('mouseleave', this.hideSiteSelector.bind(this));
this._websiteList.setStyle('margin-top', '');
if(this.listFx)this.listFx.set(0);
this._websiteList.addClass('HideClass');
}.bind(this));
try {
this._websiteList.addClass('SiteSelectorLanguageListFx');
} catch(ex) {
}
if (!document.isInDesignMode()) {
this._fxTime = 300;
this.listFx = new Fx.Style($(this._componentId + '_siteSelectorLanguageListId'), 'height', {wait:false, duration:this._fxTime});
this._textFx = new Fx.Style($(this._componentId + '_siteSelectorLanguageText'), 'opacity', {wait:false, duration:this._fxTime / 2});
}
},
hideSiteSelector : function(e) {
var target = e.relatedTarget;
while (target && target.getAttribute && (target.getAttribute('id') != this._componentId + '_siteSelectorCurrentSelectionId' && target.getAttribute('id') != this._componentId + '_siteSelectorLanguageListId')) {
if (target.getParent && target.getParent()) {
target = target.getParent();
} else {
target = false;
}
}
if (target != this._websiteList) {
this.listFx.stop();
this.listFx.start(this._websiteList.getCoordinates().height, 0);
this._textFx.stop();
this._textFx.start(this._textLink.getStyle('opacity'), 1);
this._websiteList.addClass('HideClass');
}
},
displaySiteSelector : function(e) {
this._websiteList.removeClass('HideClass');
this._textFx.stop();
this.listFx.stop();
var height = this._websiteList.getCoordinates().height;
if(height < this._websiteList.getCoordinates().height)height =  this._websiteList.getCoordinates().height;
this.listFx.start(height, this._height);
this._textFx.start(this._textLink.getStyle('opacity'), 0);
}
});
/*
Copyright (c) 2006-7, Tom Carden, Steve Coast, Mikel Maron, Andrew Turner
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the Mapstraction nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Use http://jsdoc.sourceforge.net/ to generate documentation
////////////////////////////
//
// utility to functions, TODO namespace or remove before release
//
///////////////////////////
/**
* $, the dollar function, elegantising getElementById()
* @returns an element
*/
function $m() {
var elements = new Array();
for (var i = 0; i < arguments.length; i++) {
var element = arguments[i];
if (typeof element == 'string')
element = document.getElementById(element);
if (arguments.length == 1)
return element;
elements.push(element);
}
return elements;
}
/**
* loadScript is a JSON data fetcher
*/
function loadScript(src,callback) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
if (callback) {
var evl=new Object();
evl.handleEvent=function (e){callback();};
script.addEventListener('load',evl,true);
}
document.getElementsByTagName("head")[0].appendChild(script);
return;
}
function convertLatLonXY_Yahoo(point,level){ //Mercator
var size = 1 << (26 - level);
var pixel_per_degree = size / 360.0;
var pixel_per_radian = size / (2 * Math.PI);
var origin = new YCoordPoint(size / 2 , size / 2);
var answer = new YCoordPoint();
answer.x = Math.floor(origin.x + point.lon * pixel_per_degree);
var sin = Math.sin(point.lat * Math.PI / 180.0);
answer.y = Math.floor(origin.y + 0.5 * Math.log((1 + sin) / (1 - sin)) * -pixel_per_radian);
return answer;
}
/**
*
*/
function loadStyle(href) {
var link = document.createElement('link');
link.type = 'text/css';
link.rel = 'stylesheet';
link.href = href;
document.getElementsByTagName("head")[0].appendChild(link);
return;
}
/**
* getStyle provides cross-browser access to css
*/
function getStyle(el, prop) {
var y;
if (el.currentStyle)
y = el.currentStyle[prop];
else if (window.getComputedStyle)
y = window.getComputedStyle( el, '').getPropertyValue(prop);
return y;
}
// longitude to metres
// http://www.uwgb.edu/dutchs/UsefulData/UTMFormulas.HTM
// "A degree of longitude at the equator is 111.2km... For other latitudes,
// multiply by cos(lat)"
// assumes the earth is a sphere but good enough for our purposes
function lonToMetres (lon,lat) {
return lon * 111200 * Math.cos(lat * (Math.PI/180));
}
function metresToLon(m,lat) {
return m / (111200*Math.cos(lat * (Math.PI/180)));
}
// stuff to convert google zoom levels to/from degrees
// assumes zoom 0 = 256 pixels = 360 degrees
//         zoom 1 = 256 pixels = 180 degrees
// etc.
function getDegreesFromGoogleZoomLevel (pixels,zoom)
{
return (360*pixels) / (Math.pow(2,zoom+8));
}
function getGoogleZoomLevelFromDegrees (pixels,degrees)
{
return logN ((360*pixels)/degrees, 2) - 8;
}
function logN (number,base)
{
return Math.log(number) / Math.log(base);
}
/////////////////////////////
//
// Mapstraction proper begins here
//
/////////////////////////////
/**
* Mapstraction instantiates a map with some API choice into the HTML element given
* @param {String} element The HTML element to replace with a map
* @param {String} api The API to use, one of 'google', 'yahoo', 'microsoft', 'openstreetmap', 'multimap', 'map24', 'openlayers', 'mapquest'
* @param {Bool} debug optional parameter to turn on debug support - this uses alert panels for unsupported actions
* @constructor
*/
function Mapstraction(element,api,debug) {
this.api = api; // could detect this from imported scripts?
this.maps = new Object();
this.currentElement = $m(element);
this.eventListeners = new Array();
this.markers = new Array();
this.polylines = new Array();
this.images = new Array();
this.loaded = new Object();
this.onload = new Object();
// optional debug support
if(debug == true)
this.debug = true
else
this.debug = false
// This is so that it is easy to tell which revision of this file
// has been copied into other projects.
this.svn_revision_string = '$Revision$';
this.addControlsArgs = new Object();
this.addAPI($m(element),api);
}
/**
* swap will change the current api on the fly
* @param {String} api The API to swap to
*/
Mapstraction.prototype.swap = function(element,api) {
if (this.api == api) { return; }
var center = this.getCenter();
var zoom = this.getZoom();
this.currentElement.style.visibility = 'hidden';
this.currentElement.style.display = 'none';
this.currentElement = $m(element);
this.currentElement.style.visibility = 'visible';
this.currentElement.style.display = 'block';
this.api = api;
if (this.maps[this.api] == undefined) {
this.addAPI($m(element),api);
this.setCenterAndZoom(center,zoom);
for (var i=0; i<this.markers.length; i++) {
this.addMarker( this.markers[i], true);
}
for (var i=0; i<this.polylines.length; i++) {
this.addPolyline( this.polylines[i], true);
}
}else{
//sync the view
this.setCenterAndZoom(center,zoom);
//TODO synchronize the markers and polylines too
// (any overlays created after api instantiation are not sync'd)
}
this.addControls(this.addControlsArgs);
}
Mapstraction.prototype.addAPI = function(element,api) {
me = this;
this.loaded[api] = false;
this.onload[api] = new Array();
switch (api) {
case 'yahoo':
if (YMap) {
this.maps[api] = new YMap(element);
YEvent.Capture(this.maps[api],EventsList.MouseClick,function(event,location) { me.clickHandler(location.Lat,location.Lon,location,me) });
YEvent.Capture(this.maps[api],EventsList.changeZoom,function() { me.moveendHandler(me) });
YEvent.Capture(this.maps[api],EventsList.endPan,function() { me.moveendHandler(me) });
this.loaded[api] = true;
}
else {
alert('Yahoo map script not imported');
}
break;
case 'google':
if (GMap2) {
if (GBrowserIsCompatible()) {
this.maps[api] = new GMap2(element);
GEvent.addListener(this.maps[api], 'click', function(marker,location) {
// If the user puts their own Google markers directly on the map
// then there is no location and this event should not fire.
if ( location ) {
me.clickHandler(location.y,location.x,location,me);
}
});
GEvent.addListener(this.maps[api], 'moveend', function() {me.moveendHandler(me)});
this.loaded[api] = true;
}
else {
alert('browser not compatible with Google Maps');
}
}
else {
alert('Google map script not imported');
}
break;
case 'microsoft':
if (VEMap) {
element.style.position='relative';
var msft_width = parseFloat(getStyle($m(element),'width'));
var msft_height = parseFloat(getStyle($m(element),'height'));
/* Hack so the VE works with FF2 */
var ffv = 0;
var ffn = "Firefox/";
var ffp = navigator.userAgent.indexOf(ffn);
if (ffp != -1) ffv = parseFloat(navigator.userAgent.substring(ffp+ffn.length));
if (ffv >= 1.5) {
Msn.Drawing.Graphic.CreateGraphic=function(f,b) { return new Msn.Drawing.SVGGraphic(f,b) }
}
this.maps[api] = new VEMap(element.id);
this.maps[api].LoadMap();
this.maps[api].AttachEvent("onclick", function(e) { me.clickHandler(e.view.LatLong.Latitude, e.view.LatLong.Longitude, me); });
this.maps[api].AttachEvent("onchangeview", function(e) {me.moveendHandler(me)});
//Source of our trouble with Mapufacture?
this.resizeTo(msft_width, msft_height);
this.loaded[api] = true;
}
else {
alert('Virtual Earth script not imported');
}
break;
case 'openlayers':
this.maps[api] = new OpenLayers.Map(element.id);
this.loaded[api] = true;
break;
case 'openstreetmap':
// for now, osm is a hack on top of google
if (GMap2) {
if (GBrowserIsCompatible()) {
this.maps[api] = new GMap2(element);
GEvent.addListener(this.maps[api], 'click', function(marker,location) {
// If the user puts their own Google markers directly on the map
// then there is no location and this event should not fire.
if ( location ) {
me.clickHandler(location.y,location.x,location,me);
}
});
GEvent.addListener(this.maps[api], 'moveend', function() {me.moveendHandler(me)});
// Add OSM tiles
var copyright = new GCopyright(1, new GLatLngBounds(new GLatLng(-90,-180), new GLatLng(90,180)), 0, "copyleft");
var copyrightCollection = new GCopyrightCollection('OSM');
copyrightCollection.addCopyright(copyright);
var tilelayers = new Array();
tilelayers[0] = new GTileLayer(copyrightCollection, 1, 18);
tilelayers[0].getTileUrl = function (a, b) {
return "http://tile.openstreetmap.org/"+b+"/"+a.x+"/"+a.y+".png";
};
tilelayers[0].isPng = function() { return true;};
tilelayers[0].getOpacity = function() { return 1.0; }
var custommap = new GMapType(tilelayers, new GMercatorProjection(19), "OSM", {errorMessage:"More OSM coming soon"});
this.maps[api].addMapType(custommap);
this.loaded[api] = true;
var myPoint = new LatLonPoint(50.6805,-1.4062505);
this.setCenterAndZoom(myPoint, 11);
this.maps[api].setMapType(custommap);
}
else {
alert('browser not compatible with Google Maps');
}
}
else {
alert('Google map script not imported');
}
break;
case 'multimap':
this.maps[api] = new MultimapViewer( element );
this.maps[api].addEventHandler( 'click', function(eventType, eventTarget, arg1, arg2, arg3) {
if (arg1) {
me.clickHandler(arg1.lat, arg1.lon, me);
}
});
this.maps[api].addEventHandler( 'changeZoom', function(eventType, eventTarget, arg1, arg2, arg3) {
me.moveendHandler(me);
});
this.maps[api].addEventHandler( 'endPan', function(eventType, eventTarget, arg1, arg2, arg3) {
me.moveendHandler(me);
});
this.loaded[api] = true;
break;
case 'map24':
// Copied from Google and modified
if (Map24) {
Map24.loadApi(["core_api","wrapper_api"] , function() {
Map24.MapApplication.init
( { NodeName: element.id, MapType: "Static" } );
me.maps[api] = Map24.MapApplication.Map;
Map24.MapApplication.Map.addListener('Map24.Event.MapClick',
function(e) {
me.clickHandler(e.Coordinate.Latitude/60,
e.Coordinate.Longitude/60,
me);
e.stop();
}
);
Map24.MapApplication.Map.addListener("MapPanStop",
function(e) {
me.moveendHandler(me);
}
);
/**/
var client=Map24.MapApplication.Map.MapClient['Static'];
/*
These *will* cause the specified listener to run when we stop
panning the map, but the default pan stop handler will be
cancelled. The result of this will be that when we have stopped
panning, we will permanently be in 'pan' mode and unable to do
anything else (e.g. click on the map to create a new marker).
var defaultOnPanStop = client.onPanStop;
var defaultOnZoomInStop = client.onZoomInStop;
var defaultOnZoomOutStop = client.onZoomOutStop;
client.onPanStop = function(e)
{ me.moveendHandler(me); defaultOnPanStop(e);
status('DEFAULTONPANSTOP DONE');}
// Handle zoom events - these also fire moveendHandler for the
// other APIs in Mapstraction
client.onZoomInStop = function(e)
{ me.moveendHandler(me); defaultOnZoomInStop(e); }
client.onZoomOutStop = function(e)
{ me.moveendHandler(me); defaultOnZoomOutStop(e);  }
*/
me.loaded[api] = true;
for (var i = 0; i < me.onload[api].length; i++) {
me.onload[api][i]();
}
}, "2.0.1247" );
} else {
alert('map24 api not loaded');
}
break;
case 'mapquest':
MQInitOverlays( function() {
self.loaded[api] = true;
self.maps[api] = new MQTileMap(element);
for (var i = 0; i < self.onload[api].length; i++) {
self.onload[api][i]();
}
});
// MQEventManager.addListener(this.maps[api],"click",function(event,location) { me.clickHandler(location.Lat,location.Lon,location,me) });
// MQEventManager.addListener(this.maps[api],"zoomend",function() { me.moveendHandler(me) });
// MQEventManager.addListener(this.maps[api],"moveend",function() { me.moveendHandler(me) });
break;
case 'freeearth':
this.maps[api] = new FE.Map($m(element));
self = this;
this.maps[api].onLoad = function() {
self.freeEarthLoaded = true;
self.loaded[api] = true;
for (var i = 0; i < self.onload[api].length; i++) {
self.onload[api][i]();
}
}
this.maps[api].load();
break;
default:
if(this.debug)
alert(api + ' not supported by mapstraction');
}
// this.resizeTo(getStyle($m(element),'width'), getStyle($m(element),'height'));
// the above line was called on all APIs but MSFT alters with the div size when it loads
// so you have to find the dimensions and set them again (see msft constructor).
// FIXME: test if google/yahoo etc need this resize called. Also - getStyle returns
// CSS size ('200px') not an integer, and resizeTo seems to expect ints
}
/* Returns the loaded state of a Map Provider
*
* @param {String} api Optional API to query for. If not specified, returns state of the originally created API
* @returns the state of the map loading
* @type Boolean
*/
Mapstraction.prototype.isLoaded = function(api){
if(api == null)
api = this.api;
return this.loaded[api];
}
/* Set the debugging on or off - shows alert panels for functions that don't exist in Mapstraction
*
* @param {Bool} debug true to turn on debugging, false to turn it off
* @returns the state of debugging
* @type Boolean
*/
Mapstraction.prototype.setDebug = function(debug){
if(debug != null)
return this.debug = debug;
else
return this.debug;
}
/* Resize the current map to the specified width and height
* (since it is actually on a child div of the mapElement passed
* as argument to the Mapstraction constructor, the resizing of this
* mapElement may have no effect on the size of the actual map)
*
* @param {int} width The width the map should be.
* @param {int} height The width the map should be.
*/
Mapstraction.prototype.resizeTo = function(width,height){
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.resizeTo(width,height); } );
return;
}
switch (this.api) {
case 'yahoo':
this.maps[this.api].resizeTo(new YSize(width,height));
break;
case 'google':
case 'openstreetmap':
this.currentElement.style.width = width;
this.currentElement.style.height = height;
this.maps[this.api].checkResize();
break;
case 'microsoft':
this.maps[this.api].Resize(width, height);
break;
case 'multimap':
this.currentElement.style.width = width;
this.currentElement.style.height = height;
this.maps[this.api].resize();
break;
case 'mapquest':
this.currentElement.style.width = width;
this.currentElement.style.height = height;
this.maps[this.api].setSize(new MQSize(width, height));
break;
case 'map24':
Map24.MapApplication.Map.Canvas['c'].resizeTo(width,height);
break;
}
}
/////////////////////////
//
// Event Handling
//
///////////////////////////
Mapstraction.prototype.clickHandler = function(lat,lon, me) { //FIXME need to consolidate some of these handlers...
for(var i = 0; i < this.eventListeners.length; i++) {
if(this.eventListeners[i][1] == 'click') {
this.eventListeners[i][0](new LatLonPoint(lat,lon));
}
}
}
Mapstraction.prototype.moveendHandler = function(me) {
for(var i = 0; i < this.eventListeners.length; i++) {
if(this.eventListeners[i][1] == 'moveend') {
this.eventListeners[i][0]();
}
}
}
Mapstraction.prototype.addEventListener = function(type, func) {
var listener = new Array();
listener.push(func);
listener.push(type);
this.eventListeners.push(listener);
}
////////////////////
//
// map manipulation
//
/////////////////////
/**
* addControls adds controls to the map. You specify which controls to add in
* the associative array that is the only argument.
* addControls can be called multiple time, with different args, to dynamically change controls.
*
* args = {
*     pan:      true,
*     zoom:     'large' || 'small',
*     overview: true,
*     scale:    true,
*     map_type: true,
* }
*
* @param {args} array Which controls to switch on
*/
Mapstraction.prototype.addControls = function( args ) {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.addControls(args); } );
return;
}
var map = this.maps[this.api];
this.addControlsArgs = args;
switch (this.api) {
case 'google':
case 'openstreetmap':
//remove old controls
if (this.controls) {
while (ctl = this.controls.pop()) {
map.removeControl(ctl);
}
} else {
this.controls = new Array();
}
c = this.controls;
// Google has a combined zoom and pan control.
if ( args.zoom || args.pan ) {
if ( args.zoom == 'large' ) {
c.unshift(new GLargeMapControl());
map.addControl(c[0]);
} else {
c.unshift(new GSmallMapControl());
map.addControl(c[0]);
}
}
if ( args.scale    ) { c.unshift(new GScaleControl()); map.addControl(c[0]); }
if (this.api != "openstreetmap") {
if ( args.overview ) { c.unshift(new GOverviewMapControl()); map.addControl(c[0]); }
if ( args.map_type ) { c.unshift(new GMapTypeControl()); map.addControl(c[0]); }
}
break;
case 'yahoo':
if ( args.pan             ) map.addPanControl();
else map.removePanControl();
if ( args.zoom == 'large' ) map.addZoomLong();
else if ( args.zoom == 'small' ) map.addZoomShort();
else map.removeZoomScale();
break;
case 'openlayers':
// FIXME - which one should this be?
map.addControl(new OpenLayers.Control.LayerSwitcher());
break;
case 'multimap':
//FIXME -- removeAllWidgets();  -- can't call addControls repeatedly
pan_zoom_widget = "MM";
if (args.zoom && args.zoom == "small") { pan_zoom_widget = pan_zoom_widget + "Small"; }
if (args.pan) { pan_zoom_widget = pan_zoom_widget + "Pan"; }
if (args.zoom) { pan_zoom_widget = pan_zoom_widget + "Zoom"; }
pan_zoom_widget = pan_zoom_widget + "Widget";
if (pan_zoom_widget != "MMWidget") {
eval(" map.addWidget( new " + pan_zoom_widget + "() );");
}
if ( args.map_type ) { map.addWidget( new MMMapTypeWidget() ); }
if ( args.overview ) { map.addWidget( new MMOverviewWidget() ); }
break;
case 'mapquest':
//remove old controls
if (this.controls) {
while (ctl = this.controls.pop()) {
map.removeControl(ctl);
}
} else {
this.controls = new Array();
}
c = this.controls;
if ( args.pan ) { c.unshift(new MQPanControl()); map.addControl(c[0], new MQMapCornerPlacement(MQMapCorner.TOP_LEFT, new MQSize(0,0))); }
if ( args.zoom == 'large' ) { c.unshift(new MQLargeZoomControl()); map.addControl(c[0], new MQMapCornerPlacement(MQMapCorner.TOP_LEFT, new MQSize(0,0))); }
else if ( args.zoom == 'small' ) { c.unshift(new MQZoomControl()); map.addControl(c[0],  new MQMapCornerPlacement(MQMapCorner.BOTTOM_LEFT, new MQSize(0,0))); }
// TODO: Map View Control is wonky
if ( args.map_type ) { c.unshift(new MQViewControl()); map.addControl(c[0], new MQMapCornerPlacement(MQMapCorner.TOP_RIGHT, new MQSize(0,0))); }
break;
}
}
/**
* addSmallControls adds a small map panning control and zoom buttons to the map
* Supported by: yahoo, google, openstreetmap, openlayers, multimap, mapquest
*/
Mapstraction.prototype.addSmallControls = function() {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.addSmallControls(); } );
return;
}
var map = this.maps[this.api];
switch (this.api) {
case 'yahoo':
map.addPanControl();
map.addZoomShort();
this.addControlsArgs.pan = true;
this.addControlsArgs.zoom = 'small';
break;
case 'google':
case 'openstreetmap':
map.addControl(new GSmallMapControl());
this.addControlsArgs.zoom = 'small';
break;
case 'openlayers':
map.addControl(new OpenLayers.Control.LayerSwitcher());
break;
case 'multimap':
smallPanzoomWidget = new MMSmallPanZoomWidget();
map.addWidget( smallPanzoomWidget );
this.addControlsArgs.pan = true;
this.addControlsArgs.zoom = 'small';
break;
case 'mapquest':
map.addControl(new MQZoomControl(map));
map.addControl(new PanControl(map));
this.addControlsArgs.pan = true;
this.addControlsArgs.zoom = 'small';
break;
}
}
/**
* addLargeControls adds a small map panning control and zoom buttons to the map
* Supported by: yahoo, google, openstreetmap, multimap, mapquest
*/
Mapstraction.prototype.addLargeControls = function() {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.addLargeControls(); } );
return;
}
var map = this.maps[this.api];
switch (this.api) {
case 'yahoo':
map.addPanControl();
map.addZoomLong();
this.addControlsArgs.pan = true;  // keep the controls in case of swap
this.addControlsArgs.zoom = 'large';
break;
case 'google':
map.addControl(new GMapTypeControl());
map.addControl(new GOverviewMapControl()) ;
this.addControlsArgs.overview = true;
this.addControlsArgs.map_type = true;
case 'openstreetmap':
map.addControl(new GLargeMapControl());
map.addControl(new GScaleControl()) ;
this.addControlsArgs.pan = true;
this.addControlsArgs.zoom = 'large';
this.addControlsArgs.scale = true;
break;
case 'multimap':
panzoomWidget = new MMPanZoomWidget();
map.addWidget( panzoomWidget );
this.addControlsArgs.pan = true;  // keep the controls in case of swap
this.addControlsArgs.zoom = 'large';
break;
case 'mapquest':
map.addControl(new MQLargeZoomControl(map));
map.addControl(new PanControl(map));
map.addControl(new MQViewControl(map));
this.addControlsArgs.pan = true;
this.addControlsArgs.zoom = 'large';
this.addControlsArgs.map_type = true;
break;
}
}
/**
* addMapTypeControls adds a map type control to the map (streets, aerial imagery etc)
* Supported by: yahoo, google, openstreetmap, multimap, mapquest
*/
Mapstraction.prototype.addMapTypeControls = function() {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.addMapTypeControls(); } );
return;
}
var map = this.maps[this.api];
switch (this.api) {
case 'yahoo':
map.addTypeControl();
break;
case 'google':
case 'openstreetmap':
map.addControl(new GMapTypeControl());
break;
case 'multimap':
map.addWidget( new MMMapTypeWidget() );
break;
case 'mapquest':
map.addControl(new MQViewControl(map));
break;
}
}
/**
* dragging
*  enable/disable dragging of the map
*  (only implemented for yahoo and google)
* Supported by: yahoo, google, openstreetmap, multimap
* @param {on} on Boolean
*/
Mapstraction.prototype.dragging = function(on) {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.dragging(on); } );
return;
}
var map = this.maps[this.api];
switch (this.api) {
case 'google':
case 'openstreetmap':
if (on) {
map.enableDragging();
} else {
map.disableDragging();
}
break;
case 'yahoo':
if (on) {
map.enableDragMap();
} else {
map.disableDragMap();
}
break;
case 'multimap':
if (on) {
map.setOption("drag","dragmap");
} else {
map.setOption("drag","");
}
break;
case 'mapquest':
map.enableDragging(on);
break;
}
}
/**
* centers the map to some place and zoom level
* @param {LatLonPoint} point Where the center of the map should be
* @param {int} zoom The zoom level where 0 is all the way out.
*/
Mapstraction.prototype.setCenterAndZoom = function(point, zoom) {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.setCenterAndZoom(point, zoom); } );
return;
}
var map = this.maps[this.api];
switch (this.api) {
case 'yahoo':
var yzoom = 18 - zoom; // maybe?
map.drawZoomAndCenter(point.toYahoo(),yzoom);
break;
case 'google':
case 'openstreetmap':
map.setCenter(point.toGoogle(), zoom);
break;
case 'microsoft':
map.SetCenterAndZoom(point.toMicrosoft(),zoom);
break;
case 'openlayers':
map.setCenter(new OpenLayers.LonLat(point.lng, point.lat), zoom);
break;
case 'multimap':
map.goToPosition( new MMLatLon( point.lat, point.lng ) );
map.setZoomFactor( zoom );
break;
case 'map24':
var newSettings = new Object();
newSettings.Latitude = point.lat*60;
newSettings.Longitude = point.lon*60;
var client = map.MapClient['Static'];
var dLon = getDegreesFromGoogleZoomLevel
(client.getCanvasSize().Width,zoom);
newSettings.MinimumWidth = lonToMetres (dLon, point.lat);
Map24.MapApplication.center ( newSettings );
break;
case 'mapquest':
// MapQuest's zoom levels appear to be off by '3' from the other providers for the same bbox
map.setCenter(new MQLatLng( point.lat, point.lng ), zoom - 3 );
break;
case 'freeearth':
if (this.freeEarthLoaded) {
map.setTargetLatLng( point.toFreeEarth() );
} else {
self = this;
this.freeEarthOnLoad.push( function() { self.setCenterAndZoom(point); } );
}
break;
default:
if(this.debug)
alert(this.api + ' not supported by Mapstraction.setCenterAndZoom');
}
}
/**
* addMarker adds a marker pin to the map
* @param {Marker} marker The marker to add
* @param {old} old If true, doesn't add this marker to the markers array. Used by the "swap" method
*/
Mapstraction.prototype.addMarker = function(marker,old) {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.addMarker(marker, old); } );
return;
}
var map = this.maps[this.api];
marker.api = this.api;
marker.map = this.maps[this.api];
switch (this.api) {
case 'yahoo':
var ypin = marker.toYahoo();
marker.setChild(ypin);
map.addOverlay(ypin);
if (! old) { this.markers.push(marker); }
break;
case 'google':
case 'openstreetmap':
var gpin = marker.toGoogle();
marker.setChild(gpin);
map.addOverlay(gpin);
if (! old) { this.markers.push(marker); }
break;
case 'microsoft':
var mpin = marker.toMicrosoft();
marker.setChild(mpin); // FIXME: MSFT maps remove the pin by pinID so this isn't needed?
map.AddPushpin(mpin);
if (! old) { this.markers.push(marker); }
break;
case 'openlayers':
//this.map.addPopup(new OpenLayers.Popup("chicken", new OpenLayers.LonLat(5,40), new OpenLayers.Size(200,200), "example popup"));
break;
case 'multimap':
var mmpin = marker.toMultiMap();
marker.setChild(mmpin);
map.addOverlay(mmpin);
if (! old) { this.markers.push(marker); }
break;
case 'map24':
var m24pin = marker.toMap24();
marker.setChild(m24pin);
m24pin.commit();
if (! old) { this.markers.push(marker); }
break;
case 'mapquest':
var mqpin = marker.toMapQuest();
marker.setChild(mqpin);
map.addPoi(mqpin);
if (! old) { this.markers.push(marker); }
break;
case 'freeearth':
var fepin = marker.toFreeEarth();
marker.setChild(fepin);
map.addOverlay(fepin);
if (! old) { this.markers.push(marker); }
break;
default:
if(this.debug)
alert(this.api + ' not supported by Mapstraction.addMarker');
}
}
/**
* addMarkerWithData will addData to the marker, then add it to the map
* @param{marker} marker The marker to add
* @param{data} data A data has to add
*/
Mapstraction.prototype.addMarkerWithData = function(marker,data) {
marker.addData(data);
this.addMarker(marker);
}
/**
* addPolylineWithData will addData to the polyline, then add it to the map
* @param{polyline} polyline The polyline to add
* @param{data} data A data has to add
*/
Mapstraction.prototype.addPolylineWithData = function(polyline,data) {
polyline.addData(data);
this.addPolyline(polyline);
}
/**
* removeMarker removes a Marker from the map
* @param {Marker} marker The marker to remove
*/
Mapstraction.prototype.removeMarker = function(marker) {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.removeMarker(marker); } );
return;
}
var map = this.maps[this.api];
var tmparray = new Array();
while(this.markers.length > 0){
current_marker = this.markers.pop();
if(marker == current_marker) {
switch (this.api) {
case 'google':
case 'openstreetmap':
map.removeOverlay(marker.proprietary_marker);
break;
case 'yahoo':
map.removeOverlay(marker.proprietary_marker);
break;
case 'microsoft':
map.DeletePushpin(marker.pinID);
break;
case 'multimap':
map.removeOverlay(marker.proprietary_marker);
break;
case 'mapquest':
map.removePoi(marker.proprietary_marker);
break;
case 'map24':
marker.proprietary_marker.remove();
break;
}
marker.onmap = false;
break;
} else {
tmparray.push(current_marker);
}
}
this.markers = this.markers.concat(tmparray);
}
/**
* removeAllMarkers removes all the Markers on a map
*/
Mapstraction.prototype.removeAllMarkers = function() {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.removeAllMarkers(); } );
return;
}
var map = this.maps[this.api];
switch (this.api) {
case 'yahoo':
map.removeMarkersAll();
break;
case 'google':
case 'openstreetmap':
map.clearOverlays();
break;
case 'microsoft':
map.DeleteAllPushpins();
break;
case 'multimap':
map.removeAllOverlays();
break;
case 'mapquest':
map.removeAllPois();
break;
case 'map24':
// don't think map24 has a specific method for this
var current_marker;
while(this.markers.length > 0) {
current_marker = this.markers.pop();
current_marker.proprietary_marker.remove();
}
break;
default:
if(this.debug)
alert(this.api + ' not supported by Mapstraction.removeAllMarkers');
}
this.markers = new Array(); // clear the mapstraction list of markers too
}
/**
* Add a polyline to the map
*/
Mapstraction.prototype.addPolyline = function(polyline,old) {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.addPolyline(polyline,old); } );
return;
}
var map = this.maps[this.api];
switch (this.api) {
case 'yahoo':
ypolyline = polyline.toYahoo();
polyline.setChild(ypolyline);
map.addOverlay(ypolyline);
if(!old) {this.polylines.push(polyline);}
break;
case 'google':
case 'openstreetmap':
gpolyline = polyline.toGoogle();
polyline.setChild(gpolyline);
map.addOverlay(gpolyline);
if(!old) {this.polylines.push(polyline);}
break;
case 'microsoft':
mpolyline = polyline.toMicrosoft();
polyline.setChild(mpolyline);
map.AddPolyline(mpolyline);
if(!old) {this.polylines.push(polyline);}
break;
case 'openlayers':
if(this.debug)
alert(this.api + ' not supported by Mapstraction.addPolyline');
break;
case 'multimap':
mmpolyline = polyline.toMultiMap();
polyline.setChild(mmpolyline);
map.addOverlay( mmpolyline );
if(!old) {this.polylines.push(polyline);}
break;
case 'mapquest':
mqpolyline = polyline.toMapQuest();
polyline.setChild(mqpolyline);
map.addOverlay( mqpolyline );
if(!old) {this.polylines.push(polyline);}
break;
case 'map24':
var m24polyline = polyline.toMap24();
polyline.setChild(m24polyline);
m24polyline.commit();
if(!old) {this.polylines.push(polyline);}
break;
default:
if(this.debug)
alert(this.api + ' not supported by Mapstraction.addPolyline');
}
}
/**
* Remove the polyline from the map
*/
Mapstraction.prototype.removePolyline = function(polyline) {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.removePolyline(polyline); } );
return;
}
var map = this.maps[this.api];
var tmparray = new Array();
while(this.polylines.length > 0){
current_polyline = this.polylines.pop();
if(polyline == current_polyline) {
switch (this.api) {
case 'google':
case 'openstreetmap':
map.removeOverlay(polyline.proprietary_polyline);
break;
case 'yahoo':
map.removeOverlay(polyline.proprietary_polyline);
break;
case 'microsoft':
map.DeletePolyline(polyline.pllID);
break;
case 'multimap':
polyline.proprietary_polyline.remove();
break;
case 'mapquest':
map.removeOverlay(polyline.proprietary_polyline);
break;
case 'map24':
polyline.proprietary_polyline.remove();
break;
}
polyline.onmap = false;
break;
} else {
tmparray.push(current_polyline);
}
}
this.polylines = this.polylines.concat(tmparray);
}
/**
* Removes all polylines from the map
*/
Mapstraction.prototype.removeAllPolylines = function() {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.removeAllPolylines(); } );
return;
}
var map = this.maps[this.api];
switch (this.api) {
case 'yahoo':
for(var i = 0, length = this.polylines.length;i < length;i++){
map.removeOverlay(this.polylines[i].proprietary_polyline);
}
break;
case 'google':
case 'openstreetmap':
for(var i = 0, length = this.polylines.length;i < length;i++){
map.removeOverlay(this.polylines[i].proprietary_polyline);
}
break;
case 'microsoft':
map.DeleteAllPolylines();
break;
case 'multimap':
for(var i = 0, length = this.polylines.length;i < length;i++){
this.polylines[i].proprietary_polyline.remove();
}
break;
case 'mapquest':
map.removeAllOverlays();
break;
case 'map24':
// don't think map24 has a specific method for this
var current_polyline;
while(this.polylines.length > 0) {
current_polyline = this.polylines.pop();
current_polyline.proprietary_polyline.remove();
}
break;
default:
if(this.debug)
alert(this.api + ' not supported by Mapstraction.removeAllPolylines');
}
this.polylines = new Array();
}
/**
* getCenter gets the central point of the map
* @returns  the center point of the map
* @type LatLonPoint
*/
Mapstraction.prototype.getCenter = function() {
if(this.loaded[this.api] == false) {
return null;
}
var map = this.maps[this.api];
var point = undefined;
switch (this.api) {
case 'yahoo':
var pt = map.getCenterLatLon();
point = new LatLonPoint(pt.Lat,pt.Lon);
break;
case 'google':
case 'openstreetmap':
var pt = map.getCenter();
point = new LatLonPoint(pt.lat(),pt.lng());
break;
case 'microsoft':
var pt = map.GetCenter();
point = new LatLonPoint(pt.Latitude,pt.Longitude);
break;
case 'multimap':
var pt = map.getCurrentPosition();
point = new LatLonPoint(pt.y, pt.x);
break;
case 'mapquest':
var pt = map.getCenter();
point = new LatLonPoint(pt.getLatitude(), pt.getLongitude());
break;
case 'map24':
var pt = map.MapClient['Static'].getCurrentMapView().getCenter();
point = new LatLonPoint(pt.Y/60,pt.X/60);
break;
default:
if(this.debug)
alert(this.api + ' not supported by Mapstraction.getCenter');
}
return point;
}
/**
* setCenter sets the central point of the map
* @param {LatLonPoint} point The point at which to center the map
*/
Mapstraction.prototype.setCenter = function(point) {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.setCenter(point); } );
return;
}
var map = this.maps[this.api];
switch (this.api) {
case 'yahoo':
map.panToLatLon(point.toYahoo());
break;
case 'google':
case 'openstreetmap':
map.setCenter(point.toGoogle());
break;
case 'microsoft':
map.SetCenter(point.toMicrosoft());
break;
case 'multimap':
map.goToPosition(point.toMultiMap());
break;
case 'mapquest':
map.setCenter(point.toMapQuest());
break;
case 'freeearth':
if (this.freeEarthLoaded) {
map.setTargetLatLng( point.toFreeEarth() );
} else {
self = this;
this.freeEarthOnLoad.push( function() { self.setCenterAndZoom(point); }
);
}
break;
case 'map24':
// Since center changes the zoom level to default
// we have to get the original metre width and pass it back in when
// centering.
var mv = map.MapClient['Static'].getCurrentMapView();
var newSettings = new Object();
newSettings.MinimumWidth = lonToMetres
(mv.LowerRight.Longitude - mv.TopLeft.Longitude,
(mv.LowerRight.Latitude+mv.TopLeft.Latitude)/2);
newSettings.Latitude =  point.lat*60;
newSettings.Longitude = point.lon*60;
Map24.MapApplication.center(newSettings);
break;
default:
if(this.debug)
alert(this.api + ' not supported by Mapstraction.setCenter');
}
}
/**
* setZoom sets the zoom level for the map
* MS doesn't seem to do zoom=0, and Gg's sat goes closer than it's maps, and MS's sat goes closer than Y!'s
* TODO: Mapstraction.prototype.getZoomLevels or something.
* @param {int} zoom The (native to the map) level zoom the map to.
*/
Mapstraction.prototype.setZoom = function(zoom) {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.setZoom(zoom); } );
return;
}
var map = this.maps[this.api];
switch (this.api) {
case 'yahoo':
var yzoom = 18 - zoom; // maybe?
map.setZoomLevel(yzoom);
break;
case 'google':
case 'openstreetmap':
map.setZoom(zoom);
break;
case 'microsoft':
map.SetZoomLevel(zoom);
break;
case 'multimap':
map.setZoomFactor(zoom);
break;
case 'mapquest':
map.setZoomLevel(zoom - 3); // MapQuest seems off by 3
break;
case 'map24':
// get the current centre than calculate the settings based on this
var point = this.getCenter();
var newSettings = new Object();
newSettings.Latitude = point.lat*60;
newSettings.Longitude = point.lon*60;
var client = map.MapClient['Static'];
var dLon = getDegreesFromGoogleZoomLevel
(client.getCanvasSize().Width,zoom);
newSettings.MinimumWidth = lonToMetres (dLon, point.lat);
Map24.MapApplication.center ( newSettings );
break;
default:
if(this.debug)
alert(this.api + ' not supported by Mapstraction.setZoom');
}
}
/**
* autoCenterAndZoom sets the center and zoom of the map to the smallest bounding box
*  containing all markers
*
*/
Mapstraction.prototype.autoCenterAndZoom = function() {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.autoCenterAndZoom(); } );
return;
}
var lat_max = -90;
var lat_min = 90;
var lon_max = -180;
var lon_min = 180;
for (var i=0; i<this.markers.length; i++) {
lat = this.markers[i].location.lat;
lon = this.markers[i].location.lon;
if (lat > lat_max) lat_max = lat;
if (lat < lat_min) lat_min = lat;
if (lon > lon_max) lon_max = lon;
if (lon < lon_min) lon_min = lon;
}
this.setBounds( new BoundingBox(lat_min, lon_min, lat_max, lon_max) );
}
/**
* centerAndZoomOnPoints sets the center and zoom of the map from an array of points
*
* This is useful if you don't want to have to add markers to the map
*/
Mapstraction.prototype.centerAndZoomOnPoints = function(points) {
var bounds = new BoundingBox(points[0].lat,points[0].lon,points[0].lat,points[0].lon);
for (var i=1, len = points.length ; i<len; i++) {
bounds.extend(points[i]);
}
this.setBounds(bounds);
}
/**
* getZoom returns the zoom level of the map
* @returns the zoom level of the map
* @type int
*/
Mapstraction.prototype.getZoom = function() {
if(this.loaded[this.api] == false) {
self = this;
return -1;
}
var map = this.maps[this.api];
switch (this.api) {
case 'yahoo':
return 18 - map.getZoomLevel(); // maybe?
case 'google':
case 'openstreetmap':
return map.getZoom();
case 'microsoft':
return map.GetZoomLevel();
case 'multimap':
return map.getZoomFactor();
case 'mapquest':
return map.getZoomLevel() + 3; // Mapquest seems off by 3?
case 'map24':
// since map24 doesn't use a Google-style set of zoom levels, we have
// to round to the nearest zoom
var mv = map.MapClient['Static'].getCurrentMapView();
var dLon = (mv.LowerRight.Longitude - mv.TopLeft.Longitude) / 60;
var width = map.MapClient['Static'].getCanvasSize().Width;
var zoom = getGoogleZoomLevelFromDegrees (width,dLon);
return Math.round(zoom);
default:
if(this.debug)
alert(this.api + ' not supported by Mapstraction.getZoom');
}
}
/**
* getZoomLevelForBoundingBox returns the best zoom level for bounds given
* @param boundingBox the bounds to fit
* @returns the closest zoom level that contains the bounding box
* @type int
*/
Mapstraction.prototype.getZoomLevelForBoundingBox = function( bbox ) {
if(this.loaded[this.api] == false) {
self = this;
return -1;
}
var map = this.maps[this.api];
// NE and SW points from the bounding box.
var ne = bbox.getNorthEast();
var sw = bbox.getSouthWest();
switch (this.api) {
case 'google':
case 'openstreetmap':
var gbox = new GLatLngBounds( sw.toGoogle(), ne.toGoogle() );
var zoom = map.getBoundsZoomLevel( gbox );
return zoom;
break;
case 'multimap':
var mmlocation = map.getBoundsZoomFactor( sw.toMultiMap(), ne.toMultiMap() );
var zoom = mmlocation.zoom_factor();
return zoom;
break;
case 'map24':
// since map24 doesn't use a Google-style set of zoom levels, we work
// out what zoom level will show the given longitude difference within
// the current map pixel width
var dLon = ne.lon - sw.lon;
var width = map.MapClient['Static'].getCanvasSize().Width;
var zoom = getGoogleZoomLevelFromDegrees (width,dLon);
return Math.round(zoom);
break;
default:
if(this.debug)
alert( this.api + ' not supported by Mapstraction.getZoomLevelForBoundingBox' );
}
}
// any use this being a bitmask? Should HYBRID = ROAD | SATELLITE?
Mapstraction.ROAD = 1;
Mapstraction.SATELLITE = 2;
Mapstraction.HYBRID = 3;
/**
* setMapType sets the imagery type for the map.
* The type can be one of:
* Mapstraction.ROAD
* Mapstraction.SATELLITE
* Mapstraction.HYBRID
* @param {int} type The (native to the map) level zoom the map to.
*/
Mapstraction.prototype.setMapType = function(type) {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.setMapType(type); } );
return;
}
var map = this.maps[this.api];
switch (this.api) {
case 'yahoo':
switch(type) {
case Mapstraction.ROAD:
map.setMapType(YAHOO_MAP_REG);
break;
case Mapstraction.SATELLITE:
map.setMapType(YAHOO_MAP_SAT);
break;
case Mapstraction.HYBRID:
map.setMapType(YAHOO_MAP_HYB);
break;
default:
map.setMapType(YAHOO_MAP_REG);
}
break;
case 'google':
case 'openstreetmap':
switch(type) {
case Mapstraction.ROAD:
map.setMapType(G_NORMAL_MAP);
break;
case Mapstraction.SATELLITE:
map.setMapType(G_SATELLITE_MAP);
break;
case Mapstraction.HYBRID:
map.setMapType(G_HYBRID_MAP);
break;
default:
map.setMapType(G_NORMAL_MAP);
}
break;
case 'microsoft':
// TODO: oblique?
switch(type) {
case Mapstraction.ROAD:
map.SetMapStyle(Msn.VE.MapStyle.Road);
break;
case Mapstraction.SATELLITE:
map.SetMapStyle(Msn.VE.MapStyle.Aerial);
break;
case Mapstraction.HYBRID:
map.SetMapStyle(Msn.VE.MapStyle.Hybrid);
break;
default:
map.SetMapStyle(Msn.VE.MapStyle.Road);
}
break;
case 'multimap':
maptypes = map.getAvailableMapTypes();
maptype = -1;
for (var i = 0; i < maptypes.length; i++) {
switch (maptypes[i]) {
case MM_WORLD_MAP:
if (type == Mapstraction.ROAD) {
maptype = maptypes[i];
}
default_type = maptypes[i];
break;
case MM_WORLD_AERIAL:
if (type == Mapstraction.SATELLITE) {
maptype = maptypes[i];
}
break;
case MM_WORLD_HYBRID:
if (type == Mapstraction.HYBRID) {
maptype = maptypes[i];
}
break;
}
}
if (maptype == -1) { maptype = default_type; }
map.setMapType(maptype);
break;
case 'mapquest':
switch (type) {
case Mapstraction.ROAD:
map.setMapType("map");
break;
case Mapstraction.SATELLITE:
map.setMapType("sat");
break;
case Mapstraction.HYBRID:
map.setMapType("hyb");
break;
}
break;
default:
if(this.debug)
alert(this.api + ' not supported by Mapstraction.setMapType');
}
}
/**
* getMapType gets the imagery type for the map.
* The type can be one of:
* Mapstraction.ROAD
* Mapstraction.SATELLITE
* Mapstraction.HYBRID
*/
Mapstraction.prototype.getMapType = function() {
if(this.loaded[this.api] == false) {
self = this;
return -1;
}
var map = this.maps[this.api];
var type;
switch (this.api) {
case 'yahoo':
type = map.getCurrentMapType();
switch(type) {
case YAHOO_MAP_REG:
return Mapstraction.ROAD;
break;
case YAHOO_MAP_SAT:
return Mapstraction.SATELLITE;
break;
case YAHOO_MAP_HYB:
return Mapstraction.HYBRID;
break;
default:
return null;
}
break;
case 'google':
case 'openstreetmap':
type = map.getCurrentMapType();
switch(type) {
case G_NORMAL_MAP:
return Mapstraction.ROAD;
break;
case G_SATELLITE_MAP:
return Mapstraction.SATELLITE;
break;
case G_HYBRID_MAP:
return Mapstraction.HYBRID;
break;
default:
return null;
}
break;
case 'microsoft':
// TODO: oblique?
type = map.GetMapStyle();
switch(type) {
case Msn.VE.MapStyle.Road:
return Mapstraction.ROAD;
break;
case Msn.VE.MapStyle.Aerial:
return Mapstraction.SATELLITE;
break;
case Msn.VE.MapStyle.Hybrid:
return Mapstraction.HYBRID;
break;
default:
return null;
}
break;
case 'multimap':
maptypes = map.getAvailableMapTypes();
type = map.getMapType();
switch(type) {
case MM_WORLD_MAP:
return Mapstraction.ROAD;
break;
case MM_WORLD_AERIAL:
return Mapstraction.SATELLITE;
break;
case MM_WORLD_HYBRID:
return Mapstraction.HYBRID;
break;
default:
return null;
}
break;
case 'mapquest':
type = map.getMapType();
switch(type) {
case "map":
return Mapstraction.ROAD;
break;
case "sat":
return Mapstraction.SATELLITE;
break;
case "hyb":
return Mapstraction.HYBRID;
break;
default:
return null;
}
break;
default:
if(this.debug)
alert(this.api + ' not supported by Mapstraction.getMapType');
}
}
/**
* getBounds gets the BoundingBox of the map
* @returns the bounding box for the current map state
* @type BoundingBox
*/
Mapstraction.prototype.getBounds = function () {
if(this.loaded[this.api] == false) {
return null;
}
var map = this.maps[this.api];
switch (this.api) {
case 'google':
case 'openstreetmap':
var gbox = map.getBounds();
var sw = gbox.getSouthWest();
var ne = gbox.getNorthEast();
return new BoundingBox(sw.lat(), sw.lng(), ne.lat(), ne.lng());
break;
case 'yahoo':
var ybox = map.getBoundsLatLon();
return new BoundingBox(ybox.LatMin, ybox.LonMin, ybox.LatMax, ybox.LonMax);
break;
case 'microsoft':
var mbox = map.GetMapView();
var nw = mbox.TopLeftLatLong;
var se = mbox.BottomRightLatLong;
return new BoundingBox(se.Latitude,nw.Longitude,nw.Latitude,se.Longitude);
break;
case 'multimap':
var mmbox = map.getMapBounds();
var sw = mmbox.getSouthWest();
var ne = mmbox.getNorthEast();
return new BoundingBox(sw.lat, sw.lon, ne.lat, ne.lon);
break;
case 'mapquest':
var mqbox = map.getMapBounds(); // MQRectLL
var se = mqbox.getLowerRightLatLng();
var nw = mqbox.getUpperLeftLatLng();
// NW is this correct ???
// return new BoundingBox(se.lat, se.lon, nw.lat, nw.lon);
// should be this instead
return new BoundingBox(se.lat, nw.lon, nw.lat, se.lon);
break;
case 'map24':
var mv = map.MapClient['Static'].getCurrentMapView();
var se = mv.LowerRight;
var nw = mv.TopLeft;
return new BoundingBox (se.Latitude/60, nw.Longitude/60,
nw.Latitude/60, se.Longitude/60 );
break;
default:
if(this.debug)
alert(this.api + ' not supported by Mapstraction.getBounds');
}
}
/**
* setBounds sets the map to the appropriate location and zoom for a given BoundingBox
* @param {BoundingBox} the bounding box you want the map to show
*/
Mapstraction.prototype.setBounds = function(bounds){
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.setBounds(bounds); } );
return;
}
var map = this.maps[this.api];
var sw = bounds.getSouthWest();
var ne = bounds.getNorthEast();
switch (this.api) {
case 'google':
case 'openstreetmap':
var gbounds = new GLatLngBounds(new GLatLng(sw.lat,sw.lon),new GLatLng(ne.lat,ne.lon));
map.setCenter(gbounds.getCenter(), map.getBoundsZoomLevel(gbounds));
break;
case 'yahoo':
if(sw.lon > ne.lon)
sw.lon -= 360;
var center = new YGeoPoint((sw.lat + ne.lat)/2,
(ne.lon + sw.lon)/2);
var container = map.getContainerSize();
for(var zoom = 1 ; zoom <= 17 ; zoom++){
var sw_pix = convertLatLonXY_Yahoo(sw,zoom);
var ne_pix = convertLatLonXY_Yahoo(ne,zoom);
if(sw_pix.x > ne_pix.x)
sw_pix.x -= (1 << (26 - zoom)); //earth circumference in pixel
if(Math.abs(ne_pix.x - sw_pix.x)<=container.width
&& Math.abs(ne_pix.y - sw_pix.y) <= container.height){
map.drawZoomAndCenter(center,zoom); //Call drawZoomAndCenter here: OK if called multiple times anyway
break;
}
}
break;
case 'microsoft':
map.SetMapView([new VELatLong(sw.lat,sw.lon),new VELatLong(ne.lat,ne.lon)]);
break;
case 'multimap':
var mmlocation = map.getBoundsZoomFactor( sw.toMultiMap(), ne.toMultiMap() );
var center = new LatLonPoint(mmlocation.coords.lat, mmlocation.coords.lon);
this.setCenterAndZoom(center, mmlocation.zoom_factor);
break;
case 'mapquest':
// TODO: MapQuest.setBounds
if(this.debug)
alert(this.api + ' not supported by Mapstraction.setBounds');
break;
case 'freeearth':
var center = new LatLonPoint((sw.lat + ne.lat)/2, (ne.lon + sw.lon)/2);
this.setCenter(center);
break;
case 'map24':
var settings = new Object();
settings.Latitude = ((sw.lat+ne.lat) / 2) * 60;
settings.Longitude = ((sw.lon+ne.lon) / 2) * 60;
// need to convert lat/lon to metres
settings.MinimumWidth = lonToMetres
(ne.lon-sw.lon, (ne.lat+sw.lat)/2);
Map24.MapApplication.center ( settings );
break;
default:
if(this.debug)
alert(this.api + ' not supported by Mapstraction.setBounds');
}
}
/**
* addImageOverlay layers an georeferenced image over the map
* @param {id} unique DOM identifier
* @param {src} url of image
* @param {opacity} opacity 0-100
* @param {west} west boundary
* @param {south} south boundary
* @param {east} east boundary
* @param {north} north boundary
*/
Mapstraction.prototype.addImageOverlay = function(id, src, opacity, west, south, east, north) {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.addImageOverlay(id, src, opacity, west, south, east, north); } );
return;
}
var map = this.maps[this.api];
var b = document.createElement("img");
b.style.display = 'block';
b.setAttribute('id',id);
b.setAttribute('src',src);
b.style.position = 'absolute';
b.style.zIndex = 1;
b.setAttribute('west',west);
b.setAttribute('south',south);
b.setAttribute('east',east);
b.setAttribute('north',north);
switch (this.api) {
case 'google':
case 'openstreetmap':
map.getPane(G_MAP_MAP_PANE).appendChild(b);
this.setImageOpacity(id, opacity);
this.setImagePosition(id);
GEvent.bind(map, "zoomend", this, function(){this.setImagePosition(id)});
GEvent.bind(map, "moveend", this, function(){this.setImagePosition(id)});
break;
case 'multimap':
map.getContainer().appendChild(b);
this.setImageOpacity(id, opacity);
this.setImagePosition(id);
me = this;
map.addEventHandler( 'changeZoom', function(eventType, eventTarget, arg1, arg2, arg3) {
me.setImagePosition(id);
});
map.addEventHandler( 'drag', function(eventType, eventTarget, arg1, arg2, arg3) {
me.setImagePosition(id);
});
map.addEventHandler( 'endPan', function(eventType, eventTarget, arg1, arg2, arg3) {
me.setImagePosition(id);
});
break;
default:
b.style.display = 'none';
if(this.debug)
alert(this.api + "not supported by Mapstraction.addImageOverlay not supported");
break;
}
}
Mapstraction.prototype.setImageOpacity = function(id, opacity) {
if(opacity<0){opacity=0;}  if(opacity>=100){opacity=100;}
var c=opacity/100;
var d=document.getElementById(id);
if(typeof(d.style.filter)=='string'){d.style.filter='alpha(opacity:'+opacity+')';}
if(typeof(d.style.KHTMLOpacity)=='string'){d.style.KHTMLOpacity=c;}
if(typeof(d.style.MozOpacity)=='string'){d.style.MozOpacity=c;}
if(typeof(d.style.opacity)=='string'){d.style.opacity=c;}
}
Mapstraction.prototype.setImagePosition = function(id) {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.setImagePosition(id); } );
return;
}
var map = this.maps[this.api];
var x = document.getElementById(id);
var d; var e;
switch (this.api) {
case 'google':
case 'openstreetmap':
d = map.fromLatLngToDivPixel(new GLatLng(x.getAttribute('north'), x.getAttribute('west')));
e = map.fromLatLngToDivPixel(new GLatLng(x.getAttribute('south'), x.getAttribute('east')));
break;
case 'multimap':
d = map.geoPosToContainerPixels(new MMLatLon(x.getAttribute('north'), x.getAttribute('west')));
e = map.geoPosToContainerPixels(new MMLatLon(x.getAttribute('south'), x.getAttribute('east')));
break;
}
x.style.top=d.y+'px';
x.style.left=d.x+'px';
x.style.width=e.x-d.x+'px';
x.style.height=e.y-d.y+'px';
}
/**
* addGeoRSSOverlay adds a GeoRSS overlay to the map
* @param{georssURL} GeoRSS feed URL
*/
Mapstraction.prototype.addGeoRSSOverlay = function(georssURL) {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.addGeoRSSOverlay(georssURL); } );
return;
}
var map = this.maps[this.api];
switch (this.api) {
case 'yahoo':
map.addOverlay(new YGeoRSS(georssURL));
break;
// case 'openstreetmap': // OSM uses the google interface, so allow cascade
case 'google':
map.addOverlay(new GGeoXml(georssURL));
break;
case 'microsoft':
var veLayerSpec = new VELayerSpecification();
veLayerSpec.Type = VELayerType.GeoRSS;
veLayerSpec.ID = 1;
veLayerSpec.LayerSource = georssURL;
veLayerSpec.Method = 'get';
// veLayerSpec.FnCallback = onFeedLoad;
map.AddLayer(veLayerSpec);
break;
// case 'openlayers':
// 	map.addLayer(new OpenLayers.Layer.GeoRSS("GeoRSS Layer", georssURL));
// break;
case 'multimap':
break;
case 'freeearth':
if (this.freeEarthLoaded) {
var ferss = new FE.GeoRSS(georssURL);
map.addOverlay(ferss);
} else {
self = this;
this.freeEarthOnLoad.push( function() { self.addGeoRSSOverlay(georssURL); } );
}
break;
default:
if(this.debug)
alert(this.api + ' not supported by Mapstraction.addGeoRSSOverlay');
}
}
/**
* addFilter adds a marker filter
* @param {field} name of attribute to filter on
* @param {operator} presently only "ge" or "le"
* @param {value} the value to compare against
*/
Mapstraction.prototype.addFilter = function(field, operator, value) {
if (! this.filters) {
this.filters = [];
}
this.filters.push( [field, operator, value] );
}
/**
* removeFilter
*/
Mapstraction.prototype.removeFilter = function(field, operator, value) {
if (! this.filters) { return; }
var del;
for (var f=0; f<this.filters.length; f++) {
if (this.filters[f][0] == field &&
(! operator || (this.filters[f][1] == operator && this.filters[f][2] == value))) {
this.filters.splice(f,1);
f--; //array size decreased
}
}
}
/*
* toggleFilter: delete the current filter if present; otherwise add it
*/
Mapstraction.prototype.toggleFilter = function(field, operator, value) {
if (! this.filters) {
this.filters = [];
}
var found = false;
for (var f=0; f<this.filters.length; f++) {
if (this.filters[f][0] == field && this.filters[f][1] == operator && this.filters[f][2] == value) {
this.filters.splice(f,1);
f--; //array size decreased
found = true;
}
}
if (! found) {
this.addFilter(field, operator, value);
}
}
/*
* removeAllFilters
*/
Mapstraction.prototype.removeAllFilters = function() {
this.filters = [];
}
/**
* doFilter executes all filters added since last call
*/
Mapstraction.prototype.doFilter = function() {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.doFilter(); } );
return;
}
var map = this.maps[this.api];
if (this.filters) {
switch (this.api) {
case 'multimap':
/* TODO polylines aren't filtered in multimap */
var mmfilters = [];
for (var f=0; f<this.filters.length; f++) {
mmfilters.push( new MMSearchFilter( this.filters[f][0], this.filters[f][1], this.filters[f][2] ));
}
map.setMarkerFilters( mmfilters );
map.redrawMap();
break;
default:
var vis;
for (var m=0; m<this.markers.length; m++) {
vis = true;
for (var f=0; f<this.filters.length; f++) {
if (! this.applyFilter(this.markers[m], this.filters[f])) {
vis = false;
}
}
if (vis) {
this.markers[m].show();
} else {
this.markers[m].hide();
}
}
/*
for (var p=0; m<this.polylines.length; p++) {
vis = true;
for (var f=0; f<this.filters.length; f++) {
if (! this.applyFilter(this.polylines[p], this.filters[f])) {
vis = false;
}
}
if (vis) {
this.polylines[p].show();
} else {
this.polylines[p].hide();
}
}
*/
break;
}
}
}
Mapstraction.prototype.applyFilter = function(o, f) {
var vis = true;
switch (f[1]) {
case 'ge':
if (o.getAttribute( f[0] ) < f[2]) {
vis = false;
}
break;
case 'le':
if (o.getAttribute( f[0] ) > f[2]) {
vis = false;
}
break;
case 'eq':
if (o.getAttribute( f[0] ) != f[2]) {
vis = false;
}
break;
}
return vis;
}
/**
* getAttributeExtremes returns the minimum/maximum of "field" from all markers
* @param {field} name of "field" to query
* @returns {array} of minimum/maximum
*/
Mapstraction.prototype.getAttributeExtremes = function(field) {
var min;
var max;
for (var m=0; m<this.markers.length; m++) {
if (! min || min > this.markers[m].getAttribute(field)) {
min = this.markers[m].getAttribute(field);
}
if (! max || max < this.markers[m].getAttribute(field)) {
max = this.markers[m].getAttribute(field);
}
}
for (var p=0; m<this.polylines.length; m++) {
if (! min || min > this.polylines[p].getAttribute(field)) {
min = this.polylines[p].getAttribute(field);
}
if (! max || max < this.polylines[p].getAttribute(field)) {
max = this.polylines[p].getAttribute(field);
}
}
return [min, max];
}
/**
* getMap returns the native map object that mapstraction is talking to
* @returns the native map object mapstraction is using
*/
Mapstraction.prototype.getMap = function() {
// FIXME in an ideal world this shouldn't exist right?
return this.maps[this.api];
}
//////////////////////////////
//
//   LatLonPoint
//
/////////////////////////////
/**
* LatLonPoint is a point containing a latitude and longitude with helper methods
* @param {double} lat is the latitude
* @param {double} lon is the longitude
* @returns a new LatLonPoint
* @type LatLonPoint
*/
function LatLonPoint(lat,lon) {
// TODO error if undefined?
//  if (lat == undefined) alert('undefined lat');
//  if (lon == undefined) alert('undefined lon');
this.lat = lat;
this.lon = lon;
this.lng = lon; // lets be lon/lng agnostic
}
/**
* toYahoo returns a Y! maps point
* @returns a YGeoPoint
*/
LatLonPoint.prototype.toYahoo = function() {
return new YGeoPoint(this.lat,this.lon);
}
/**
* toGoogle returns a Google maps point
* @returns a GLatLng
*/
LatLonPoint.prototype.toGoogle = function() {
return new GLatLng(this.lat,this.lon);
}
/**
* toMicrosoft returns a VE maps point
* @returns a VELatLong
*/
LatLonPoint.prototype.toMicrosoft = function() {
return new VELatLong(this.lat,this.lon);
}
/**
* toMultiMap returns a MultiMap point
* @returns a MMLatLon
*/
LatLonPoint.prototype.toMultiMap = function() {
return new MMLatLon(this.lat, this.lon);
}
/**
* toMapQuest returns a MapQuest point
* @returns a MQLatLng
*/
LatLonPoint.prototype.toMapQuest = function() {
return new MQLatLng(this.lat, this.lon);
}
/**
* toFreeEarth returns a FreeEarth point
* @returns a FE.LatLng
*/
LatLonPoint.prototype.toFreeEarth = function() {
return new FE.LatLng(this.lat,this.lon);
}
/**
* toMap24 returns a Map24 point
* @returns a Map24.Point
*/
LatLonPoint.prototype.toMap24 = function() {
return new Map24.Point (this.lon,this.lat);
}
/**
* toString returns a string represntation of a point
* @returns a string like '51.23, -0.123'
* @type String
*/
LatLonPoint.prototype.toString = function() {
return this.lat + ', ' + this.lon;
}
/**
* distance returns the distance in kilometers between two points
* @param {LatLonPoint} otherPoint The other point to measure the distance from to this one
* @returns the distance between the points in kilometers
* @type double
*/
LatLonPoint.prototype.distance = function(otherPoint) {
var d,dr;
with (Math) {
dr = 0.017453292519943295; // 2.0 * PI / 360.0; or, radians per degree
d = cos(otherPoint.lon*dr - this.lon*dr) * cos(otherPoint.lat*dr - this.lat*dr);
return acos(d)*6378.137; // equatorial radius
}
return -1;
}
/**
* equals tests if this point is the same as some other one
* @param {LatLonPoint} otherPoint The other point to test with
* @returns true or false
* @type boolean
*/
LatLonPoint.prototype.equals = function(otherPoint) {
return this.lat == otherPoint.lat && this.lon == otherPoint.lon;
}
//////////////////////////
//
//  BoundingBox
//
//////////////////////////
/**
* BoundingBox creates a new bounding box object
* @param {double} swlat the latitude of the south-west point
* @param {double} swlon the longitude of the south-west point
* @param {double} nelat the latitude of the north-east point
* @param {double} nelon the longitude of the north-east point
* @returns a new BoundingBox
* @type BoundingBox
* @constructor
*/
function BoundingBox(swlat, swlon, nelat, nelon) {
//FIXME throw error if box bigger than world
//alert('new bbox ' + swlat + ',' +  swlon + ',' +  nelat + ',' + nelon);
this.sw = new LatLonPoint(swlat, swlon);
this.ne = new LatLonPoint(nelat, nelon);
}
/**
* getSouthWest returns a LatLonPoint of the south-west point of the bounding box
* @returns the south-west point of the bounding box
* @type LatLonPoint
*/
BoundingBox.prototype.getSouthWest = function() {
return this.sw;
}
/**
* getNorthEast returns a LatLonPoint of the north-east point of the bounding box
* @returns the north-east point of the bounding box
* @type LatLonPoint
*/
BoundingBox.prototype.getNorthEast = function() {
return this.ne;
}
/**
* isEmpty finds if this bounding box has zero area
* @returns whether the north-east and south-west points of the bounding box are the same point
* @type boolean
*/
BoundingBox.prototype.isEmpty = function() {
return this.ne == this.sw; // is this right? FIXME
}
/**
* contains finds whether a given point is within a bounding box
* @param {LatLonPoint} point the point to test with
* @returns whether point is within this bounding box
* @type boolean
*/
BoundingBox.prototype.contains = function(point){
return point.lat >= this.sw.lat && point.lat <= this.ne.lat && point.lon>= this.sw.lon && point.lon <= this.ne.lon;
}
/**
* toSpan returns a LatLonPoint with the lat and lon as the height and width of the bounding box
* @returns a LatLonPoint containing the height and width of this bounding box
* @type LatLonPoint
*/
BoundingBox.prototype.toSpan = function() {
return new LatLonPoint( Math.abs(this.sw.lat - this.ne.lat), Math.abs(this.sw.lon - this.ne.lon) );
}
/**
* extend extends the bounding box to include the new point
*/
BoundingBox.prototype.extend = function(point) {
if(this.sw.lat > point.lat)
this.sw.setLat(point.lat);
if(this.sw.lon > point.lon)
this.sw.setLon(point.lon);
if(this.ne.lat < point.lat)
this.ne.setLat(point.lat);
if(this.ne.lon < point.lon)
this.ne.setLon(point.lon);
return;
}
//////////////////////////////
//
//  Marker
//
///////////////////////////////
/**
* Marker create's a new marker pin
* @param {LatLonPoint} point the point on the map where the marker should go
* @constructor
*/
function Marker(point) {
this.location = point;
this.onmap = false;
this.proprietary_marker = false;
this.attributes = new Array();
this.pinID = "mspin-"+new Date().getTime()+'-'+(Math.floor(Math.random()*Math.pow(2,16)));
}
Marker.prototype.setChild = function(some_proprietary_marker) {
this.proprietary_marker = some_proprietary_marker;
this.onmap = true
}
Marker.prototype.setLabel = function(labelText) {
this.labelText = labelText;
}
/**
* addData conviniently set a hash of options on a marker
*/
Marker.prototype.addData = function(options){
if(options.label)
this.setLabel(options.label);
if(options.infoBubble)
this.setInfoBubble(options.infoBubble);
if(options.icon) {
if(options.iconSize)
this.setIcon(options.icon, new Array(options.iconSize[0], options.iconSize[1]));
else
this.setIcon(options.icon);
}
if(options.infoDiv)
this.setInfoDiv(options.infoDiv[0],options.infoDiv[1]);
if(options.draggable)
this.setDraggable(options.draggable);
if(options.hover)
this.setHover(options.hover);
if(options.hoverIcon)
this.setHoverIcon(options.hoverIcon);
if(options.openBubble)
this.openBubble();
if(options.date)
this.setAttribute( 'date', eval(options.date) );
if(options.category)
this.setAttribute( 'category', options.category );
}
/**
* setInfoBubble sets the html/text content for a bubble popup for a marker
* @param {String} infoBubble the html/text you want displayed
*/
Marker.prototype.setInfoBubble = function(infoBubble) {
this.infoBubble = infoBubble;
}
/**
* setInfoDiv sets the text and the id of the div element where to the information
*  useful for putting information in a div outside of the map
* @param {String} infoDiv the html/text you want displayed
* @param {String} div the element id to use for displaying the text/html
*/
Marker.prototype.setInfoDiv = function(infoDiv,div){
this.infoDiv = infoDiv;
this.div = div;
}
/**
* setIcon sets the icon for a marker
* @param {String} iconUrl The URL of the image you want to be the icon
*/
Marker.prototype.setIcon = function(iconUrl, iconSize){
this.iconUrl = iconUrl;
if(iconSize)
this.iconSize = iconSize;
}
Marker.prototype.setHoverIcon = function(hoverIconUrl){
this.hoverIconUrl = hoverIconUrl;
}
/**
* setDraggable sets the draggable state of the marker
* @param {Bool} draggable set to true if marker should be draggable by the user
*/
Marker.prototype.setDraggable = function(draggable) {
this.draggable = draggable;
}
/**
* setHover sets that the marker info is displayed on hover
* @param {Bool} hover set to true if marker should display info on hover
*/
Marker.prototype.setHover = function(hover) {
this.hover = hover;
}
/**
* toYahoo returns a Yahoo Maps compatible marker pin
* @returns a Yahoo Maps compatible marker
*/
Marker.prototype.toYahoo = function() {
var ymarker;
if(this.iconUrl) {
ymarker = new YMarker(this.location.toYahoo (),new YImage(this.iconUrl));
} else {
ymarker = new YMarker(this.location.toYahoo());
}
if(this.iconSize) {
ymarker.size = new YSize(this.iconSize[0], this.iconSize[1]);
}
if(this.labelText) {
ymarker.addLabel(this.labelText);
}
if(this.infoBubble) {
var theInfo = this.infoBubble;
var event_action;
if(this.hover) {
event_action = EventsList.MouseOver;
}
else {
event_action = EventsList.MouseClick;
}
YEvent.Capture(ymarker, event_action, function() {
ymarker.openSmartWindow(theInfo); });
}
if(this.infoDiv) {
var theInfo = this.infoDiv;
var div = this.div;
var event_div;
if(this.hover) {
event_action = EventsList.MouseOver;
}
else {
event_action = EventsList.MouseClick;
}
YEvent.Capture(ymarker, event_action, function() {
document.getElementById(div).innerHTML = theInfo;});
}
return ymarker;
}
/**
* toGoogle returns a Google Maps compatible marker pin
* @returns Google Maps compatible marker
*/
Marker.prototype.toGoogle = function() {
var options = new Object();
if(this.labelText) {
options.title =  this.labelText;
}
if(this.iconUrl){
var icon = new GIcon(G_DEFAULT_ICON,this.iconUrl);
if(this.iconSize)
icon.iconSize = new GSize(this.iconSize[0], this.iconSize[1]);
options.icon = icon;
}
if(this.draggable){
options.draggable = this.draggable;
}
var gmarker = new GMarker( this.location.toGoogle(),options);
if(this.infoBubble) {
var theInfo = this.infoBubble;
var event_action;
if(this.hover) {
event_action = "mouseover";
}
else {
event_action = "click";
}
GEvent.addListener(gmarker, event_action, function() {
gmarker.openInfoWindowHtml(theInfo, {maxWidth: 100});
});
}
if(this.hoverIconUrl) {
GEvent.addListener(gmarker, "mouseover", function() {
gmarker.setImage(this.hoverIconUrl);
});
GEvent.addListener(gmarker, "mouseout", function() {
gmarker.setImage(this.iconUrl);
});
}
if(this.infoDiv){
var theInfo = this.infoDiv;
var div = this.div;
var event_action;
if(this.hover) {
event_action = "mouseover";
}
else {
event_action = "click";
}
GEvent.addListener(gmarker, event_action, function() {
document.getElementById(div).innerHTML = theInfo;
});
}
return gmarker;
}
/**
* toMicrosoft returns a MSFT VE compatible marker pin
* @returns MSFT VE compatible marker
*/
Marker.prototype.toMicrosoft = function() {
var pin = new VEPushpin(this.pinID,this.location.toMicrosoft(),
this.iconUrl,this.labelText,this.infoBubble);
return pin;
}
/**
* toMap24 returns a Map24 Location
* @returns Map24 Location
*/
Marker.prototype.toMap24 = function() {
var ops = new Object();
ops.Longitude = this.location.lon*60;
ops.Latitude = this.location.lat*60;
if(this.infoBubble) {
// not sure how map24 differentiates between tooltips and
// info bubble content
ops.TooltipContent =  this.infoBubble;
}
if(this.labelText) {
// ????
}
ops.LogoURL = this.iconUrl ? this.iconUrl :
"http://www.free-map.org.uk/images/marker.png";
ops.TooltipLayout = Map24.MapObject.LAYOUT_BUBBLE;
if(this.hover) {
ops.TooltipOpen = "OnMouseOver";
//        ops.TooltipClose = "OnMouseOut";
} else {
ops.TooltipOpen = "OnClick";
//        ops.TooltipClose = "OnMouseOut";
}
var m24Location = new Map24.Location ( ops );
return m24Location;
}
/**
* toMultiMap returns a MultiMap compatible marker pin
* @returns MultiMap compatible marker
*/
Marker.prototype.toMultiMap = function() {
if (this.iconUrl) {
var icon = new MMIcon(this.iconUrl);
icon.iconSize = new MMDimensions(32, 32); //how to get this?
var mmmarker = new MMMarkerOverlay( this.location.toMultiMap(), {'icon' : icon} );
} else {
var mmmarker = new MMMarkerOverlay( this.location.toMultiMap());
}
if(this.labelText){
}
if(this.infoBubble) {
mmmarker.setInfoBoxContent(this.infoBubble);
}
if(this.infoDiv) {
}
for (var key in this.attributes) {
mmmarker.setAttribute(key, this.attributes[ key ]);
}
return mmmarker;
}
/**
* toMapQuest returns a MapQuest compatible marker pin
* @returns MapQuest compatible marker
*/
Marker.prototype.toMapQuest = function() {
var mqmarker = new MQPoi( this.location.toMapQuest() );
if(this.iconUrl){
var mqicon = new MQMapIcon();
mqicon.setImage(this.iconUrl,32,32,true,false);
// TODO: Finish MapQuest icon params - icon file location, width, height, recalc infowindow offset, is it a PNG image?
mqmarker.setIcon(mqicon);
// mqmarker.setLabel('Hola!');
}
if(this.labelText) { mqmarker.setInfoTitleHTML( this.labelText ); }
if(this.infoBubble) { mqmarker.setInfoContentHTML( this.infoBubble ); }
if(this.infoDiv){
var theInfo = this.infoDiv;
var div = this.div;
MQEventManager.addListener(mqmarker, "click", function() {
document.getElementById(div).innerHTML = theInfo;
});
}
return mqmarker;
}
/**
* toFreeEarth returns a FreeEarth compatible marker pin
* @returns FreeEarth compatible marker
*/
Marker.prototype.toFreeEarth = function() {
var feicon;
if (this.iconUrl) {
feicon = new FE.Icon(this.iconUrl);
} else {
feicon = new FE.Icon("http://freeearth.poly9.com/images/bullmarker.png");
}
var femarker = new FE.Pushpin( this.location.toFreeEarth(), feicon);
if(this.infoBubble) {
var theBubble = this.infoBubble;
FE.Event.addListener(femarker, 'click', function() {
femarker.openInfoWindowHtml( theBubble, 200, 100 );
} );
}
if(this.infoDiv) {
var theInfo = this.infoDiv;
var div = this.div;
FE.Event.addListener(femarker, 'click', function() {
document.getElementById(div).innerHTML = theInfo;
});
}
return femarker;
}
/**
* setAttribute: set an arbitrary key/value pair on a marker
* @arg(String) key
* @arg value
*/
Marker.prototype.setAttribute = function(key,value) {
this.attributes[key] = value;
}
/**
* getAttribute: gets the value of "key"
* @arg(String) key
* @returns value
*/
Marker.prototype.getAttribute = function(key) {
return this.attributes[key];
}
/**
* openBubble opens the infoBubble
*/
Marker.prototype.openBubble = function() {
if( this.api) {
switch (this.api) {
case 'yahoo':
var ypin = this.proprietary_marker;
ypin.openSmartWindow(this.infoBubble);
break;
case 'google':
case 'openstreetmap':
var gpin = this.proprietary_marker;
gpin.openInfoWindowHtml(this.infoBubble);
break;
case 'microsoft':
var pin = this.proprietary_marker;
// bloody microsoft -- this is broken
var el = $m(this.pinID + "_" + this.maps[this.api].GUID).onmouseover;
setTimeout(el, 1000); // wait a second in case the map is booting as it cancels the event
break;
case 'multimap':
this.proprietary_marker.openInfoBox();
break;
case 'mapquest':
// MapQuest hack to work around bug when opening marker
this.proprietary_marker.setRolloverEnabled(false);
this.proprietary_marker.showInfoWindow();
this.proprietary_marker.setRolloverEnabled(true);
break;
}
} else {
alert('You need to add the marker before opening it');
}
}
/**
* hide the marker
*/
Marker.prototype.hide = function() {
if (this.api) {
switch (this.api) {
case 'google':
case 'openstreetmap':
this.proprietary_marker.hide();
break;
case 'yahoo':
this.proprietary_marker.hide();
break;
case 'map24':
this.proprietary_marker.hide();
break;
case 'multimap':
this.proprietary_marker.setVisibility(false);
break;
case 'mapquest':
this.proprietary_marker.setVisible(false);
break;
default:
if(this.debug)
alert(this.api + "not supported by Marker.hide");
}
}
}
/**
* show the marker
*/
Marker.prototype.show = function() {
if (this.api) {
switch (this.api) {
case 'google':
case 'openstreetmap':
this.proprietary_marker.show();
break;
case 'map24':
this.proprietary_marker.show();
break;
case 'yahoo':
this.proprietary_marker.unhide();
break;
case 'multimap':
this.proprietary_marker.setVisibility(true);
break;
case 'mapquest':
this.proprietary_marker.setVisible(true);
break;
default:
if(this.debug)
alert(this.api + "not supported by Marker.show");
}
}
}
///////////////
// Polyline ///
///////////////
function Polyline(points) {
this.points = points;
this.attributes = new Array();
this.onmap = false;
this.proprietary_polyline = false;
this.pllID = "mspll-"+new Date().getTime()+'-'+(Math.floor(Math.random()*Math.pow(2,16)));
}
/**
* addData conviniently set a hash of options on a polyline
*/
Polyline.prototype.addData = function(options){
if(options.color)
this.setColor(options.color);
if(options.width)
this.setWidth(options.width); // NW corrected from setInfoBubble()
if(options.opacity)
this.setIcon(options.opacity);
if(options.date)
this.setAttribute( 'date', eval(options.date) );
if(options.category)
this.setAttribute( 'category', options.category );
}
Polyline.prototype.setChild = function(some_proprietary_polyline) {
this.proprietary_polyline = some_proprietary_polyline;
this.onmap = true;
}
//in the form: #RRGGBB
//Note map24 insists on upper case, so we convert it.
Polyline.prototype.setColor = function(color){
this.color = (color.length==7 && color[0]=="#") ? color.toUpperCase() : color;
}
//An integer
Polyline.prototype.setWidth = function(width){
this.width = width;
}
//A float between 0.0 and 1.0
Polyline.prototype.setOpacity = function(opacity){
this.opacity = opacity;
}
Polyline.prototype.toYahoo = function() {
var ypolyline;
var ypoints = [];
for (var i = 0, length = this.points.length ; i< length; i++){
ypoints.push(this.points[i].toYahoo());
}
ypolyline = new YPolyline(ypoints,this.color,this.width,this.opacity);
return ypolyline;
}
Polyline.prototype.toGoogle = function() {
var gpolyline;
var gpoints = [];
for (var i = 0,  length = this.points.length ; i< length; i++){
gpoints.push(this.points[i].toGoogle());
}
gpolyline = new GPolyline(gpoints,this.color,this.width,this.opacity);
return gpolyline;
}
Polyline.prototype.toMap24 = function() {
var m24polyline;
var m24longs = "";
var m24lats = "";
for (var i=0; i<this.points.length; i++) {
if(i) {
m24longs += "|";
m24lats += "|";
}
m24longs += (this.points[i].lon*60);
m24lats += (this.points[i].lat*60);
}
m24polyline = new Map24.Polyline({
Longitudes: m24longs,
Latitudes: m24lats,
Color: this.color || "black",
Width: this.width || 3
});
return m24polyline;
}
Polyline.prototype.toMicrosoft = function() {
var mpolyline;
var mpoints = [];
for (var i = 0, length = this.points.length ; i< length; i++){
mpoints.push(this.points[i].toMicrosoft());
}
var color;
var opacity = this.opacity ||1.0;
if(this.color){
color = new VEColor(parseInt(this.color.substr(1,2),16),parseInt(this.color.substr(3,2),16),parseInt(this.color.substr(5,2),16), opacity);
}else{
color = new VEColor(0,255,0, opacity);
}
mpolyline = new VEPolyline(this.pllID,mpoints,color,this.width);
return mpolyline;
}
Polyline.prototype.toMultiMap = function() {
var mmpolyline;
var mmpoints = [];
for (var i = 0, length = this.points.length ; i< length; i++){
mmpoints.push(this.points[i].toMultiMap());
}
mmpolyline = new MMPolyLineOverlay(mmpoints, this.color, this.opacity, this.width, false, undefined);
return mmpolyline;
}
Polyline.prototype.toMapQuest = function() {
var mqpolyline = new MQLineOverlay();
mqpolyline.setColor(this.color||"red");
mqpolyline.setBorderWidth(this.width || 3);
mqpolyline.setKey("Line");
mqpolyline.setColorAlpha(this.opacity);
var mqpoints = new MQLatLngCollection();
for (var i = 0, length = this.points.length ; i< length; i++){
mqpoints.add(this.points[i].toMapQuest());
}
mqpolyline.setShapePoints(mqpoints);
return mqpolyline;
}
Polyline.prototype.toFreeEarth = function() {
var fepoints = new Array();
for (var i = 0, length = this.points.length ; i< length; i++){
fepoints.push(this.points[i].toFreeEarth());
}
var fepolyline = new FE.Polyline(fepoints, this.color || '0xff0000', this.width || 1, this.opacity || 1);
return fepolyline;
}
/**
* setAttribute: set an arbitrary key/value pair on a polyline
* @arg(String) key
* @arg value
*/
Polyline.prototype.setAttribute = function(key,value) {
this.attributes[key] = value;
}
/**
* getAttribute: gets the value of "key"
* @arg(String) key
* @returns value
*/
Polyline.prototype.getAttribute = function(key) {
return this.attributes[key];
}
/**
* show: not yet implemented
*/
Polyline.prototype.show = function() {
if (this.api) {
}
}
/**
* hide: not yet implemented
*/
Polyline.prototype.hide = function() {
if (this.api) {
}
}
/////////////
/// Route ///
/////////////
/**
* Show a route from MapstractionRouter on a mapstraction map
* Currently only supported by MapQuest
* @params {Object} route The route object returned in the callback from MapstractionRouter
*/
Mapstraction.prototype.showRoute = function(route) {
if(this.loaded[this.api] == false) {
self = this;
this.onload[this.api].push( function() { self.showRoute(route); } );
return;
}
var map = this.maps[this.api];
switch (this.api) {
case 'mapquest':
map.addRouteHighlight(route['bounding_box'],"http://map.access.mapquest.com",route['session_id'],true);
break;
default:
if(this.debug)
alert(api + ' not supported by Mapstration.showRoute');
break;
}
}
/**
* This class is used for the slideshow functionnalities
*
* @author Patrick Jordan <patrick.jordan@pyrameed.com>
* @author Yves-André Giroud <yves-andre.giroud@pyrameed.com>
* @copyright Copyright 2007 Pyrameed
*
* @event Event start This event is fired when the slideshow start
* @event Event stop This event is fired when the slideshow stops
* @event Event pagechange This event is fired when the page is changed
* @event Event imagechange This event is fired when the image is changed
*
*
* @param Element[] pages The pages of the slideshow
* @param Element[] images The images (contained in the pages) of the slideshow
* @param Element imageViewer The image viewer of the slideshow
* @param Element commentViewer The comment viewer of the slideshow
* @optionalparam Element floating The floating element to show selected image
*/
var Slideshow = Events.extend({
/**
* This is the initialization function
*/
initialize : function(pages, images, imageViewer, commentViewer, floating) {
this._pages = pages;
this._images = images;
this._viewer = imageViewer;
this._viewerImage = $E('img', this._viewer);
this._comment = commentViewer;
// The event listener are added
if (this._viewerImage && typeof(this._viewerImage.addEvent) == 'function') {
this._viewerImage.addEvent('load', this.centerViewerImage.bind(this));
}
if (this._viewerImage.complete) {
this.centerViewerImage();
}
images.each(function(el) {
el.imageJS = new Image();
el.imageJS.onload = function(e) {
this._resizeThumbnailImage(el);
}.bind(this);
if (el.imageJS.complete) {
this._resizeThumbnailImage(el);
}
el.imageJS.src = $E('img', el).getProperty('src');
el.addEvent('click', function(e) {
this.selectImage(el);
this.stop();
}.bind(this));
}.bind(this));
// The pages container is adjusted
if (this._pages && this._pages.length) {
this._pages[0].getParent().setStyle('width', (this._pages.length * (this._pages[0].getCoordinates().width) + 20) + 'px');
this._scroll = new Fx.Scroll(this._pages[0].getParent().getParent(), {
onStart : function(e) {
this._isScrolling = true;
}.bind(this),
onComplete : function(e) {
this._isScrolling = false;
}.bind(this)
});
}
this._currentImage = 0;
this._currentPage = 0;
this._floating = floating ? new Fx.Styles(floating, {duration: 500, wait: false}) : null;
this._isScrolling = false;
/*
this.selectImage(this._images[0]);
this.selectPage(this._pages[0]);
*/
},
/**
* Resize all the thumbnail images
*/
resizeThumbnails : function() {
this._images.each(function(el) {
this._resizeThumbnailImage(el);
}.bind(this));
if (this._pages[0].getParent().getStyle('width') == '20px') {
this._pages[0].getParent().setStyle('width', (this._pages.length * (this._pages[0].getCoordinates().width) + 20) + 'px');
}
},
/**
* This function select an image from the slideshow
*
* @param Element oNode The image node
*/
selectImage : function(oNode) {
//currentImage = $$('div.Synergee-Web-Page-Component-SlideShow-Slide').indexOf(oNode);
if (oNode) {
if (this._floating) {
var top = oNode.getTop() - oNode.getParent().getParent().getParent().getTop();
var left = oNode.getLeft() - oNode.getParent().getParent().getParent().getLeft();
this._floating.start({
'top': top + 'px',
'left':left + 'px'
});
}
this._currentImage = this._images.indexOf(oNode);
//this._displayImage.delay(500, this, oNode);
this._displayImage(oNode);
this.fireEvent('imagechange');
}
},
/**
* This function display the image inside the viewer
*
* @param Element oNode The image node
*/
_displayImage : function(oNode) {
var thumbnailImage = $E('img', oNode);
// A fade in/fade out effect is added
var myFx = new Fx.Style(this._viewerImage, 'opacity', {duration:250});
myFx.start(1, 0).chain(function() {
this._viewerImage.setProperty('src', thumbnailImage.getProperty('src'));
this._viewerImage.setProperty('alt', thumbnailImage.getProperty('alt'));
this._comment.setHTML(thumbnailImage.getProperty('alt'));
myFx.start(0, 1);
}.bind(this));
},
/**
* Select the next image in the slideshow
*/
selectNextImage : function() {
if (this.hasNextImage() && !this._isScrolling) {
var next = this._images[++this._currentImage];
if (this._currentImage % this._pages[0].getChildren().length == 0) {
this.nextPage(null, next);
} else {
this.selectImage(next);
}
} else if (!this._isScrolling) {
this.selectPage(this._pages[0]);
this.selectImage(this._images[0]);
this.fireEvent('pagechange');
this.fireEvent('imagechange');
}
},
/**
* Select the previous image in the slideshow
*/
selectPreviousImage : function() {
if (this.hasPreviousImage() && !this._isScrolling) {
var previous = this._images[--this._currentImage];
if (this._currentImage % this._pages[0].getChildren().length == this._pages[0].getChildren().length - 1) {
this.previousPage(null, previous);
} else {
this.selectImage(previous);
}
} else if (!this._isScrolling) {
this.selectPage(this._pages[this._pages.length - 1]);
this.selectImage(this._images[this._images.length - 1]);
this.fireEvent('pagechange');
this.fireEvent('imagechange');
}
},
/**
* Return if there is previous image
*
* @return Boolean
*/
hasPreviousImage : function() {
return this._currentImage > 0;
},
/**
* Return if there is next image
*
* @return Boolean
*/
hasNextImage : function() {
return this._currentImage < this._images.length - 1;
},
/**
* This function center the viewer image
*/
centerViewerImage : function() {
this._viewerImage.setStyle('margin-top', (this._viewer.getCoordinates().height - this._viewerImage.getCoordinates().height) / 2 + 'px');
this._viewerImage.setStyle('margin-bottom', (this._viewer.getCoordinates().height - this._viewerImage.getCoordinates().height) / 2 + 'px');
this._viewerImage.setStyle('margin-left', (this._viewer.getCoordinates().width - this._viewerImage.getCoordinates().width) / 2 + 'px');
this._viewerImage.setStyle('margin-right', (this._viewer.getCoordinates().width - this._viewerImage.getCoordinates().width) / 2 + 'px');
},
/**
* This function resize and crop the thumbnail images
*
* @param Element e the element that contains the image
*/
_resizeThumbnailImage : function(e) {
var slideImage = $E('img', e);
var slide = slideImage.getParent();
// The slides have to be rectangular
var containerWidth = slide.getCoordinates().width;
var containerHeight = slide.getCoordinates().height;
var containerRatio = containerWidth / containerHeight;
var imageWidth = slideImage.width;
var imageHeight = slideImage.height;
var imageRatio = imageWidth / imageHeight;
if (containerWidth > 0) {
if (imageHeight > imageWidth) {
slideImage.setStyle('width', containerWidth);
slideImage.setStyle('height', Math.round(containerWidth / imageRatio));
slideImage.setStyle('top', Math.round((containerHeight - Math.round(containerWidth / imageRatio)) / 2));
} else {
slideImage.setStyle('width', Math.round(containerWidth * imageRatio));
slideImage.setStyle('height', containerHeight);
slideImage.setStyle('left', Math.round((containerWidth - Math.round(containerWidth * imageRatio)) / 2));
}
}
},
/**
* This function select a given page
*
* @param Element page The page to select
*/
selectPage : function(page) {
if (page) {
this._scroll.scrollTo(page.getLeft() - (this._pages[0]).getLeft(), 0);
this.fireEvent('pagechange');
this._currentPage = this._pages.indexOf(page);
}
},
/**
* This function go to the previous page
*/
previousPage : function(e, oNode) {
if (this.hasPreviousPage() && !this._isScrolling) {
this._scroll.scrollTo((this._pages[--this._currentPage]).getLeft() - (this._pages[0]).getLeft(), 0);
this.fireEvent('pagechange');
this.selectImage(oNode || this._pages[this._currentPage].getFirst().getFirst());
}
},
/**
* This function go to the next page
*/
nextPage : function(e, oNode) {
if (this.hasNextPage() && !this._isScrolling) {
this._scroll.scrollTo((this._pages[++this._currentPage]).getLeft() - (this._pages[0]).getLeft(), 0);
this.fireEvent('pagechange');
this.selectImage(oNode || this._pages[this._currentPage].getFirst().getFirst());
}
},
/**
* Return if there is previous page
*
* @return Boolean
*/
hasPreviousPage : function() {
return this._currentPage > 0;
},
/**
* Return if there is next page
*
* @return Boolean
*/
hasNextPage : function() {
return this._currentPage < this._pages.length - 1;
},
/**
* Start to play the slideshow
*/
play : function(e) {
if (!this._timeoutID) {
this._timeoutID = this.selectNextImage.periodical(3000, this);
this.fireEvent('start');
}
},
/**
* Stop to play the slideshow
*/
stop : function(e) {
if (this._timeoutID)
this._timeoutID = $clear(this._timeoutID);
this.fireEvent('stop');
},
/**
* Refresh the slideshow (viewer)
*/
refresh : function() {
this.centerViewerImage();
this.resizeThumbnails();
}
});

