//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;
/**
* 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() {
var currentPageUrl = window.location.href;
if(currentPageUrl.indexOf('#') != -1){
currentPageUrl = currentPageUrl.slice(0, currentPageUrl.indexOf('#'));
}
if (currentPageUrl.indexOf('?') != -1) {
return currentPageUrl.substr(0, currentPageUrl.indexOf('?'));
}
return currentPageUrl;
},
/**
* 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 (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 the week number
*/
Date.prototype.getWeek = function() {
var onejan = new Date(this.getFullYear(),0,1);
return Math.ceil((((this - onejan) / 86400000) + onejan.getDay())/7);
};
/**
* 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(/^([\w-\._\+%]+@(?:[\w-]+\.)+[\w]{2,6})?$/),
/**
* 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() == 'div' || 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.removeClass('WaitingButton');
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.getParent().getElementsByTagName('div')[0].addClass('Synergee-Web-Page-Form-FieldErrorMessage-Container');
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.getParent().addClass('InvalidField')
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.getParent().removeClass('InvalidField')
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);
}
});
/**
*  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.getStyle('opacity') != 0) {
this._waitingFxStyle.start(0.5, 0);
this._waitingImageFxStyle.start(1, 0);
}
}
});
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);
}
});
window.addEvent('domready', function () {
var searchForm = $('Home-SchoolSearch');
var searchPanelToggle = $('Home-SchoolSearchAdvancedToggle');
var searchPanel = $('Home-SchoolSearchAdvancedPanel');
var closedLabelNode;
var openLabelNode;
function ensureToggleLabelNodes(closedLabel, openLabel) {
closedLabelNode = searchPanelToggle.getElement('.mas-school-search-compact__toggle-label--closed');
openLabelNode = searchPanelToggle.getElement('.mas-school-search-compact__toggle-label--open');
if (closedLabelNode && openLabelNode) {
return;
}
searchPanelToggle.empty();
closedLabelNode = new Element('span', {
'class': 'mas-school-search-compact__toggle-label mas-school-search-compact__toggle-label--closed'
});
closedLabelNode.appendText(closedLabel);
openLabelNode = new Element('span', {
'class': 'mas-school-search-compact__toggle-label mas-school-search-compact__toggle-label--open'
});
openLabelNode.appendText(openLabel);
closedLabelNode.inject(searchPanelToggle);
openLabelNode.inject(searchPanelToggle);
}
function setToggleLabel(label) {
searchPanelToggle.setProperty('aria-label', label);
searchPanelToggle.setProperty('title', label);
}
if (!searchForm || !searchPanelToggle || !searchPanel || searchPanelToggle.getProperty('data-mas-panel-bound') == 'true') {
return;
}
var closedLabel = searchPanelToggle.getProperty('data-label-closed') || '+ de choix';
var openLabel = searchPanelToggle.getProperty('data-label-open') || 'Moins de choix';
searchPanelToggle.setProperty('data-mas-panel-bound', 'true');
ensureToggleLabelNodes(closedLabel, openLabel);
setToggleLabel(closedLabel);
searchPanelToggle.setProperty('aria-expanded', 'false');
searchPanel.setProperty('aria-hidden', 'true');
searchPanel.setProperty('hidden', 'hidden');
searchPanel.removeClass('is-open');
searchForm.removeClass('is-advanced-open');
searchPanelToggle.addEvent('click', function () {
var searchPanelOpen = !searchPanel.hasClass('is-open');
setToggleLabel(searchPanelOpen ? openLabel : closedLabel);
searchPanelToggle.setProperty('aria-expanded', searchPanelOpen ? 'true' : 'false');
searchPanel.setProperty('aria-hidden', searchPanelOpen ? 'false' : 'true');
if (searchPanelOpen) {
searchPanel.removeProperty('hidden');
searchPanel.addClass('is-open');
searchForm.addClass('is-advanced-open');
} else {
searchPanel.removeClass('is-open');
searchPanel.setProperty('hidden', 'hidden');
searchForm.removeClass('is-advanced-open');
}
});
});
window.addEvent('domready', function () {
if (!document.body || !document.body.classList.contains('MoveAndStudyCore-home')) {
return;
}
function normalizeDestinationLabel(rawLabel) {
var label = (rawLabel || '')
.replace(/\u00a0/g, ' ')
.replace(/\s+/g, ' ')
.trim();
label = label.replace(/^s[ée]jour linguistique\s+/i, '');
label = label.replace(/^s[ée]jour\s+/i, '');
label = label.replace(/^ados?\s+/i, '');
label = label.replace(/^(?:en|au|aux|a|à)\s+/i, '');
return label.trim();
}
function updateDestinationTitle(titleElement) {
var heading = titleElement.querySelector('h1, h2, h3, h4, p');
var link = titleElement.querySelector('a');
var rawLabel = (link && link.textContent) || (heading && heading.textContent) || titleElement.textContent;
var cleanLabel = normalizeDestinationLabel(rawLabel);
if (!cleanLabel) {
return;
}
if (link && heading && link.parentNode === heading) {
link.textContent = cleanLabel;
} else if (link && heading && heading.parentNode === link) {
heading.textContent = cleanLabel;
} else if (link) {
link.textContent = cleanLabel;
} else if (heading) {
heading.textContent = cleanLabel;
} else {
titleElement.textContent = cleanLabel;
}
titleElement.setAttribute('data-mas-destination-clean', 'true');
titleElement.setAttribute('data-mas-destination-label', cleanLabel);
}
Array.prototype.forEach.call(document.querySelectorAll('.mas-destinations .mas-destination-card__title'), function (titleElement) {
if (titleElement.getAttribute('data-mas-destination-clean') === 'true') {
return;
}
updateDestinationTitle(titleElement);
});
});
(function () {
var defaultProfile = "young";
function onReady(callback) {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", callback);
return;
}
callback();
}
onReady(function () {
var stage = document.querySelector("[data-mas-home-hero-stage]");
var source = document.querySelector("[data-mas-home-hero-source]");
var image = document.querySelector("[data-mas-home-hero-image]");
var cards = Array.prototype.slice.call(document.querySelectorAll("[data-mas-home-profile-card]"));
var activeProfile = defaultProfile;
var lockedProfile = defaultProfile;
var hasUserLock = false;
var isRuntimeReady = document.readyState === "complete";
var supportsWebp = false;
var hasScheduledWarmup = false;
if (!stage || !source || !image || !cards.length) {
return;
}
supportsWebp = /\.webp(?:$|\?)/i.test(image.currentSrc || "");
function getCardAsset(card) {
var webp = card.getAttribute("data-mas-home-hero-webp");
var fallback = card.getAttribute("data-mas-home-hero-fallback");
return supportsWebp && webp ? webp : fallback;
}
function findCard(profile) {
return cards.filter(function (card) {
return card.getAttribute("data-mas-home-profile") === profile;
})[0] || null;
}
function updateCardState(profile) {
cards.forEach(function (card) {
var cardProfile = card.getAttribute("data-mas-home-profile");
card.classList.toggle("is-active", cardProfile === profile);
card.classList.toggle("is-locked", cardProfile === lockedProfile);
card.setAttribute("aria-pressed", cardProfile === lockedProfile ? "true" : "false");
});
}
function updateImage(card) {
var webp = card.getAttribute("data-mas-home-hero-webp");
var fallback = card.getAttribute("data-mas-home-hero-fallback");
var currentSrc = image.currentSrc || image.getAttribute("src") || "";
if (!isRuntimeReady) {
return;
}
if (!webp || !fallback || currentSrc.indexOf(webp) !== -1 || currentSrc.indexOf(fallback) !== -1) {
return;
}
stage.classList.add("is-switching");
window.requestAnimationFrame(function () {
source.setAttribute("srcset", webp);
image.setAttribute("src", fallback);
image.setAttribute("srcset", fallback + " 1672w");
stage.setAttribute("data-mas-home-hero-active", card.getAttribute("data-mas-home-profile"));
window.requestAnimationFrame(function () {
stage.classList.remove("is-switching");
});
});
}
function setProfile(profile) {
var card = findCard(profile);
if (!card) {
return;
}
activeProfile = profile;
updateCardState(profile);
updateImage(card);
}
function warmupSecondaryImages() {
cards.forEach(function (card) {
var asset = getCardAsset(card);
if (!asset || asset === image.currentSrc || asset === image.getAttribute("src")) {
return;
}
new Image().src = asset;
});
}
function scheduleWarmup() {
if (hasScheduledWarmup) {
return;
}
hasScheduledWarmup = true;
if (window.requestIdleCallback) {
window.requestIdleCallback(warmupSecondaryImages, { timeout: 1800 });
return;
}
window.setTimeout(warmupSecondaryImages, 240);
}
cards.forEach(function (card) {
var profile = card.getAttribute("data-mas-home-profile");
card.addEventListener("click", function (event) {
if (event.target && event.target.closest && event.target.closest(".mas-home-main-card-arrow")) {
return;
}
event.preventDefault();
lockedProfile = profile;
hasUserLock = true;
setProfile(profile);
stage.setAttribute("data-mas-home-hero-locked", lockedProfile);
});
card.addEventListener("keydown", function (event) {
if (event.key !== " " && event.key !== "Spacebar") {
return;
}
event.preventDefault();
card.click();
});
});
lockedProfile = defaultProfile;
stage.setAttribute("data-mas-home-hero-locked", lockedProfile);
setProfile(activeProfile);
if (!isRuntimeReady) {
window.addEventListener("load", function () {
isRuntimeReady = true;
supportsWebp = /\.webp(?:$|\?)/i.test(image.currentSrc || "") || supportsWebp;
setProfile(activeProfile);
scheduleWarmup();
}, { once: true });
return;
}
scheduleWarmup();
});
}());
(function () {
function onReady(callback) {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", callback);
return;
}
callback();
}
function closest(element, selector) {
while (element && element.nodeType === 1) {
if (element.matches && element.matches(selector)) {
return element;
}
element = element.parentNode;
}
return null;
}
function bindMegaMenu(menu) {
var mobileToggle = menu.querySelector(".mas-mega-menu__toggle");
var items = Array.prototype.slice.call(menu.querySelectorAll("[data-mas-mega-item]"));
var triggers = Array.prototype.slice.call(menu.querySelectorAll("[data-mas-mega-trigger]"));
var languageButtons = Array.prototype.slice.call(menu.querySelectorAll("[data-mas-menu-lang]"));
var countryCards = Array.prototype.slice.call(menu.querySelectorAll("[data-mas-country-langs]"));
var closeTimer = null;
function setItemOpen(item, isOpen) {
var trigger = item.querySelector("[data-mas-mega-trigger]");
var panel = item.querySelector("[data-mas-mega-panel]");
if (!trigger || !panel) {
return;
}
item.classList.toggle("is-open", isOpen);
trigger.setAttribute("aria-expanded", isOpen ? "true" : "false");
panel.hidden = !isOpen;
}
function closeAll(exceptItem) {
items.forEach(function (item) {
if (item !== exceptItem) {
setItemOpen(item, false);
}
});
}
function openItem(item) {
window.clearTimeout(closeTimer);
closeAll(item);
setItemOpen(item, true);
}
function closeSoon(item) {
window.clearTimeout(closeTimer);
closeTimer = window.setTimeout(function () {
setItemOpen(item, false);
}, 140);
}
if (mobileToggle) {
mobileToggle.addEventListener("click", function () {
var isOpen = menu.classList.toggle("is-mobile-open");
mobileToggle.setAttribute("aria-expanded", isOpen ? "true" : "false");
if (!isOpen) {
closeAll();
}
});
}
triggers.forEach(function (trigger) {
trigger.addEventListener("click", function () {
var item = closest(trigger, "[data-mas-mega-item]");
var isOpen = item && item.classList.contains("is-open");
closeAll(item);
if (item) {
setItemOpen(item, !isOpen);
}
});
trigger.addEventListener("keydown", function (event) {
if (event.key === "Escape") {
closeAll();
trigger.focus();
}
});
});
items.forEach(function (item) {
item.addEventListener("mouseenter", function () {
if (window.matchMedia("(min-width: 901px)").matches) {
openItem(item);
}
});
item.addEventListener("mouseleave", function () {
if (window.matchMedia("(min-width: 901px)").matches) {
closeSoon(item);
}
});
item.addEventListener("focusin", function () {
openItem(item);
});
item.addEventListener("focusout", function (event) {
if (!item.contains(event.relatedTarget)) {
closeSoon(item);
}
});
});
document.addEventListener("click", function (event) {
if (!menu.contains(event.target)) {
closeAll();
menu.classList.remove("is-mobile-open");
if (mobileToggle) {
mobileToggle.setAttribute("aria-expanded", "false");
}
}
});
document.addEventListener("keydown", function (event) {
if (event.key === "Escape") {
closeAll();
menu.classList.remove("is-mobile-open");
if (mobileToggle) {
mobileToggle.setAttribute("aria-expanded", "false");
mobileToggle.focus();
}
}
});
languageButtons.forEach(function (button) {
button.addEventListener("click", function () {
var language = button.getAttribute("data-mas-menu-lang");
languageButtons.forEach(function (item) {
item.classList.toggle("is-active", item === button);
});
countryCards.forEach(function (card) {
var languages = card.getAttribute("data-mas-country-langs") || "";
var shouldShow = language === "all" || languages.split(" ").indexOf(language) !== -1;
card.classList.toggle("is-hidden", !shouldShow);
});
});
});
}
onReady(function () {
Array.prototype.slice.call(document.querySelectorAll("[data-mas-mega-menu]")).forEach(bindMegaMenu);
});
}());
(function () {
"use strict";
function toArray(nodeList) {
return Array.prototype.slice.call(nodeList || []);
}
function toggleHidden(element, shouldHide) {
if (!element) {
return;
}
if (shouldHide) {
element.setAttribute("hidden", "hidden");
} else {
element.removeAttribute("hidden");
}
}
function pluralize(count, singular, plural) {
return count + " " + (count > 1 ? plural : singular);
}
function buildMetaText(visibleCount, totalCount) {
if (totalCount <= 0) {
return "Aucune école disponible pour cette formule.";
}
if (visibleCount >= totalCount) {
return pluralize(totalCount, "école disponible", "écoles disponibles") + " pour cette formule.";
}
return "Aperçu de " + pluralize(visibleCount, "école", "écoles") + " sur " + totalCount + " disponibles pour cette formule.";
}
function initCourseTypeDirectory() {
var body = document.body;
if (!body || body.className.indexOf("MoveAndStudyCore-course-type") === -1) {
return;
}
var directory = document.querySelector("[data-course-type-directory]");
var explorer = document.querySelector("[data-course-type-explorer]");
if (!directory || !explorer) {
return;
}
var pageSize = parseInt(directory.getAttribute("data-page-size"), 10) || 4;
var countryCarousel = explorer.querySelector("[data-course-type-country-carousel]");
var countryPageSize = countryCarousel ? parseInt(countryCarousel.getAttribute("data-country-page-size"), 10) || 4 : 4;
var state = {
language: directory.getAttribute("data-initial-language") || "",
country: directory.getAttribute("data-initial-country") || "",
schoolPageIndex: 0,
countryPageIndex: 0
};
var meta = directory.querySelector("[data-course-type-meta]");
var nextButton = directory.querySelector("[data-course-type-next]");
var previousButton = directory.querySelector("[data-course-type-prev]");
var pagination = directory.querySelector("[data-course-type-pagination]");
var track = directory.querySelector("[data-course-type-track]");
var fallbackList = directory.querySelector("[data-course-type-directory-list]");
var countryTrack = countryCarousel ? countryCarousel.querySelector("[data-course-type-country-track]") : null;
var countryFallbackList = countryCarousel ? countryCarousel.querySelector("[data-course-type-country-list]") : null;
var countryNextButton = countryCarousel ? countryCarousel.querySelector("[data-course-type-country-next]") : null;
var countryPreviousButton = countryCarousel ? countryCarousel.querySelector("[data-course-type-country-prev]") : null;
var countryPagination = countryCarousel ? countryCarousel.querySelector("[data-course-type-country-pagination]") : null;
var schoolCards = toArray(directory.querySelectorAll("[data-course-type-school-card]"));
var languageButtons = toArray(explorer.querySelectorAll("[data-course-type-language]"));
var countryButtons = toArray(explorer.querySelectorAll(".mas-course-type-country-toolbar [data-course-type-country]"));
var countryCards = toArray(explorer.querySelectorAll("[data-course-type-country-card]"));
var renderedSchoolKey = "";
var renderedSchoolPages = [];
var renderedSchoolCards = [];
var renderedCountryKey = "";
var renderedCountryPages = [];
var renderedCountryCards = [];
if (!track || !fallbackList || !countryTrack || !countryFallbackList) {
return;
}
directory.classList.add("is-enhanced");
countryCarousel.classList.add("is-enhanced");
function getLanguageCode(element) {
return element.getAttribute("data-language-code") || "";
}
function getCountryCode(element) {
return element.getAttribute("data-country-code") || "";
}
function getMatchingSchoolCards() {
return schoolCards.filter(function (card) {
var cardLanguage = getLanguageCode(card);
var cardCountry = getCountryCode(card);
if (state.language && cardLanguage !== state.language) {
return false;
}
if (state.country && cardCountry !== state.country) {
return false;
}
return true;
});
}
function getCurrentStateKey() {
return [state.language, state.country].join("|");
}
function getCountryStateKey() {
return state.language || "";
}
function clearTrack(element) {
while (element.firstChild) {
element.removeChild(element.firstChild);
}
}
function clearElement(element) {
while (element && element.firstChild) {
element.removeChild(element.firstChild);
}
}
function createPage(cards, pageClass, gridClass) {
var page = document.createElement("section");
var list = document.createElement("ul");
page.className = pageClass;
list.className = gridClass;
cards.forEach(function (card) {
toggleHidden(card, false);
list.appendChild(card);
});
page.appendChild(list);
return page;
}
function buildSchoolPages(matchingCards) {
var index;
var pageCards;
var page;
clearTrack(track);
renderedSchoolPages = [];
renderedSchoolCards = matchingCards.slice();
schoolCards.forEach(function (card) {
toggleHidden(card, true);
});
for (index = 0; index < matchingCards.length; index += pageSize) {
pageCards = matchingCards.slice(index, index + pageSize);
page = createPage(pageCards, "mas-course-type-directory__page", "mas-course-type-directory__page-grid");
page.setAttribute("data-course-type-page", "");
renderedSchoolPages.push(page);
track.appendChild(page);
}
renderedSchoolKey = getCurrentStateKey();
}
function getMatchingCountryCards() {
return countryCards.filter(function (card) {
var cardLanguage = getLanguageCode(card);
if (state.language && cardLanguage !== state.language) {
return false;
}
return true;
});
}
function buildCountryPages(matchingCards) {
var index;
var pageCards;
var page;
clearTrack(countryTrack);
renderedCountryPages = [];
renderedCountryCards = matchingCards.slice();
countryCards.forEach(function (card) {
toggleHidden(card, true);
});
for (index = 0; index < matchingCards.length; index += countryPageSize) {
pageCards = matchingCards.slice(index, index + countryPageSize);
page = createPage(pageCards, "mas-course-type-country-carousel__page", "mas-course-type-country-carousel__page-grid");
page.setAttribute("data-course-type-country-page", "");
renderedCountryPages.push(page);
countryTrack.appendChild(page);
}
renderedCountryKey = getCountryStateKey();
}
function buildPagination(container, pageCount, activeIndex, labelPrefix, onSelect) {
var index;
var button;
var isActive;
if (!container) {
return;
}
clearElement(container);
if (pageCount <= 1) {
toggleHidden(container, true);
return;
}
for (index = 0; index < pageCount; index += 1) {
isActive = index === activeIndex;
button = document.createElement("button");
button.type = "button";
button.className = "mas-course-type-slider-pagination__dot" + (isActive ? " is-active" : "");
button.setAttribute("aria-label", labelPrefix + " " + (index + 1));
button.setAttribute("aria-pressed", isActive ? "true" : "false");
if (isActive) {
button.setAttribute("aria-current", "true");
}
button.title = labelPrefix + " " + (index + 1);
button.addEventListener("click", (function (targetIndex) {
return function () {
onSelect(targetIndex);
};
}(index)));
container.appendChild(button);
}
toggleHidden(container, false);
}
function updateSchoolPager() {
var pageCount = renderedSchoolPages.length;
var visibleCount = 0;
var isLastPage;
var isFirstPage;
if (pageCount && state.schoolPageIndex >= pageCount) {
state.schoolPageIndex = pageCount - 1;
}
isLastPage = !pageCount || state.schoolPageIndex >= pageCount - 1;
isFirstPage = state.schoolPageIndex <= 0;
renderedSchoolPages.forEach(function (page, index) {
page.classList.toggle("is-active", index === state.schoolPageIndex);
});
if (pageCount) {
visibleCount = Math.max(0, Math.min(pageSize, renderedSchoolCards.length - (state.schoolPageIndex * pageSize)));
}
track.style.transform = pageCount ? "translate3d(-" + (state.schoolPageIndex * 100) + "%, 0, 0)" : "";
if (meta) {
meta.textContent = buildMetaText(visibleCount, renderedSchoolCards.length);
}
if (nextButton) {
toggleHidden(nextButton, pageCount <= 1 || isLastPage);
}
if (previousButton) {
toggleHidden(previousButton, pageCount <= 1 || isFirstPage);
}
buildPagination(pagination, pageCount, state.schoolPageIndex, "Slide écoles", function (targetIndex) {
state.schoolPageIndex = targetIndex;
updateSchoolPager();
});
}
function updateCountryPager() {
var pageCount = renderedCountryPages.length;
var isLastPage;
var isFirstPage;
if (pageCount && state.countryPageIndex >= pageCount) {
state.countryPageIndex = pageCount - 1;
}
isLastPage = !pageCount || state.countryPageIndex >= pageCount - 1;
isFirstPage = state.countryPageIndex <= 0;
renderedCountryPages.forEach(function (page, index) {
page.classList.toggle("is-active", index === state.countryPageIndex);
});
countryTrack.style.transform = pageCount ? "translate3d(-" + (state.countryPageIndex * 100) + "%, 0, 0)" : "";
if (countryNextButton) {
toggleHidden(countryNextButton, pageCount <= 1 || isLastPage);
}
if (countryPreviousButton) {
toggleHidden(countryPreviousButton, pageCount <= 1 || isFirstPage);
}
buildPagination(countryPagination, pageCount, state.countryPageIndex, "Slide pays", function (targetIndex) {
state.countryPageIndex = targetIndex;
updateCountryPager();
});
}
function updateLanguageButtons() {
languageButtons.forEach(function (button) {
var isActive = (button.getAttribute("data-course-type-language") || "") === state.language;
button.classList.toggle("is-active", isActive);
button.setAttribute("aria-pressed", isActive ? "true" : "false");
});
}
function updateCountryControls() {
countryButtons.forEach(function (button) {
var buttonLanguage = getLanguageCode(button);
var isVisible = !state.language || buttonLanguage === state.language;
var isActive = isVisible && (button.getAttribute("data-course-type-country") || "") === state.country;
toggleHidden(button, !isVisible);
button.classList.toggle("is-active", isActive);
button.setAttribute("aria-pressed", isActive ? "true" : "false");
});
countryCards.forEach(function (card) {
var cardCountry = getCountryCode(card);
var cardButton = card.querySelector("[data-course-type-country]");
var isActive = cardCountry === state.country;
card.classList.toggle("is-active", isActive);
if (cardButton) {
cardButton.setAttribute("aria-pressed", isActive ? "true" : "false");
}
});
}
function updateSchoolCards() {
var matchingCards = getMatchingSchoolCards();
if (renderedSchoolKey !== getCurrentStateKey()) {
buildSchoolPages(matchingCards);
}
updateSchoolPager();
}
function updateCountryCards() {
var matchingCards = getMatchingCountryCards();
if (renderedCountryKey !== getCountryStateKey()) {
buildCountryPages(matchingCards);
}
updateCountryPager();
}
function update() {
updateLanguageButtons();
updateCountryControls();
updateCountryCards();
updateSchoolCards();
}
languageButtons.forEach(function (button) {
button.addEventListener("click", function () {
state.language = button.getAttribute("data-course-type-language") || "";
state.country = "";
state.schoolPageIndex = 0;
state.countryPageIndex = 0;
update();
});
});
countryButtons.forEach(function (button) {
button.addEventListener("click", function () {
state.language = getLanguageCode(button) || state.language;
state.country = button.getAttribute("data-course-type-country") || "";
state.schoolPageIndex = 0;
update();
});
});
countryCards.forEach(function (card) {
var button = card.querySelector("[data-course-type-country]");
if (!button) {
return;
}
button.addEventListener("click", function () {
state.language = getLanguageCode(card) || state.language;
state.country = getCountryCode(card);
state.schoolPageIndex = 0;
update();
});
});
if (countryNextButton) {
countryNextButton.addEventListener("click", function () {
state.countryPageIndex += 1;
updateCountryPager();
});
}
if (countryPreviousButton) {
countryPreviousButton.addEventListener("click", function () {
state.countryPageIndex = Math.max(0, state.countryPageIndex - 1);
updateCountryPager();
});
}
if (nextButton) {
nextButton.addEventListener("click", function () {
state.schoolPageIndex += 1;
updateSchoolPager();
});
}
if (previousButton) {
previousButton.addEventListener("click", function () {
state.schoolPageIndex = Math.max(0, state.schoolPageIndex - 1);
updateSchoolPager();
});
}
update();
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", initCourseTypeDirectory);
} else {
initCourseTypeDirectory();
}
})();
(function () {
function onReady(callback) {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", callback);
return;
}
callback();
}
function bindFavouriteSchools(root) {
var images = Array.prototype.slice.call(root.querySelectorAll("[data-mas-favourite-slide]"));
var slides = Array.prototype.slice.call(root.querySelectorAll("[data-mas-favourite-info]"));
var dots = Array.prototype.slice.call(root.querySelectorAll("[data-mas-favourite-dot]"));
var previous = root.querySelector("[data-mas-favourite-prev]");
var next = root.querySelector("[data-mas-favourite-next]");
var current = 0;
var timer = null;
function setActive(index) {
if (!slides.length) {
return;
}
current = (index + slides.length) % slides.length;
images.forEach(function (image, imageIndex) {
image.classList.toggle("is-active", imageIndex === current);
});
slides.forEach(function (slide, slideIndex) {
slide.classList.toggle("is-active", slideIndex === current);
});
dots.forEach(function (dot, dotIndex) {
dot.classList.toggle("is-active", dotIndex === current);
});
}
function stop() {
window.clearInterval(timer);
timer = null;
}
function start() {
if (slides.length < 2 || timer) {
return;
}
timer = window.setInterval(function () {
setActive(current + 1);
}, 4500);
}
if (previous) {
previous.addEventListener("click", function () {
setActive(current - 1);
stop();
});
}
if (next) {
next.addEventListener("click", function () {
setActive(current + 1);
stop();
});
}
dots.forEach(function (dot) {
dot.addEventListener("click", function () {
setActive(parseInt(dot.getAttribute("data-mas-favourite-dot"), 10) || 0);
stop();
});
});
root.addEventListener("mouseenter", stop);
root.addEventListener("mouseleave", start);
setActive(0);
start();
}
onReady(function () {
Array.prototype.slice.call(document.querySelectorAll("[data-mas-favourite-schools]")).forEach(bindFavouriteSchools);
});
}());
(function () {
var apiBase = "/synergee/MoveAndStudyCountryExchange.php";
var cacheLifetime = 6 * 60 * 60 * 1000;
var supportedTargets = ["EUR", "USD", "GBP", "CHF", "CAD", "AUD", "NZD", "JPY"];
function onReady(callback) {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", callback);
return;
}
callback();
}
function getCurrencyFromText(text) {
var normalized = (text || "").toLowerCase();
var currencies = [
{code: "AUD", pattern: /dollar australien|aud/},
{code: "CAD", pattern: /dollar canadien|cad/},
{code: "USD", pattern: /dollar americain|dollar américain|usd/},
{code: "NZD", pattern: /dollar neo zelandais|dollar néo zélandais|nzd/},
{code: "GBP", pattern: /livre sterling|gbp/},
{code: "JPY", pattern: /yen|jpy/},
{code: "KRW", pattern: /won|krw/},
{code: "MXN", pattern: /peso mexicain|mxn/},
{code: "ARS", pattern: /peso argentin|ars/},
{code: "ZAR", pattern: /rand|zar/},
{code: "EUR", pattern: /euro|eur/},
{code: "CHF", pattern: /franc suisse|chf/}
];
var index;
for (index = 0; index < currencies.length; index += 1) {
if (currencies[index].pattern.test(normalized)) {
return currencies[index].code;
}
}
return "";
}
function normalizeCurrency(value) {
var currency = (value || "").toUpperCase().replace(/[^A-Z]/g, "");
return /^[A-Z]{3}$/.test(currency) ? currency : "";
}
function isSupportedTarget(value) {
return supportedTargets.indexOf(normalizeCurrency(value)) !== -1;
}
function getStoredCurrency() {
var keys = [
"SynergeeCurrency",
"synergee.currency",
"currency",
"masCurrency",
"booking.currency"
];
var index;
var value;
try {
for (index = 0; index < keys.length; index += 1) {
value = normalizeCurrency(window.localStorage && window.localStorage.getItem(keys[index]));
if (isSupportedTarget(value)) {
return value;
}
}
for (index = 0; index < keys.length; index += 1) {
value = normalizeCurrency(window.sessionStorage && window.sessionStorage.getItem(keys[index]));
if (isSupportedTarget(value)) {
return value;
}
}
} catch (error) {
return "";
}
return "";
}
function getDomCurrency(card) {
var selector = [
"select[name='currency']",
"input[name='currency']",
"[data-visitor-currency]",
"[data-website-currency]",
"[data-currency]"
].join(",");
var nodes = Array.prototype.slice.call(document.querySelectorAll(selector));
var index;
var node;
var value;
for (index = 0; index < nodes.length; index += 1) {
node = nodes[index];
if (card && card.contains(node)) {
continue;
}
value = normalizeCurrency(node.value || node.getAttribute("data-visitor-currency") || node.getAttribute("data-website-currency") || node.getAttribute("data-currency"));
if (isSupportedTarget(value)) {
return value;
}
}
return "";
}
function getLocaleCurrency() {
var locale = (navigator.language || (navigator.languages && navigator.languages[0]) || "").toLowerCase();
if (!locale) {
return "";
}
if (/-(us|pr|gu|as|vi)$/.test(locale)) {
return "USD";
}
if (/-(gb|gg|im|je)$/.test(locale)) {
return "GBP";
}
if (/-ch$/.test(locale)) {
return "CHF";
}
if (/-ca$/.test(locale)) {
return "CAD";
}
if (/-au$/.test(locale)) {
return "AUD";
}
if (/-nz$/.test(locale)) {
return "NZD";
}
if (/-jp$/.test(locale)) {
return "JPY";
}
if (/^(fr|de|es|it|nl|pt|fi|sv|da|el|ga|et|lv|lt|mt|sk|sl|hr)(-|$)/.test(locale)) {
return "EUR";
}
return "";
}
function getTargetCurrency(card, sourceCurrency) {
var fallback = normalizeCurrency(card.getAttribute("data-fallback-currency")) || "EUR";
var candidates = [
normalizeCurrency(card.getAttribute("data-target-currency")),
getStoredCurrency(),
getDomCurrency(card),
getLocaleCurrency(),
fallback
];
var index;
var currency;
for (index = 0; index < candidates.length; index += 1) {
currency = normalizeCurrency(candidates[index]);
if (isSupportedTarget(currency) && currency != sourceCurrency) {
return currency;
}
}
return sourceCurrency == "EUR" ? "USD" : "EUR";
}
function formatDate(dateValue) {
try {
return new Intl.DateTimeFormat("fr-FR", {
day: "2-digit",
month: "2-digit",
year: "numeric"
}).format(new Date(dateValue + "T12:00:00Z"));
} catch (error) {
return dateValue;
}
}
function formatRate(value, currency) {
try {
return new Intl.NumberFormat("fr-FR", {
style: "currency",
currency: currency,
maximumFractionDigits: 4
}).format(value);
} catch (error) {
return Math.round(value * 10000) / 10000 + " " + currency;
}
}
function formatRoundedAmount(value, currency) {
try {
return new Intl.NumberFormat("fr-FR", {
style: "currency",
currency: currency,
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(value);
} catch (error) {
return Math.round(value * 100) / 100 + " " + currency;
}
}
function formatUpdated(dateValue) {
var consultedAt = "";
try {
consultedAt = new Intl.DateTimeFormat("fr-FR", {
hour: "2-digit",
minute: "2-digit"
}).format(new Date());
} catch (error) {
consultedAt = "";
}
return "Dernière mise à jour : " + formatDate(dateValue) + (consultedAt ? " · consulté à " + consultedAt : "");
}
function isoDate(date) {
return date.toISOString().slice(0, 10);
}
function getCachedJson(cacheKey) {
var stored;
var parsed;
try {
stored = window.sessionStorage && window.sessionStorage.getItem(cacheKey);
if (!stored) {
return null;
}
parsed = JSON.parse(stored);
if (!parsed || !parsed.createdAt || (Date.now() - parsed.createdAt) > cacheLifetime) {
window.sessionStorage.removeItem(cacheKey);
return null;
}
return parsed.payload || null;
} catch (error) {
return null;
}
}
function setCachedJson(cacheKey, payload) {
try {
if (window.sessionStorage) {
window.sessionStorage.setItem(cacheKey, JSON.stringify({
createdAt: Date.now(),
payload: payload
}));
}
} catch (error) {
return;
}
}
function fetchJson(url, cacheKey) {
var cached = getCachedJson(cacheKey);
var controller;
var timeoutId;
var fetchOptions = {};
if (cached) {
return Promise.resolve(cached);
}
if (window.AbortController) {
controller = new window.AbortController();
fetchOptions.signal = controller.signal;
timeoutId = window.setTimeout(function () {
controller.abort();
}, 10000);
}
return window.fetch(url, fetchOptions)
.then(function (response) {
if (timeoutId) {
window.clearTimeout(timeoutId);
}
if (!response.ok) {
throw new Error("Exchange rate unavailable");
}
return response.json();
})
.then(function (data) {
setCachedJson(cacheKey, data);
return data;
})
.catch(function (error) {
if (timeoutId) {
window.clearTimeout(timeoutId);
}
throw error;
});
}
function getLatestRate(data, targetCurrency) {
var latest;
if (Array.isArray(data)) {
latest = data.filter(function (item) {
return item && item.quote == targetCurrency && typeof item.rate !== "undefined";
}).pop();
return latest ? parseFloat(latest.rate) : NaN;
}
if (data && typeof data.rate !== "undefined") {
return parseFloat(data.rate);
}
if (data && data.rates && typeof data.rates[targetCurrency] !== "undefined") {
return parseFloat(data.rates[targetCurrency]);
}
return NaN;
}
function getLatestDate(data) {
if (Array.isArray(data) && data.length && data[data.length - 1].date) {
return data[data.length - 1].date;
}
return data && data.date ? data.date : isoDate(new Date());
}
function getDateFromIso(value) {
var parts = String(value || "").split("-");
if (parts.length != 3) {
return new Date();
}
return new Date(parseInt(parts[0], 10), parseInt(parts[1], 10) - 1, parseInt(parts[2], 10));
}
function normalizeSeries(data, targetCurrency) {
var rows = [];
if (Array.isArray(data)) {
data.forEach(function (item) {
if (item && item.quote == targetCurrency && typeof item.rate !== "undefined") {
rows.push({
date: item.date,
rate: parseFloat(item.rate)
});
}
});
return rows;
}
Object.keys((data && data.rates) || {}).sort().forEach(function (date) {
if (data.rates[date] && typeof data.rates[date][targetCurrency] !== "undefined") {
rows.push({
date: date,
rate: parseFloat(data.rates[date][targetCurrency])
});
}
});
return rows;
}
function renderChart(polyline, series) {
var values = series.map(function (item) {
return item.rate;
}).filter(function (value) {
return !isNaN(value);
});
var min;
var max;
var range;
var width;
var height;
var points;
if (!values.length) {
return;
}
min = Math.min.apply(Math, values);
max = Math.max.apply(Math, values);
range = max - min || 1;
width = 180;
height = 44;
points = values.map(function (value, index) {
var x = values.length == 1 ? width : (index / (values.length - 1)) * width;
var y = height - ((value - min) / range) * (height - 6) - 3;
return Math.round(x * 10) / 10 + "," + Math.round(y * 10) / 10;
});
polyline.setAttribute("points", points.join(" "));
}
function setUnavailable(exchange, pair, rate, updated, sourceCurrency, targetCurrency) {
applyExchangeDisplay(null, exchange, pair, sourceCurrency, targetCurrency, "forward");
if (rate) {
rate.textContent = "Taux de change momentanément indisponible";
}
if (updated) {
updated.textContent = "La monnaie reste indiquée ci-contre.";
}
if (exchange) {
exchange.classList.add("is-unavailable");
exchange.classList.remove("is-ready");
}
}
function applyExchangeDisplay(card, exchange, pair, fromCurrency, toCurrency, direction) {
var resolvedDirection = direction == "reverse" ? "reverse" : "forward";
if (pair && fromCurrency) {
pair.textContent = fromCurrency + " \u2192 " + toCurrency;
}
if (card) {
card.setAttribute("data-mas-exchange-from-currency", fromCurrency || "");
card.setAttribute("data-mas-exchange-to-currency", toCurrency || "");
card.setAttribute("data-mas-exchange-direction", resolvedDirection);
}
if (exchange) {
exchange.setAttribute("data-mas-exchange-from-currency", fromCurrency || "");
exchange.setAttribute("data-mas-exchange-to-currency", toCurrency || "");
exchange.setAttribute("data-mas-exchange-direction", resolvedDirection);
}
}
function getDirectionalState(sourceCurrency, targetCurrency, latestRate, direction) {
var normalizedDirection = direction == "reverse" ? "reverse" : "forward";
var resolvedRate = parseFloat(latestRate);
if (isNaN(resolvedRate) || !isFinite(resolvedRate) || resolvedRate <= 0) {
return null;
}
if (normalizedDirection == "reverse") {
return {
direction: normalizedDirection,
fromCurrency: targetCurrency,
toCurrency: sourceCurrency,
rate: 1 / resolvedRate,
operator: "\u2248"
};
}
return {
direction: normalizedDirection,
fromCurrency: sourceCurrency,
toCurrency: targetCurrency,
rate: resolvedRate,
operator: "="
};
}
function renderExchangeState(card, exchange, pair, rate, updated, toggle, sourceCurrency, targetCurrency, latestRate, latestDate, direction) {
var state = getDirectionalState(sourceCurrency, targetCurrency, latestRate, direction);
if (!state) {
setUnavailable(exchange, pair, rate, updated, sourceCurrency, targetCurrency);
if (toggle) {
toggle.hidden = true;
toggle.disabled = true;
toggle.setAttribute("aria-pressed", "false");
}
return false;
}
applyExchangeDisplay(card, exchange, pair, state.fromCurrency, state.toCurrency, state.direction);
if (rate) {
rate.textContent = "1 " + state.fromCurrency + " " + state.operator + " " + formatRate(state.rate, state.toCurrency);
}
if (updated) {
updated.textContent = "100 " + state.fromCurrency + " \u2248 " + formatRoundedAmount(state.rate * 100, state.toCurrency) + " \u00b7 mis \u00e0 jour le " + formatDate(latestDate);
}
if (toggle) {
toggle.hidden = false;
toggle.disabled = false;
toggle.setAttribute("aria-pressed", state.direction == "reverse" ? "true" : "false");
}
if (exchange) {
exchange.classList.add("is-ready");
exchange.classList.remove("is-unavailable");
}
return true;
}
function getExchangeState(card) {
return card && card._masExchangeState ? card._masExchangeState : null;
}
function syncExchangeCard(card) {
var state = getExchangeState(card);
if (!state) {
return false;
}
return renderExchangeState(
card,
state.exchange,
state.pair,
state.rate,
state.updated,
state.toggle,
state.sourceCurrency,
state.targetCurrency,
state.latestRateValue,
state.latestDateValue,
state.currentDirection
);
}
function toggleExchangeCard(card) {
var state = getExchangeState(card);
if (!state || isNaN(state.latestRateValue) || !isFinite(state.latestRateValue) || state.latestRateValue <= 0) {
return false;
}
state.currentDirection = state.currentDirection == "forward" ? "reverse" : "forward";
return syncExchangeCard(card);
}
function getClosestExchangeNode(node, attributeName) {
var currentNode = node;
if (currentNode && currentNode.nodeType !== 1 && currentNode.parentNode && currentNode.parentNode.nodeType === 1) {
currentNode = currentNode.parentNode;
}
while (currentNode && currentNode.nodeType === 1) {
if (currentNode.hasAttribute(attributeName)) {
return currentNode;
}
currentNode = currentNode.parentNode;
}
return null;
}
function hydrateExchange(card) {
var copy = card.querySelector(".mas-country-info__currency-copy");
var exchange = card.querySelector(".mas-country-info__exchange");
var pair = card.querySelector("[data-mas-exchange-pair]");
var rate = card.querySelector("[data-mas-exchange-rate]");
var updated = card.querySelector("[data-mas-exchange-updated]");
var toggle = card.querySelector("[data-mas-exchange-toggle]");
var chart = card.querySelector("[data-mas-exchange-chart]");
var sourceCurrency = getCurrencyFromText(copy ? copy.textContent : "");
var targetCurrency = getTargetCurrency(card, sourceCurrency);
var now;
var start;
var latestUrl;
var historyUrl;
var cachePrefix;
var latestRateValue = NaN;
var latestDateValue = "";
var currentDirection = "forward";
card._masExchangeState = {
exchange: exchange,
pair: pair,
rate: rate,
updated: updated,
toggle: toggle,
sourceCurrency: sourceCurrency,
targetCurrency: targetCurrency,
latestRateValue: latestRateValue,
latestDateValue: latestDateValue,
currentDirection: currentDirection
};
if (!sourceCurrency || sourceCurrency == targetCurrency || !window.fetch) {
setUnavailable(exchange, pair, rate, updated, sourceCurrency, targetCurrency);
if (toggle) {
toggle.hidden = true;
toggle.disabled = true;
toggle.setAttribute("aria-pressed", "false");
}
return;
}
applyExchangeDisplay(card, exchange, pair, sourceCurrency, targetCurrency, currentDirection);
if (toggle) {
toggle.hidden = true;
toggle.disabled = true;
}
now = new Date();
latestUrl = apiBase + "?base=" + encodeURIComponent(sourceCurrency) + "&quotes=" + encodeURIComponent(targetCurrency);
cachePrefix = "mas.exchange." + sourceCurrency + "." + targetCurrency + "." + isoDate(now);
fetchJson(latestUrl, cachePrefix + ".latest")
.then(function (data) {
latestRateValue = getLatestRate(data, targetCurrency);
latestDateValue = getLatestDate(data);
card._masExchangeState.latestRateValue = latestRateValue;
card._masExchangeState.latestDateValue = latestDateValue;
if (isNaN(latestRateValue) || !isFinite(latestRateValue) || latestRateValue <= 0) {
throw new Error("Exchange rate missing");
}
syncExchangeCard(card);
if (!chart) {
if (chart) {
chart.setAttribute("points", "");
}
return;
}
start = getDateFromIso(latestDateValue);
start.setMonth(start.getMonth() - 3);
historyUrl = apiBase + "?from=" + encodeURIComponent(isoDate(start)) + "&to=" + encodeURIComponent(latestDateValue) + "&base=" + encodeURIComponent(sourceCurrency) + "&quotes=" + encodeURIComponent(targetCurrency);
return fetchJson(historyUrl, cachePrefix + ".history." + latestDateValue)
.then(function (historyData) {
var series = normalizeSeries(historyData, targetCurrency);
renderChart(chart, series);
if (exchange && series.length > 1) {
exchange.classList.add("has-chart");
}
})
.catch(function () {
chart.setAttribute("points", "");
if (exchange) {
exchange.classList.remove("has-chart");
}
});
})
.catch(function () {
setUnavailable(exchange, pair, rate, updated, sourceCurrency, targetCurrency);
});
}
onReady(function () {
if (!document._masCountryExchangeDelegated) {
document.addEventListener("click", function (event) {
var toggle = getClosestExchangeNode(event.target, "data-mas-exchange-toggle");
var card;
if (!toggle) {
return;
}
card = getClosestExchangeNode(toggle, "data-mas-country-exchange");
if (!card) {
return;
}
event.preventDefault();
toggleExchangeCard(card);
});
document._masCountryExchangeDelegated = true;
}
Array.prototype.slice.call(document.querySelectorAll("[data-mas-country-exchange]")).forEach(hydrateExchange);
});
}());
(function () {
var mobileMedia = window.matchMedia ? window.matchMedia("(max-width: 759px)") : null;
var collapsedHeight = 416;
function onReady(callback) {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", callback);
return;
}
callback();
}
function setExpanded(root, toggle, expanded) {
root.classList.toggle("is-expanded", expanded);
toggle.setAttribute("aria-expanded", expanded ? "true" : "false");
toggle.textContent = expanded ? "Réduire" : "Continuer à lire";
}
function resetCountryIntroItems(content) {
Array.prototype.slice.call(content.children).forEach(function (item) {
item.classList.remove("mas-country-intro__item", "is-hidden-by-default");
});
}
function getCountryIntroItemsToHide(content, isMobile) {
var items = Array.prototype.slice.call(content.children);
var hiddenItems = [];
var firstHeadingSeen = false;
var firstTextCardSeen = false;
var afterFirstGroup = false;
items.forEach(function (item) {
var tagName = item.tagName ? item.tagName.toUpperCase() : "";
var isHeading = tagName === "H3";
var isTextCard = tagName === "P" || tagName === "UL" || tagName === "OL";
item.classList.add("mas-country-intro__item");
if (isMobile) {
if (!firstHeadingSeen && isHeading) {
firstHeadingSeen = true;
return;
}
if (!firstTextCardSeen && isTextCard) {
firstTextCardSeen = true;
return;
}
hiddenItems.push(item);
return;
}
if (isHeading) {
if (!firstHeadingSeen) {
firstHeadingSeen = true;
return;
}
afterFirstGroup = true;
}
if (afterFirstGroup) {
hiddenItems.push(item);
}
});
return hiddenItems;
}
function syncCountryIntro(root) {
var toggle = root.querySelector("[data-mas-country-intro-toggle]");
var content = root.querySelector("#Home-Txt2 .Synergee-Web-Page-Component-Text-Container");
var isMobile = mobileMedia ? mobileMedia.matches : window.innerWidth < 760;
var hiddenItems;
if (!toggle || !content) {
return;
}
resetCountryIntroItems(content);
hiddenItems = getCountryIntroItemsToHide(content, isMobile);
root.classList.toggle("is-collapsible", hiddenItems.length > 0);
toggle.hidden = hiddenItems.length === 0;
if (!hiddenItems.length) {
setExpanded(root, toggle, true);
return;
}
hiddenItems.forEach(function (item) {
item.classList.add("is-hidden-by-default");
});
if (!root.hasAttribute("data-mas-country-intro-initialized")) {
setExpanded(root, toggle, false);
} else {
toggle.setAttribute("aria-expanded", root.classList.contains("is-expanded") ? "true" : "false");
toggle.textContent = root.classList.contains("is-expanded") ? "Réduire" : "Continuer à lire";
}
}
function initCountryIntro(root) {
var toggle = root.querySelector("[data-mas-country-intro-toggle]");
var resizeTimer = null;
if (!toggle) {
return;
}
toggle.addEventListener("click", function () {
setExpanded(root, toggle, !root.classList.contains("is-expanded"));
});
function refresh() {
syncCountryIntro(root);
root.setAttribute("data-mas-country-intro-initialized", "true");
}
if (mobileMedia) {
if (mobileMedia.addEventListener) {
mobileMedia.addEventListener("change", refresh);
} else if (mobileMedia.addListener) {
mobileMedia.addListener(refresh);
}
}
window.addEventListener("resize", function () {
window.clearTimeout(resizeTimer);
resizeTimer = window.setTimeout(refresh, 120);
});
refresh();
}
onReady(function () {
Array.prototype.slice.call(document.querySelectorAll("[data-mas-country-intro]")).forEach(initCountryIntro);
});
}());
(function () {
var forecastUrl = "https://api.open-meteo.com/v1/forecast";
var cacheLifetime = 60 * 60 * 1000;
var clockTimer = null;
var clocks = [];
function onReady(callback) {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", callback);
return;
}
callback();
}
function normalize(value) {
return (value || "")
.toLowerCase()
.replace(/[’']/g, " ")
.replace(/[^a-z0-9\u00c0-\u017f]+/g, " ")
.replace(/\s+/g, " ")
.trim();
}
function getCityName(card) {
var title = card.querySelector(".mas-destination-card__title");
var heading = title ? title.querySelector("h1, h2, h3, h4, p, a") : null;
return (heading ? heading.textContent : title ? title.textContent : "").replace(/\s+/g, " ").trim();
}
function getMarkers(root) {
var markers = {
byName: {},
list: []
};
Array.prototype.slice.call(root.querySelectorAll(".mas-country-map__markers [data-title][data-lat][data-lng]")).forEach(function (marker) {
var cityMarker = {
title: marker.getAttribute("data-title"),
latitude: marker.getAttribute("data-lat"),
longitude: marker.getAttribute("data-lng")
};
var key = normalize(cityMarker.title);
if (key) {
markers.byName[key] = cityMarker;
markers.list.push(cityMarker);
}
});
return markers;
}
function getCityOverviewMarker() {
var marker = document.querySelector(".MoveAndStudyCore.MoveAndStudyCore-city .mas-city-map__markers [data-city][data-lat][data-lng]");
if (!marker) {
return null;
}
return {
title: marker.getAttribute("data-city") || "",
latitude: marker.getAttribute("data-lat"),
longitude: marker.getAttribute("data-lng")
};
}
function findMarkerForCity(markers, cityName) {
var cityKey = normalize(cityName);
var candidates;
if (!cityKey || !markers) {
return null;
}
if (markers.byName[cityKey]) {
return markers.byName[cityKey];
}
candidates = markers.list.filter(function (marker) {
var markerKey = normalize(marker.title);
return markerKey && (markerKey.indexOf(cityKey) !== -1 || cityKey.indexOf(markerKey) !== -1);
});
return candidates.length == 1 ? candidates[0] : null;
}
function isFiniteNumber(value) {
return value !== null && value !== "" && isFinite(parseFloat(value));
}
function weatherIconSvg(iconKey) {
switch (iconKey) {
case "sun":
return '<svg viewBox="0 0 24 24" focusable="false"><circle cx="12" cy="12" r="3.2"></circle><path d="M12 2.8v2.3M12 18.9v2.3M21.2 12h-2.3M5.1 12H2.8M18.5 5.5l-1.6 1.6M7.1 16.9l-1.6 1.6M18.5 18.5l-1.6-1.6M7.1 7.1 5.5 5.5"></path></svg>';
case "sun-cloud":
return '<svg viewBox="0 0 24 24" focusable="false"><path d="M8.2 6.1a3.1 3.1 0 0 1 5.5-.7"></path><path d="M7.1 3.6v1.7M3.9 6.8H5.6M15.4 6.8h1.7M5.2 4.9l1.2 1.2"></path><path d="M7.7 17.5h8.1a3.2 3.2 0 0 0 .2-6.3 4.7 4.7 0 0 0-9.1 1 2.7 2.7 0 0 0 .8 5.3Z"></path></svg>';
case "cloud":
return '<svg viewBox="0 0 24 24" focusable="false"><path d="M7.4 17.5h8.4a3.3 3.3 0 0 0 .2-6.5 4.8 4.8 0 0 0-9.3 1 2.8 2.8 0 0 0 .7 5.5Z"></path></svg>';
case "rain":
return '<svg viewBox="0 0 24 24" focusable="false"><path d="M7.4 14.9h8.4a3.3 3.3 0 0 0 .2-6.5 4.8 4.8 0 0 0-9.3 1 2.8 2.8 0 0 0 .7 5.5Z"></path><path d="M9.2 17.7 8.4 20M12.2 17.7l-.8 2.3M15.2 17.7l-.8 2.3"></path></svg>';
case "snow":
return '<svg viewBox="0 0 24 24" focusable="false"><path d="M7.4 14.6h8.4A3.3 3.3 0 0 0 16 8.1a4.8 4.8 0 0 0-9.3 1 2.8 2.8 0 0 0 .7 5.5Z"></path><path d="m9.5 17.5 1.1 1.9m0-1.9-1.1 1.9m1.1-3v4.1"></path><path d="m14 17.5 1.1 1.9m0-1.9-1.1 1.9m1.1-3v4.1"></path></svg>';
case "storm":
return '<svg viewBox="0 0 24 24" focusable="false"><path d="M7.4 14.4h8.4A3.3 3.3 0 0 0 16 8a4.8 4.8 0 0 0-9.3 1 2.8 2.8 0 0 0 .7 5.4Z"></path><path d="m11.8 15.8-1.7 3.1h2l-.9 2.3 2.9-4h-2.1l1.1-1.4"></path></svg>';
default:
return '<svg viewBox="0 0 24 24" focusable="false"><path d="M8 15.8a4.2 4.2 0 1 0 0-7.6"></path><path d="M16 8.2a4.2 4.2 0 1 0 0 7.6"></path><path d="M7.6 12h8.8"></path></svg>';
}
}
function weatherSummary(code) {
var numericCode = parseInt(code, 10);
if ([0].indexOf(numericCode) !== -1) {
return {iconKey: "sun", label: "Ensoleillé"};
}
if ([1, 2].indexOf(numericCode) !== -1) {
return {iconKey: "sun-cloud", label: "Éclaircies"};
}
if ([3, 45, 48].indexOf(numericCode) !== -1) {
return {iconKey: "cloud", label: "Nuageux"};
}
if ([51, 53, 55, 56, 57, 61, 63, 65, 66, 67, 80, 81, 82].indexOf(numericCode) !== -1) {
return {iconKey: "rain", label: "Pluie"};
}
if ([71, 73, 75, 77, 85, 86].indexOf(numericCode) !== -1) {
return {iconKey: "snow", label: "Neige"};
}
if ([95, 96, 99].indexOf(numericCode) !== -1) {
return {iconKey: "storm", label: "Orage"};
}
return {iconKey: "variable", label: "Variable"};
}
function formatTemperature(value) {
if (value === null || typeof value === "undefined" || isNaN(parseFloat(value))) {
return "-";
}
return Math.round(parseFloat(value)) + "\u00b0";
}
function formatDay(value, index) {
if (index === 0) {
return "Auj.";
}
try {
return new Intl.DateTimeFormat("fr-FR", {weekday: "short"}).format(new Date(value + "T12:00:00"));
} catch (error) {
return value.slice(5);
}
}
function formatUpdated(value) {
if (!value) {
return "";
}
try {
return new Intl.DateTimeFormat("fr-FR", {
hour: "2-digit",
minute: "2-digit"
}).format(new Date(value));
} catch (error) {
return value.slice(11, 16);
}
}
function formatLocalTime(timezone) {
try {
return new Intl.DateTimeFormat("fr-FR", {
hour: "2-digit",
minute: "2-digit",
timeZone: timezone
}).format(new Date());
} catch (error) {
return "";
}
}
function padClockPart(value) {
return String(value).padStart(2, "0");
}
function getLocalTimeParts(timezone) {
var parts;
var values = {};
var hour;
var minute;
try {
parts = new Intl.DateTimeFormat("fr-FR", {
hour: "2-digit",
minute: "2-digit",
hour12: false,
timeZone: timezone
}).formatToParts(new Date());
parts.forEach(function (part) {
values[part.type] = part.value;
});
hour = parseInt(values.hour || "0", 10) % 24;
minute = parseInt(values.minute || "0", 10);
return {
label: padClockPart(hour) + ":" + padClockPart(minute),
hour: hour,
minute: minute
};
} catch (error) {
return null;
}
}
function getTimezoneOffsetMinutes(timezone, date) {
var parts;
var values = {};
var utcDate;
try {
parts = new Intl.DateTimeFormat("en-GB", {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false,
timeZone: timezone
}).formatToParts(date);
parts.forEach(function (part) {
values[part.type] = part.value;
});
utcDate = Date.UTC(
parseInt(values.year, 10),
parseInt(values.month, 10) - 1,
parseInt(values.day, 10),
parseInt(values.hour, 10) % 24,
parseInt(values.minute, 10),
parseInt(values.second, 10)
);
return Math.round((utcDate - date.getTime()) / 60000);
} catch (error) {
return null;
}
}
function formatTimezoneLabel(timezone) {
var offset = getTimezoneOffsetMinutes(timezone, new Date());
var zoneName;
if (timezone == "Australia/Sydney") {
return offset >= 660 ? "AEDT" : "AEST";
}
if (timezone == "Europe/Zurich") {
return offset >= 120 ? "CEST" : "CET";
}
try {
zoneName = new Intl.DateTimeFormat("en-US", {
timeZone: timezone,
timeZoneName: "short"
}).formatToParts(new Date()).filter(function (part) {
return part.type == "timeZoneName";
}).map(function (part) {
return part.value;
}).join("");
return zoneName || timezone;
} catch (error) {
return timezone;
}
}
function updateClock(clock) {
var time = getLocalTimeParts(clock.timezone);
var hourDegrees;
var minuteDegrees;
if (!time || !time.label) {
clock.element.classList.add("is-unavailable");
return false;
}
hourDegrees = ((time.hour % 12) + (time.minute / 60)) * 30;
minuteDegrees = time.minute * 6;
clock.element.classList.remove("is-unavailable");
clock.timeElement.textContent = time.label;
clock.hourHand.style.transform = "translateX(-50%) rotate(" + hourDegrees + "deg)";
clock.minuteHand.style.transform = "translateX(-50%) rotate(" + minuteDegrees + "deg)";
if (clock.labelElement) {
clock.labelElement.textContent = clock.label;
}
if (clock.zoneElement) {
clock.zoneElement.textContent = formatTimezoneLabel(clock.timezone);
}
clock.element.setAttribute("aria-label", clock.label + " : " + time.label + " " + formatTimezoneLabel(clock.timezone));
return true;
}
function refreshClocks() {
clocks = clocks.filter(function (clock) {
if (!clock.element || !clock.element.parentNode) {
return false;
}
return updateClock(clock);
});
if (!clocks.length && clockTimer) {
window.clearInterval(clockTimer);
clockTimer = null;
}
}
function registerAnalogClock(element, timezone, label) {
var clock;
if (!element || !timezone) {
return;
}
clock = {
element: element,
timezone: timezone,
label: label || element.getAttribute("data-mas-clock-label") || "Heure locale",
timeElement: element.querySelector("[data-mas-clock-time]"),
labelElement: element.querySelector("[data-mas-clock-label]"),
zoneElement: element.querySelector("[data-mas-clock-zone]"),
hourHand: element.querySelector("[data-mas-clock-hour]"),
minuteHand: element.querySelector("[data-mas-clock-minute]")
};
if (!clock.timeElement || !clock.hourHand || !clock.minuteHand) {
return;
}
clocks = clocks.filter(function (registeredClock) {
return registeredClock.element !== element;
});
clocks.push(clock);
updateClock(clock);
if (!clockTimer) {
clockTimer = window.setInterval(refreshClocks, 60000);
}
}
function getPreferredClockCity(section) {
var cityNames = Array.prototype.slice.call(section.querySelectorAll(".mas-destination-card")).map(getCityName).filter(Boolean);
var preferred = cityNames.filter(function (cityName) {
return normalize(cityName) == "sydney";
});
return preferred[0] || cityNames[0] || "";
}
function getPreferredClockMarker(markers, preferredCity) {
var preferredKey = normalize(preferredCity);
if (!markers || !markers.list || !markers.list.length) {
return null;
}
if (preferredKey && markers.byName[preferredKey]) {
return markers.byName[preferredKey];
}
return markers.list.filter(function (marker) {
return normalize(marker.title) == "sydney";
})[0] || markers.list[0] || null;
}
function createCountryClockController(section) {
var root = document.querySelector("[data-mas-country-clocks]");
var destinationClock = root ? root.querySelector("[data-mas-country-clock='destination']") : null;
var referenceClock = root ? root.querySelector("[data-mas-country-clock='reference']") : null;
var preferredCity = getPreferredClockCity(section);
var destinationReady = false;
if (!root) {
return null;
}
if (referenceClock) {
registerAnalogClock(
referenceClock,
referenceClock.getAttribute("data-mas-clock-timezone"),
referenceClock.getAttribute("data-mas-clock-label") || "Genève"
);
}
return {
registerDestination: function (cityName, timezone) {
if (destinationReady || !destinationClock || !timezone || (preferredCity && normalize(cityName) != normalize(preferredCity))) {
return;
}
destinationReady = true;
registerAnalogClock(destinationClock, timezone, cityName);
}
};
}
function createCityClockController(section) {
var root = section ? section.querySelector("[data-mas-city-clocks]") : null;
var destinationClock = root ? root.querySelector("[data-mas-city-clock='destination']") : null;
var referenceClock = root ? root.querySelector("[data-mas-city-clock='reference']") : null;
var destinationReady = false;
if (!root) {
return null;
}
if (referenceClock) {
registerAnalogClock(
referenceClock,
referenceClock.getAttribute("data-mas-clock-timezone"),
referenceClock.getAttribute("data-mas-clock-label") || "Geneve"
);
}
return {
registerDestination: function (cityName, timezone) {
if (destinationReady || !destinationClock || !timezone) {
return;
}
destinationReady = true;
registerAnalogClock(destinationClock, timezone, cityName || "Destination");
}
};
}
function setFallback(panel, cityName) {
panel.classList.add("is-unavailable");
panel.classList.remove("is-ready");
panel.innerHTML = [
'<p class="mas-city-weather__eyebrow">Météo locale</p>',
'<p class="mas-city-weather__current"><span class="mas-city-weather__icon" aria-hidden="true">' + weatherIconSvg("variable") + '</span><span class="mas-city-weather__summary">Prévisions indisponibles</span></p>',
'<p class="mas-city-weather__fallback">Consultez la destination ' + escapeHtml(cityName || "sélectionnée") + ' pour préparer votre séjour.</p>'
].join("");
}
function escapeHtml(value) {
return String(value || "")
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;");
}
function renderWeather(panel, cityName, data) {
var current = data.current || {};
var daily = data.daily || {};
var summary = weatherSummary(current.weather_code);
var dates = (daily.time || []).slice(0, 4);
var highs = daily.temperature_2m_max || [];
var lows = daily.temperature_2m_min || [];
var codes = daily.weather_code || [];
var forecast = dates.map(function (date, index) {
var daySummary = weatherSummary(codes[index]);
return [
'<div class="mas-city-weather__day">',
'<div class="mas-city-weather__day-meta">',
'<span class="mas-city-weather__day-label">' + escapeHtml(formatDay(date, index)) + '</span>',
'<span class="mas-city-weather__day-icon" aria-hidden="true">' + weatherIconSvg(daySummary.iconKey) + '</span>',
'</div>',
'<strong class="mas-city-weather__day-temp">' + escapeHtml(formatTemperature(lows[index])) + '/' + escapeHtml(formatTemperature(highs[index])) + '</strong>',
'</div>'
].join("");
}).join("");
var updated = formatUpdated(current.time);
panel.classList.add("is-ready");
panel.classList.remove("is-unavailable");
panel.innerHTML = [
'<p class="mas-city-weather__eyebrow">Météo à ' + escapeHtml(cityName) + '</p>',
'<p class="mas-city-weather__current">',
'<span class="mas-city-weather__icon" aria-hidden="true">' + weatherIconSvg(summary.iconKey) + '</span>',
'<span class="mas-city-weather__summary">' + escapeHtml(formatTemperature(current.temperature_2m)) + ' aujourd’hui, ' + escapeHtml(summary.label.toLowerCase()) + '</span>',
'</p>',
'<div class="mas-city-weather__forecast">' + forecast + '</div>',
updated ? '<p class="mas-city-weather__updated">Mise à jour à ' + escapeHtml(updated) + '</p>' : ''
].join("");
}
function getWeatherCacheKey(marker) {
var latitude = Math.round(parseFloat(marker.latitude) * 1000) / 1000;
var longitude = Math.round(parseFloat(marker.longitude) * 1000) / 1000;
return "mas.weather." + latitude + "." + longitude + "." + new Date().toISOString().slice(0, 13);
}
function getCachedJson(cacheKey) {
var stored;
var parsed;
try {
stored = window.sessionStorage && window.sessionStorage.getItem(cacheKey);
if (!stored) {
return null;
}
parsed = JSON.parse(stored);
if (!parsed || !parsed.createdAt || (Date.now() - parsed.createdAt) > cacheLifetime) {
window.sessionStorage.removeItem(cacheKey);
return null;
}
return parsed.payload || null;
} catch (error) {
return null;
}
}
function setCachedJson(cacheKey, payload) {
try {
if (window.sessionStorage) {
window.sessionStorage.setItem(cacheKey, JSON.stringify({
createdAt: Date.now(),
payload: payload
}));
}
} catch (error) {
return;
}
}
function fetchWeather(url, cacheKey) {
var cached = getCachedJson(cacheKey);
if (cached) {
return Promise.resolve(cached);
}
return window.fetch(url)
.then(function (response) {
if (!response.ok) {
throw new Error("Weather unavailable");
}
return response.json();
})
.then(function (data) {
setCachedJson(cacheKey, data);
return data;
});
}
function hydrateCard(card, markers, countryClockController) {
var panel = card.querySelector("[data-mas-city-weather]");
var cityName = getCityName(card);
var marker = findMarkerForCity(markers, cityName);
if (!panel || !cityName || !marker || !window.fetch || !isFiniteNumber(marker.latitude) || !isFiniteNumber(marker.longitude)) {
if (panel) {
setFallback(panel, cityName);
}
return;
}
var url = forecastUrl
+ "?latitude=" + encodeURIComponent(marker.latitude)
+ "&longitude=" + encodeURIComponent(marker.longitude)
+ "&current=temperature_2m,weather_code"
+ "&daily=weather_code,temperature_2m_max,temperature_2m_min"
+ "&forecast_days=4"
+ "&timezone=auto";
fetchWeather(url, getWeatherCacheKey(marker))
.then(function (data) {
if (countryClockController) {
countryClockController.registerDestination(cityName, data.timezone);
}
renderWeather(panel, cityName, data);
})
.catch(function () {
setFallback(panel, cityName);
});
}
function hydrateCityOverview(section) {
var panel = section ? section.querySelector("[data-mas-city-weather]") : null;
var marker = getCityOverviewMarker();
var cityClockController = createCityClockController(section);
var cityName = marker ? marker.title : "";
var url;
if (!panel || !marker || !window.fetch || !isFiniteNumber(marker.latitude) || !isFiniteNumber(marker.longitude)) {
if (panel) {
setFallback(panel, cityName);
}
return;
}
url = forecastUrl
+ "?latitude=" + encodeURIComponent(marker.latitude)
+ "&longitude=" + encodeURIComponent(marker.longitude)
+ "&current=temperature_2m,weather_code"
+ "&daily=weather_code,temperature_2m_max,temperature_2m_min"
+ "&forecast_days=4"
+ "&timezone=auto";
fetchWeather(url, getWeatherCacheKey(marker))
.then(function (data) {
if (cityClockController) {
cityClockController.registerDestination(cityName, data.timezone);
}
renderWeather(panel, cityName, data);
})
.catch(function () {
setFallback(panel, cityName);
});
}
onReady(function () {
var section = document.querySelector(".MoveAndStudyCore-country .mas-country-destinations");
var cards;
var markers;
var countryClockController;
var countryClockRoot;
var destinationClock;
var preferredMarker;
var url;
if (!section) {
return;
}
cards = Array.prototype.slice.call(section.querySelectorAll(".mas-destination-card"));
markers = getMarkers(section);
countryClockController = createCountryClockController(section);
countryClockRoot = document.querySelector("[data-mas-country-clocks]");
destinationClock = countryClockRoot ? countryClockRoot.querySelector("[data-mas-country-clock='destination']") : null;
cards.forEach(function (card) {
hydrateCard(card, markers, countryClockController);
});
if (cards.length || !countryClockController) {
return;
}
preferredMarker = getPreferredClockMarker(markers, getPreferredClockCity(section));
if (!preferredMarker || !window.fetch || !isFiniteNumber(preferredMarker.latitude) || !isFiniteNumber(preferredMarker.longitude)) {
return;
}
url = forecastUrl
+ "?latitude=" + encodeURIComponent(preferredMarker.latitude)
+ "&longitude=" + encodeURIComponent(preferredMarker.longitude)
+ "&current=temperature_2m,weather_code"
+ "&daily=weather_code,temperature_2m_max,temperature_2m_min"
+ "&forecast_days=4"
+ "&timezone=auto";
fetchWeather(url, getWeatherCacheKey(preferredMarker))
.then(function (data) {
if (!destinationClock || !data || !data.timezone) {
return;
}
registerAnalogClock(destinationClock, data.timezone, preferredMarker.title || "Destination");
})
.catch(function () {
return;
});
});
}());
(function () {
var LAYOUTS = {
COMPACT: "editorial-compact",
LANDSCAPE: "editorial-landscape",
MIXED: "editorial-mixed",
PANORAMA: "editorial-panorama"
};
function onReady(callback) {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", callback);
return;
}
callback();
}
function qs(root, selector) {
return root ? root.querySelector(selector) : null;
}
function qsa(root, selector) {
return root ? Array.prototype.slice.call(root.querySelectorAll(selector)) : [];
}
function getBreakpoint() {
if (window.matchMedia("(min-width: 960px)").matches) {
return "desktop";
}
if (window.matchMedia("(min-width: 760px)").matches) {
return "tablet";
}
return "mobile";
}
function getPreviewLimit(layout, count) {
var breakpoint = getBreakpoint();
if (breakpoint === "mobile") {
return Math.min(count, 3);
}
if (breakpoint === "tablet") {
if (layout === LAYOUTS.COMPACT) {
return Math.min(count, 4);
}
if (layout === LAYOUTS.PANORAMA) {
return Math.min(count, 4);
}
return Math.min(count, 5);
}
if (layout === LAYOUTS.COMPACT) {
return Math.min(count, 4);
}
if (layout === LAYOUTS.MIXED) {
return Math.min(count, 6);
}
if (layout === LAYOUTS.PANORAMA) {
return Math.min(count, 5);
}
return Math.min(count, 7);
}
function getLegacyPreviewLayout(layout) {
if (layout === LAYOUTS.COMPACT) {
return "compact";
}
if (layout === LAYOUTS.MIXED) {
return "balanced";
}
return "editorial";
}
function classifyRatio(ratio) {
if (!isFinite(ratio) || ratio <= 0) {
return "landscape";
}
if (ratio < 0.9) {
return "portrait";
}
if (ratio <= 1.2) {
return "square";
}
if (ratio <= 1.9) {
return "landscape";
}
if (ratio <= 2.8) {
return "wide";
}
return "panorama";
}
function buildViewerUrl(url) {
try {
var absolute = new URL(url, window.location.href);
if (absolute.pathname.indexOf("image.php") === -1) {
return absolute.toString();
}
absolute.searchParams.set("destinationWidth", "1800");
absolute.searchParams.set("destinationHeight", "1200");
absolute.searchParams.set("keepRatio", "1");
return absolute.pathname + "?" + absolute.searchParams.toString();
} catch (error) {
return url;
}
}
function normalizeText(text) {
return (text || "").replace(/\s+/g, " ").trim();
}
function waitForImageMetrics(image, href) {
return new Promise(function (resolve) {
var source = image ? (image.currentSrc || image.getAttribute("src") || href) : href;
if (image && image.complete && image.naturalWidth > 0 && image.naturalHeight > 0) {
resolve({
naturalWidth: image.naturalWidth,
naturalHeight: image.naturalHeight
});
return;
}
if (!source) {
resolve(null);
return;
}
var probe = new Image();
var settled = false;
function finish(result) {
if (settled) {
return;
}
settled = true;
resolve(result);
}
probe.onload = function () {
finish({
naturalWidth: probe.naturalWidth,
naturalHeight: probe.naturalHeight
});
};
probe.onerror = function () {
finish(null);
};
window.setTimeout(function () {
finish(null);
}, 3000);
probe.src = source;
});
}
async function createGalleryModel(links) {
var models = await Promise.all(links.map(async function (link, index) {
var image = qs(link, ".mas-city-gallery-component__image");
var title = normalizeText(link.getAttribute("title") || (image ? image.getAttribute("alt") : ""));
var href = link.getAttribute("href") || "";
var metrics = await waitForImageMetrics(image, href);
var ratio = metrics ? metrics.naturalWidth / metrics.naturalHeight : 0;
return {
index: index,
link: link,
image: image,
href: href,
viewerHref: buildViewerUrl(href),
alt: image ? (image.getAttribute("alt") || "") : "",
title: title,
naturalWidth: metrics ? metrics.naturalWidth : 0,
naturalHeight: metrics ? metrics.naturalHeight : 0,
ratio: ratio,
ratioType: classifyRatio(ratio),
isValid: !!metrics
};
}));
return models;
}
function chooseLayout(items) {
var validItems = items.filter(function (item) {
return item.isValid;
});
var counts = {
portrait: 0,
square: 0,
landscape: 0,
wide: 0,
panorama: 0
};
var firstType;
validItems.forEach(function (item) {
counts[item.ratioType] += 1;
});
if (validItems.length <= 5) {
return LAYOUTS.COMPACT;
}
firstType = validItems[0] ? validItems[0].ratioType : "landscape";
if (firstType === "panorama" || (counts.panorama >= 1 && (counts.wide + counts.panorama) >= 2 && firstType !== "portrait")) {
return LAYOUTS.PANORAMA;
}
if (firstType === "portrait" || counts.portrait >= 1 || counts.square >= 2) {
return LAYOUTS.MIXED;
}
return LAYOUTS.LANDSCAPE;
}
function getVisiblePreviewIndexes(items, previewLimit) {
var visible = [];
items.forEach(function (item) {
if (!item.isValid || visible.length >= previewLimit) {
return;
}
visible.push(item.index);
});
return visible;
}
function setPreviewState(frame, items, actions) {
var validItems = items.filter(function (item) {
return item.isValid;
});
var layout = chooseLayout(items);
var previewLimit = getPreviewLimit(layout, validItems.length);
var visibleIndexes = getVisiblePreviewIndexes(items, previewLimit);
frame.setAttribute("data-gallery-state", "preview");
frame.setAttribute("data-city-gallery-layout", layout);
frame.setAttribute("data-image-count", String(items.length));
frame.setAttribute("data-city-gallery-ready", "true");
frame.setAttribute("data-preview-layout", getLegacyPreviewLayout(layout));
items.forEach(function (item) {
item.link.classList.toggle("is-preview-hidden", visibleIndexes.indexOf(item.index) === -1);
});
if (actions) {
actions.hidden = validItems.length <= previewLimit;
}
}
function bindGallery(frame) {
var links = qsa(frame, ".mas-city-gallery-component__link");
var actions = qs(frame, "[data-mas-city-gallery-actions]");
var openButton = qs(frame, "[data-mas-city-gallery-open]");
var viewer = qs(frame, "[data-mas-city-gallery-viewer]");
var viewerImage = qs(frame, "[data-mas-city-gallery-image]");
var viewerCaption = qs(frame, "[data-mas-city-gallery-caption]");
var closeButtons = qsa(frame, "[data-mas-city-gallery-close]");
var prevButton = qs(frame, "[data-mas-city-gallery-prev]");
var nextButton = qs(frame, "[data-mas-city-gallery-next]");
var items = [];
var viewerItems = [];
var currentIndex = 0;
if (!links.length || !viewer || !viewerImage) {
return;
}
frame.setAttribute("data-city-gallery-ready", "false");
frame.setAttribute("data-image-count", String(links.length));
function render(index) {
var item = viewerItems[index];
if (!item) {
return;
}
currentIndex = index;
viewerImage.src = item.viewerHref || item.href;
viewerImage.alt = item.alt || "";
if (viewerCaption) {
if (item.title) {
viewerCaption.textContent = item.title;
viewerCaption.hidden = false;
} else {
viewerCaption.textContent = "";
viewerCaption.hidden = true;
}
}
}
function open(index) {
render(index);
viewer.hidden = false;
document.body.classList.add("is-city-gallery-viewer-open");
}
function close() {
viewer.hidden = true;
document.body.classList.remove("is-city-gallery-viewer-open");
}
function prev() {
render((currentIndex - 1 + viewerItems.length) % viewerItems.length);
}
function next() {
render((currentIndex + 1) % viewerItems.length);
}
function updatePreview() {
setPreviewState(frame, items, actions);
}
createGalleryModel(links).then(function (models) {
items = models;
viewerItems = items.filter(function (item) {
return item.isValid;
});
if (!viewerItems.length) {
frame.setAttribute("data-city-gallery-ready", "true");
if (actions) {
actions.hidden = true;
}
return;
}
items.forEach(function (item) {
item.link.addEventListener("click", function (event) {
var viewerIndex;
event.preventDefault();
viewerIndex = viewerItems.findIndex(function (viewerItem) {
return viewerItem.index === item.index;
});
if (viewerIndex === -1) {
return;
}
open(viewerIndex);
});
});
if (openButton) {
openButton.addEventListener("click", function () {
open(0);
});
}
closeButtons.forEach(function (button) {
button.addEventListener("click", close);
});
if (prevButton) {
prevButton.addEventListener("click", prev);
}
if (nextButton) {
nextButton.addEventListener("click", next);
}
updatePreview();
window.addEventListener("resize", updatePreview);
});
document.addEventListener("keydown", function (event) {
if (viewer.hidden || !viewerItems.length) {
return;
}
if (event.key === "Escape") {
close();
} else if (event.key === "ArrowLeft") {
prev();
} else if (event.key === "ArrowRight") {
next();
}
});
}
onReady(function () {
qsa(document, "[data-mas-city-gallery]").forEach(bindGallery);
});
})();
(function () {
var messageTypeInit = "CityInteractiveMap:init";
var messageTypeReady = "CityInteractiveMap:ready";
var messageTypeUnavailable = "CityInteractiveMap:unavailable";
var iframeSource = "/synergee/Themes/MoveAndStudyCore/Components/InteractiveMap/Iframe/CityInteractiveMap.html";
function onReady(callback) {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", callback);
} else {
callback();
}
}
function addClass(element, className) {
if (element && element.className.indexOf(className) === -1) {
element.className += " " + className;
}
}
function hideMap(component) {
if (!component) {
return;
}
addClass(component, "is-unavailable");
}
function getMarkers(component) {
var markerLinks = component.querySelectorAll(".mas-city-map__markers a");
var markers = [];
Array.prototype.forEach.call(markerLinks, function (markerLink) {
var latitude = parseFloat(markerLink.getAttribute("data-lat"));
var longitude = parseFloat(markerLink.getAttribute("data-lng"));
var zoom = parseFloat(markerLink.getAttribute("data-zoom")) || 14;
var url = markerLink.getAttribute("href");
if (!isFinite(latitude) || !isFinite(longitude) || latitude === 0 || longitude === 0 || !url) {
return;
}
markers.push({
title: markerLink.getAttribute("data-title") || markerLink.textContent || "",
city: markerLink.getAttribute("data-city") || "",
url: url,
zoom: zoom,
position: {
lat: latitude,
lng: longitude
}
});
});
return markers;
}
function initMap(component) {
var key = component.getAttribute("data-map-key");
var frame = component.querySelector(".mas-city-map__iframe");
var markers = getMarkers(component);
var timeout = null;
var settled = false;
if (!key || !frame || !markers.length) {
hideMap(component);
return;
}
function settleAsReady() {
if (settled) {
return;
}
settled = true;
clearTimeout(timeout);
addClass(component, "is-ready");
}
function settleAsUnavailable() {
if (settled) {
return;
}
settled = true;
clearTimeout(timeout);
hideMap(component);
}
function postInitMessage() {
if (!frame.contentWindow) {
settleAsUnavailable();
return;
}
frame.contentWindow.postMessage({
type: messageTypeInit,
key: key,
markers: markers
}, window.location.origin);
}
function onMessage(event) {
if (event.origin !== window.location.origin || event.source !== frame.contentWindow || !event.data) {
return;
}
if (event.data.type === messageTypeReady) {
window.removeEventListener("message", onMessage);
settleAsReady();
}
if (event.data.type === messageTypeUnavailable) {
window.removeEventListener("message", onMessage);
settleAsUnavailable();
}
}
window.addEventListener("message", onMessage);
frame.addEventListener("load", postInitMessage);
frame.setAttribute("src", iframeSource);
timeout = setTimeout(function () {
window.removeEventListener("message", onMessage);
settleAsUnavailable();
}, 12000);
}
onReady(function () {
var maps = document.querySelectorAll(".MoveAndStudyCore.MoveAndStudyCore-city [data-mas-city-interactive-map]");
Array.prototype.forEach.call(maps, function (component) {
if (component.getAttribute("data-map-bound") === "true") {
return;
}
component.setAttribute("data-map-bound", "true");
initMap(component);
});
});
}());
(function () {
var forecastUrl = "https://api.open-meteo.com/v1/forecast";
var cacheLifetime = 60 * 60 * 1000;
var clockTimer = null;
var clocks = [];
function onReady(callback) {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", callback);
return;
}
callback();
}
function escapeHtml(value) {
return String(value || "")
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;");
}
function isFiniteNumber(value) {
return value !== null && value !== "" && isFinite(parseFloat(value));
}
function weatherIconSvg(iconKey) {
switch (iconKey) {
case "sun":
return '<svg viewBox="0 0 24 24" focusable="false"><circle cx="12" cy="12" r="3.2"></circle><path d="M12 2.8v2.3M12 18.9v2.3M21.2 12h-2.3M5.1 12H2.8M18.5 5.5l-1.6 1.6M7.1 16.9l-1.6 1.6M18.5 18.5l-1.6-1.6M7.1 7.1 5.5 5.5"></path></svg>';
case "sun-cloud":
return '<svg viewBox="0 0 24 24" focusable="false"><path d="M8.2 6.1a3.1 3.1 0 0 1 5.5-.7"></path><path d="M7.1 3.6v1.7M3.9 6.8H5.6M15.4 6.8h1.7M5.2 4.9l1.2 1.2"></path><path d="M7.7 17.5h8.1a3.2 3.2 0 0 0 .2-6.3 4.7 4.7 0 0 0-9.1 1 2.7 2.7 0 0 0 .8 5.3Z"></path></svg>';
case "cloud":
return '<svg viewBox="0 0 24 24" focusable="false"><path d="M7.4 17.5h8.4a3.3 3.3 0 0 0 .2-6.5 4.8 4.8 0 0 0-9.3 1 2.8 2.8 0 0 0 .7 5.5Z"></path></svg>';
case "rain":
return '<svg viewBox="0 0 24 24" focusable="false"><path d="M7.4 14.9h8.4a3.3 3.3 0 0 0 .2-6.5 4.8 4.8 0 0 0-9.3 1 2.8 2.8 0 0 0 .7 5.5Z"></path><path d="M9.2 17.7 8.4 20M12.2 17.7l-.8 2.3M15.2 17.7l-.8 2.3"></path></svg>';
case "snow":
return '<svg viewBox="0 0 24 24" focusable="false"><path d="M7.4 14.6h8.4A3.3 3.3 0 0 0 16 8.1a4.8 4.8 0 0 0-9.3 1 2.8 2.8 0 0 0 .7 5.5Z"></path><path d="m9.5 17.5 1.1 1.9m0-1.9-1.1 1.9m1.1-3v4.1"></path><path d="m14 17.5 1.1 1.9m0-1.9-1.1 1.9m1.1-3v4.1"></path></svg>';
case "storm":
return '<svg viewBox="0 0 24 24" focusable="false"><path d="M7.4 14.4h8.4A3.3 3.3 0 0 0 16 8a4.8 4.8 0 0 0-9.3 1 2.8 2.8 0 0 0 .7 5.4Z"></path><path d="m11.8 15.8-1.7 3.1h2l-.9 2.3 2.9-4h-2.1l1.1-1.4"></path></svg>';
default:
return '<svg viewBox="0 0 24 24" focusable="false"><path d="M8 15.8a4.2 4.2 0 1 0 0-7.6"></path><path d="M16 8.2a4.2 4.2 0 1 0 0 7.6"></path><path d="M7.6 12h8.8"></path></svg>';
}
}
function weatherSummary(code) {
var numericCode = parseInt(code, 10);
if ([0].indexOf(numericCode) !== -1) {
return {iconKey: "sun", label: "Ensoleillé"};
}
if ([1, 2].indexOf(numericCode) !== -1) {
return {iconKey: "sun-cloud", label: "Éclaircies"};
}
if ([3, 45, 48].indexOf(numericCode) !== -1) {
return {iconKey: "cloud", label: "Nuageux"};
}
if ([51, 53, 55, 56, 57, 61, 63, 65, 66, 67, 80, 81, 82].indexOf(numericCode) !== -1) {
return {iconKey: "rain", label: "Pluie"};
}
if ([71, 73, 75, 77, 85, 86].indexOf(numericCode) !== -1) {
return {iconKey: "snow", label: "Neige"};
}
if ([95, 96, 99].indexOf(numericCode) !== -1) {
return {iconKey: "storm", label: "Orage"};
}
return {iconKey: "variable", label: "Variable"};
}
function formatTemperature(value) {
if (value === null || typeof value === "undefined" || isNaN(parseFloat(value))) {
return "-";
}
return Math.round(parseFloat(value)) + "\u00b0";
}
function formatDay(value, index) {
if (index === 0) {
return "Auj.";
}
try {
return new Intl.DateTimeFormat("fr-FR", {weekday: "short"}).format(new Date(value + "T12:00:00"));
} catch (error) {
return value.slice(5);
}
}
function formatUpdated(value) {
if (!value) {
return "";
}
try {
return new Intl.DateTimeFormat("fr-FR", {
hour: "2-digit",
minute: "2-digit"
}).format(new Date(value));
} catch (error) {
return value.slice(11, 16);
}
}
function getLocalTimeParts(timezone) {
var parts;
var values = {};
var hour;
var minute;
try {
parts = new Intl.DateTimeFormat("fr-FR", {
hour: "2-digit",
minute: "2-digit",
hour12: false,
timeZone: timezone
}).formatToParts(new Date());
parts.forEach(function (part) {
values[part.type] = part.value;
});
hour = parseInt(values.hour || "0", 10) % 24;
minute = parseInt(values.minute || "0", 10);
return {
label: String(hour).padStart(2, "0") + ":" + String(minute).padStart(2, "0"),
hour: hour,
minute: minute
};
} catch (error) {
return null;
}
}
function getTimezoneOffsetMinutes(timezone, date) {
var parts;
var values = {};
var utcDate;
try {
parts = new Intl.DateTimeFormat("en-GB", {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false,
timeZone: timezone
}).formatToParts(date);
parts.forEach(function (part) {
values[part.type] = part.value;
});
utcDate = Date.UTC(
parseInt(values.year, 10),
parseInt(values.month, 10) - 1,
parseInt(values.day, 10),
parseInt(values.hour, 10) % 24,
parseInt(values.minute, 10),
parseInt(values.second, 10)
);
return Math.round((utcDate - date.getTime()) / 60000);
} catch (error) {
return null;
}
}
function formatTimezoneLabel(timezone) {
var offset = getTimezoneOffsetMinutes(timezone, new Date());
var zoneName;
if (timezone == "Australia/Sydney") {
return offset >= 660 ? "AEDT" : "AEST";
}
if (timezone == "Europe/Zurich") {
return offset >= 120 ? "CEST" : "CET";
}
try {
zoneName = new Intl.DateTimeFormat("en-US", {
timeZone: timezone,
timeZoneName: "short"
}).formatToParts(new Date()).filter(function (part) {
return part.type == "timeZoneName";
}).map(function (part) {
return part.value;
}).join("");
return zoneName || timezone;
} catch (error) {
return timezone;
}
}
function updateClock(clock) {
var time = getLocalTimeParts(clock.timezone);
var hourDegrees;
var minuteDegrees;
if (!time || !time.label) {
clock.element.classList.add("is-unavailable");
return false;
}
hourDegrees = ((time.hour % 12) + (time.minute / 60)) * 30;
minuteDegrees = time.minute * 6;
clock.element.classList.remove("is-unavailable");
clock.timeElement.textContent = time.label;
clock.hourHand.style.transform = "translateX(-50%) rotate(" + hourDegrees + "deg)";
clock.minuteHand.style.transform = "translateX(-50%) rotate(" + minuteDegrees + "deg)";
if (clock.labelElement) {
clock.labelElement.textContent = clock.label;
}
if (clock.zoneElement) {
clock.zoneElement.textContent = formatTimezoneLabel(clock.timezone);
}
clock.element.setAttribute("aria-label", clock.label + " : " + time.label + " " + formatTimezoneLabel(clock.timezone));
return true;
}
function refreshClocks() {
clocks = clocks.filter(function (clock) {
if (!clock.element || !clock.element.parentNode) {
return false;
}
return updateClock(clock);
});
if (!clocks.length && clockTimer) {
window.clearInterval(clockTimer);
clockTimer = null;
}
}
function registerAnalogClock(element, timezone, label) {
var clock;
if (!element || !timezone) {
return;
}
clock = {
element: element,
timezone: timezone,
label: label || element.getAttribute("data-mas-clock-label") || "Heure locale",
timeElement: element.querySelector("[data-mas-clock-time]"),
labelElement: element.querySelector("p[data-mas-clock-label]"),
zoneElement: element.querySelector("[data-mas-clock-zone]"),
hourHand: element.querySelector("[data-mas-clock-hour]"),
minuteHand: element.querySelector("[data-mas-clock-minute]")
};
if (!clock.timeElement || !clock.hourHand || !clock.minuteHand) {
return;
}
clocks = clocks.filter(function (registeredClock) {
return registeredClock.element !== element;
});
clocks.push(clock);
updateClock(clock);
if (!clockTimer) {
clockTimer = window.setInterval(refreshClocks, 60000);
}
}
function createCityClockController(section) {
var root = section ? section.querySelector("[data-mas-city-clocks]") : null;
var destinationClock = root ? root.querySelector("[data-mas-city-clock='destination']") : null;
var referenceClock = root ? root.querySelector("[data-mas-city-clock='reference']") : null;
var destinationReady = false;
if (!root) {
return null;
}
if (referenceClock) {
registerAnalogClock(
referenceClock,
referenceClock.getAttribute("data-mas-clock-timezone"),
referenceClock.getAttribute("data-mas-clock-label") || "Geneve"
);
}
return {
registerDestination: function (cityName, timezone) {
if (destinationReady || !destinationClock || !timezone) {
return;
}
destinationReady = true;
registerAnalogClock(destinationClock, timezone, cityName || "Destination");
}
};
}
function getCityOverviewMarker() {
var marker = document.querySelector(".MoveAndStudyCore.MoveAndStudyCore-city .mas-city-map__markers [data-city][data-lat][data-lng]");
if (!marker) {
return null;
}
return {
title: marker.getAttribute("data-city") || "",
latitude: marker.getAttribute("data-lat"),
longitude: marker.getAttribute("data-lng")
};
}
function setFallback(panel, cityName) {
panel.classList.add("is-unavailable");
panel.classList.remove("is-ready");
panel.innerHTML = [
'<p class="mas-city-weather__eyebrow">Météo locale</p>',
'<p class="mas-city-weather__current"><span class="mas-city-weather__icon" aria-hidden="true">' + weatherIconSvg("variable") + '</span><span class="mas-city-weather__summary">Prévisions indisponibles</span></p>',
'<p class="mas-city-weather__fallback">Consultez la destination ' + escapeHtml(cityName || "sélectionnée") + ' pour préparer votre séjour.</p>'
].join("");
}
function renderWeather(panel, cityName, data) {
var current = data.current || {};
var daily = data.daily || {};
var summary = weatherSummary(current.weather_code);
var dates = (daily.time || []).slice(0, 4);
var highs = daily.temperature_2m_max || [];
var lows = daily.temperature_2m_min || [];
var codes = daily.weather_code || [];
var forecast = dates.map(function (date, index) {
var daySummary = weatherSummary(codes[index]);
return [
'<div class="mas-city-weather__day">',
'<div class="mas-city-weather__day-meta">',
'<span class="mas-city-weather__day-label">' + escapeHtml(formatDay(date, index)) + '</span>',
'<span class="mas-city-weather__day-icon" aria-hidden="true">' + weatherIconSvg(daySummary.iconKey) + '</span>',
'</div>',
'<strong class="mas-city-weather__day-temp">' + escapeHtml(formatTemperature(lows[index])) + '/' + escapeHtml(formatTemperature(highs[index])) + '</strong>',
'</div>'
].join("");
}).join("");
var updated = formatUpdated(current.time);
panel.classList.add("is-ready");
panel.classList.remove("is-unavailable");
panel.innerHTML = [
'<p class="mas-city-weather__eyebrow">Météo à ' + escapeHtml(cityName) + '</p>',
'<p class="mas-city-weather__current">',
'<span class="mas-city-weather__icon" aria-hidden="true">' + weatherIconSvg(summary.iconKey) + '</span>',
'<span class="mas-city-weather__summary">' + escapeHtml(formatTemperature(current.temperature_2m)) + ' aujourd’hui, ' + escapeHtml(summary.label.toLowerCase()) + '</span>',
'</p>',
'<div class="mas-city-weather__forecast">' + forecast + '</div>',
updated ? '<p class="mas-city-weather__updated">Mise à jour à ' + escapeHtml(updated) + '</p>' : ''
].join("");
}
function getWeatherCacheKey(marker) {
var latitude = Math.round(parseFloat(marker.latitude) * 1000) / 1000;
var longitude = Math.round(parseFloat(marker.longitude) * 1000) / 1000;
return "mas.weather." + latitude + "." + longitude + "." + new Date().toISOString().slice(0, 13);
}
function getCachedJson(cacheKey) {
var stored;
var parsed;
try {
stored = window.sessionStorage && window.sessionStorage.getItem(cacheKey);
if (!stored) {
return null;
}
parsed = JSON.parse(stored);
if (!parsed || !parsed.createdAt || (Date.now() - parsed.createdAt) > cacheLifetime) {
window.sessionStorage.removeItem(cacheKey);
return null;
}
return parsed.payload || null;
} catch (error) {
return null;
}
}
function setCachedJson(cacheKey, payload) {
try {
if (window.sessionStorage) {
window.sessionStorage.setItem(cacheKey, JSON.stringify({
createdAt: Date.now(),
payload: payload
}));
}
} catch (error) {
return;
}
}
function fetchWeather(url, cacheKey) {
var cached = getCachedJson(cacheKey);
if (cached) {
return Promise.resolve(cached);
}
return window.fetch(url)
.then(function (response) {
if (!response.ok) {
throw new Error("Weather unavailable");
}
return response.json();
})
.then(function (data) {
setCachedJson(cacheKey, data);
return data;
});
}
function hydrateCityOverview(section) {
var panel = section ? section.querySelector("[data-mas-city-weather]") : null;
var marker = getCityOverviewMarker();
var cityClockController = createCityClockController(section);
var cityName = marker ? marker.title : "";
var url;
if (!panel || !marker || !window.fetch || !isFiniteNumber(marker.latitude) || !isFiniteNumber(marker.longitude)) {
if (panel) {
setFallback(panel, cityName);
}
return;
}
url = forecastUrl
+ "?latitude=" + encodeURIComponent(marker.latitude)
+ "&longitude=" + encodeURIComponent(marker.longitude)
+ "&current=temperature_2m,weather_code"
+ "&daily=weather_code,temperature_2m_max,temperature_2m_min"
+ "&forecast_days=4"
+ "&timezone=auto";
fetchWeather(url, getWeatherCacheKey(marker))
.then(function (data) {
if (cityClockController) {
cityClockController.registerDestination(cityName, data.timezone);
}
renderWeather(panel, cityName, data);
})
.catch(function () {
setFallback(panel, cityName);
});
}
onReady(function () {
var cityOverview = document.querySelector(".MoveAndStudyCore.MoveAndStudyCore-city .mas-city-overview");
if (!cityOverview) {
return;
}
hydrateCityOverview(cityOverview);
});
}());
(function () {
function splitCityHeroTitle() {
var heroLead = document.querySelector(".MoveAndStudyCore-city .mas-city-hero__lead");
if (!heroLead) {
return;
}
var titleNode = heroLead.querySelector("h1");
if (!titleNode || titleNode.querySelector(".mas-city-hero__title-main")) {
return;
}
var rawTitle = (titleNode.textContent || "").replace(/\s+/g, " ").trim();
if (!rawTitle) {
return;
}
var splitIndex = -1;
var splitPattern = /\s[àa]\s+/ig;
var match;
while ((match = splitPattern.exec(rawTitle)) !== null) {
splitIndex = match.index;
}
if (splitIndex <= 0) {
return;
}
var mainTitle = rawTitle.slice(0, splitIndex).trim();
var placeTitle = rawTitle.slice(splitIndex + 1).trim();
if (!mainTitle || !/^[àa]\s+\S+/i.test(placeTitle)) {
return;
}
var mainSpan = document.createElement("span");
mainSpan.className = "mas-city-hero__title-main";
mainSpan.textContent = mainTitle;
var placeSpan = document.createElement("span");
placeSpan.className = "mas-city-hero__title-place";
placeSpan.textContent = placeTitle;
titleNode.textContent = "";
titleNode.appendChild(mainSpan);
titleNode.appendChild(document.createElement("br"));
titleNode.appendChild(placeSpan);
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", splitCityHeroTitle);
} else {
splitCityHeroTitle();
}
})();
(function () {
function onReady(callback) {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", callback);
return;
}
callback();
}
function hideEmptyAccreditations() {
var accreditations = document.getElementById("school-accreditations");
if (!accreditations) {
return;
}
var component = accreditations.querySelector(".Component-Container");
if (component && component.innerHTML.trim() === "") {
accreditations.style.display = "none";
}
}
function disableMapScroll() {
if (
typeof window.gmapstraction === "object" &&
window.gmapstraction.maps &&
window.gmapstraction.maps.google &&
typeof window.gmapstraction.maps.google.disableScrollWheelZoom === "function"
) {
window.gmapstraction.maps.google.disableScrollWheelZoom();
}
}
var googleMapsCallbacks = [];
var googleMapsFailureCallbacks = [];
var googleMapsLoading = false;
var googleMapsTimeoutId = null;
var googleMapsCallbackName = "__masSchoolPageGoogleMapsReady";
var holidayTooltipsReady = false;
function flushGoogleMapsCallbacks() {
var callbacks = googleMapsCallbacks.slice();
googleMapsCallbacks = [];
callbacks.forEach(function (readyCallback) {
readyCallback();
});
}
function flushGoogleMapsFailureCallbacks() {
var callbacks = googleMapsFailureCallbacks.slice();
googleMapsFailureCallbacks = [];
callbacks.forEach(function (failureCallback) {
failureCallback();
});
}
function resetGoogleMapsLoader() {
googleMapsLoading = false;
if (googleMapsTimeoutId) {
window.clearTimeout(googleMapsTimeoutId);
googleMapsTimeoutId = null;
}
}
function loadGoogleMaps(key, callback, failureCallback) {
if (window.google && window.google.maps && typeof window.google.maps.Map === "function") {
callback();
return;
}
googleMapsCallbacks.push(callback);
if (typeof failureCallback === "function") {
googleMapsFailureCallbacks.push(failureCallback);
}
if (googleMapsLoading || !key) {
return;
}
googleMapsLoading = true;
function fail() {
resetGoogleMapsLoader();
googleMapsCallbacks = [];
flushGoogleMapsFailureCallbacks();
}
window.gm_authFailure = fail;
window[googleMapsCallbackName] = function () {
if (!(window.google && window.google.maps && typeof window.google.maps.Map === "function")) {
fail();
return;
}
resetGoogleMapsLoader();
flushGoogleMapsCallbacks();
};
var script = document.createElement("script");
script.src = "https://maps.googleapis.com/maps/api/js?key=" + encodeURIComponent(key) +
"&callback=" + encodeURIComponent(googleMapsCallbackName) +
"&loading=async";
script.async = true;
script.defer = true;
script.onerror = fail;
document.head.appendChild(script);
googleMapsTimeoutId = window.setTimeout(fail, 10000);
}
function escapeHtml(value) {
return String(value || "")
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
function getNumberAttribute(element, name, fallback) {
var value = parseFloat(element.getAttribute(name));
return isFinite(value) ? value : fallback;
}
function hydrateSchoolMapFrames() {
var components = Array.prototype.slice.call(document.querySelectorAll("[data-mas-school-map][data-map-key][data-map-lat][data-map-lng]"));
components.forEach(function (component) {
var frame = component.querySelector(".mas-school-map__iframe");
var key = component.getAttribute("data-map-key") || "";
var lat = component.getAttribute("data-map-lat") || "";
var lng = component.getAttribute("data-map-lng") || "";
var zoom = component.getAttribute("data-map-zoom") || "14";
var mapSrc = "";
if (!frame || !key || !lat || !lng) {
return;
}
mapSrc = "/synergee/Themes/MoveAndStudyCore/Components/InteractiveMap/Iframe/InteractiveMap.html" +
"?key=" + encodeURIComponent(key) +
"&lat=" + encodeURIComponent(lat) +
"&lng=" + encodeURIComponent(lng) +
"&zoom=" + encodeURIComponent(zoom);
if (frame.getAttribute("src") === mapSrc) {
return;
}
frame.setAttribute("src", mapSrc);
});
}
function renderSchoolStreetView(component) {
var canvas = component.querySelector("[data-mas-school-streetview-canvas]");
var lat = getNumberAttribute(component, "data-latitude", null);
var lng = getNumberAttribute(component, "data-longitude", null);
if (!canvas || component.getAttribute("data-mas-school-streetview-ready") === "1" || lat === null || lng === null) {
return;
}
new google.maps.StreetViewPanorama(canvas, {
position: { lat: lat, lng: lng },
pov: {
heading: getNumberAttribute(component, "data-heading", 0),
pitch: getNumberAttribute(component, "data-pitch", 0)
},
zoom: getNumberAttribute(component, "data-zoom", 1),
addressControl: false,
fullscreenControl: true,
linksControl: true,
panControl: true,
enableCloseButton: false
});
component.setAttribute("data-mas-school-streetview-ready", "1");
}
function initSchoolLocationComponents() {
var streetViewComponents = Array.prototype.slice.call(document.querySelectorAll("[data-mas-school-streetview]"));
var key = "";
hydrateSchoolMapFrames();
if (!streetViewComponents.length) {
return;
}
streetViewComponents.some(function (component) {
key = component.getAttribute("data-mas-google-key") || "";
return Boolean(key);
});
loadGoogleMaps(
key,
function () {
streetViewComponents.forEach(function (component) {
renderSchoolStreetView(component);
});
},
function () {}
);
}
function hideBookingCart() {
if (!window.jQuery) {
return;
}
window.jQuery(".Synergee-Web-Page-Component-Booking-Cart").addClass("hidden");
}
function initHolidayTooltips() {
var chips = Array.prototype.slice.call(document.querySelectorAll("[data-mas-holiday-chip]"));
if (!chips.length || holidayTooltipsReady) {
return;
}
holidayTooltipsReady = true;
var isCoarsePointer = typeof window.matchMedia === "function" &&
window.matchMedia("(hover: none), (pointer: coarse)").matches;
function setExpandedState(chip, expanded) {
var trigger = chip.querySelector("[data-mas-holiday-trigger]");
var tooltip = chip.querySelector("[data-mas-holiday-tooltip]");
chip.classList.toggle("is-active", expanded);
if (trigger) {
trigger.setAttribute("aria-expanded", expanded ? "true" : "false");
}
if (tooltip) {
tooltip.setAttribute("aria-hidden", expanded ? "false" : "true");
}
}
function closeAll(exceptChip) {
chips.forEach(function (chip) {
if (chip !== exceptChip) {
setExpandedState(chip, false);
}
});
}
chips.forEach(function (chip) {
var trigger = chip.querySelector("[data-mas-holiday-trigger]");
if (!trigger) {
return;
}
trigger.addEventListener("click", function (event) {
var isExpanded = chip.classList.contains("is-active");
event.preventDefault();
closeAll(chip);
setExpandedState(chip, !isExpanded);
});
chip.addEventListener("mouseenter", function () {
if (isCoarsePointer) {
return;
}
closeAll(chip);
setExpandedState(chip, true);
});
chip.addEventListener("mouseleave", function () {
if (isCoarsePointer) {
return;
}
if (!chip.contains(document.activeElement)) {
setExpandedState(chip, false);
}
});
chip.addEventListener("focusin", function () {
closeAll(chip);
setExpandedState(chip, true);
});
chip.addEventListener("focusout", function () {
window.setTimeout(function () {
if (!chip.contains(document.activeElement)) {
setExpandedState(chip, false);
}
}, 0);
});
});
document.addEventListener("click", function (event) {
var clickedInside = chips.some(function (chip) {
return chip.contains(event.target);
});
if (!clickedInside) {
closeAll();
}
});
document.addEventListener("keydown", function (event) {
if (event.key !== "Escape") {
return;
}
closeAll();
});
}
function revealBookingCartWhenReady() {
if (!window.jQuery || !window.bookingManager || !window.bookingManager.booking) {
return;
}
if (typeof window.bookingManager.booking.addEvent === "function") {
window.bookingManager.booking.addEvent("onPriceRefreshComplete", function () {
window.jQuery(".Synergee-Web-Page-Component-Booking-Cart").removeClass("hidden");
});
}
}
function initSchoolMediaSlider() {
var slider = document.querySelector("[data-mas-school-media-slider]");
if (!slider || slider.getAttribute("data-mas-school-media-ready") === "1") {
return;
}
var rawSlides = Array.prototype.slice.call(slider.querySelectorAll("[data-mas-school-media-item]"));
var slides = rawSlides.filter(function (slide) {
var image = slide.querySelector("img");
var video = slide.querySelector(".Synergee-Web-Page-Component-Video-PlayVideoButton[href]");
if (!image && !video) {
slide.classList.add("is-empty");
slide.setAttribute("aria-hidden", "true");
return false;
}
return true;
});
if (!slides.length) {
slider.classList.add("is-empty");
return;
}
slider.setAttribute("data-mas-school-media-ready", "1");
var previous = slider.querySelector("[data-mas-school-media-prev]");
var next = slider.querySelector("[data-mas-school-media-next]");
var controls = slider.querySelector("[data-mas-school-media-controls]");
var status = slider.querySelector("[data-mas-school-media-status]");
var dotsContainer = slider.querySelector("[data-mas-school-media-dots]");
var hideDots = slider.getAttribute("data-mas-school-media-hide-dots") === "1";
var dots = [];
var current = 0;
function getSlideLabel(slide, index) {
var videoText = slide.querySelector(".school-gallery-video-txt");
var image = slide.querySelector("img");
var text = "";
if (videoText) {
text = videoText.textContent || "";
}
if (!text && image) {
text = image.getAttribute("alt") || "";
}
text = text.replace(/\s+/g, " ").trim();
if (text) {
return text;
}
return (slide.getAttribute("data-mas-media-kind") === "video" ? "Video " : "Photo ") + (index + 1);
}
function setFocusable(slide, enabled) {
var focusables = slide.querySelectorAll("a, button, input, select, textarea, [tabindex]");
Array.prototype.forEach.call(focusables, function (element) {
element.setAttribute("tabindex", enabled ? "0" : "-1");
});
if (slide.matches("a")) {
slide.setAttribute("tabindex", enabled ? "0" : "-1");
}
}
function showSlide(index) {
current = (index + slides.length) % slides.length;
slides.forEach(function (slide, slideIndex) {
var active = slideIndex === current;
slide.classList.toggle("is-active", active);
slide.setAttribute("aria-hidden", active ? "false" : "true");
setFocusable(slide, active);
});
dots.forEach(function (dot, dotIndex) {
var active = dotIndex === current;
dot.classList.toggle("is-active", active);
dot.setAttribute("aria-current", active ? "true" : "false");
});
if (status) {
status.textContent = (current + 1) + " / " + slides.length;
}
}
if (dotsContainer && !hideDots) {
dotsContainer.innerHTML = "";
slides.forEach(function (slide, index) {
var dot = document.createElement("button");
var kind = slide.getAttribute("data-mas-media-kind");
dot.type = "button";
dot.className = "mas-school-media-slider__dot";
if (kind === "video") {
dot.className += " mas-school-media-slider__dot--video";
}
dot.textContent = String(index + 1);
dot.setAttribute("aria-label", "Afficher " + getSlideLabel(slide, index));
dot.addEventListener("click", function () {
showSlide(index);
});
dotsContainer.appendChild(dot);
dots.push(dot);
});
} else if (dotsContainer) {
dotsContainer.setAttribute("hidden", "hidden");
}
if (previous) {
previous.addEventListener("click", function () {
showSlide(current - 1);
});
}
if (next) {
next.addEventListener("click", function () {
showSlide(current + 1);
});
}
slider.addEventListener("keydown", function (event) {
if (event.key === "ArrowLeft") {
event.preventDefault();
showSlide(current - 1);
}
if (event.key === "ArrowRight") {
event.preventDefault();
showSlide(current + 1);
}
});
if (controls && slides.length > 1) {
controls.hidden = false;
}
slider.classList.add("is-ready");
showSlide(0);
}
onReady(function () {
var galleryToggle = document.querySelector("[data-mas-school-gallery-toggle]");
var galleryToggleContainer = document.getElementById("gallery-btn-container");
var gallery = document.getElementById("school-gallery");
hydrateSchoolMapFrames();
if (galleryToggle && gallery) {
galleryToggle.addEventListener("click", function () {
gallery.classList.toggle("clicked");
if (galleryToggleContainer) {
galleryToggleContainer.classList.toggle("active");
}
});
}
initSchoolMediaSlider();
initSchoolLocationComponents();
initHolidayTooltips();
hideEmptyAccreditations();
window.setTimeout(hideEmptyAccreditations, 400);
hideBookingCart();
revealBookingCartWhenReady();
});
if (typeof window.addEvent === "function") {
window.addEvent("domready", function () {
hydrateSchoolMapFrames();
initSchoolMediaSlider();
initSchoolLocationComponents();
initHolidayTooltips();
hideEmptyAccreditations();
hideBookingCart();
revealBookingCartWhenReady();
});
window.addEvent("mapInitialized", disableMapScroll);
}
}());
(function () {
var DEFAULT_CHAT_WIDGET_URL = "https://chat.selvix-test.ch/widget?sourceSite=moveandstudy&language=fr";
var CHAT_WIDGET_URL = "";
if (typeof window.CHAT_WIDGET_URL === "string") {
CHAT_WIDGET_URL = window.CHAT_WIDGET_URL.replace(/^\s+|\s+$/g, "");
}
if (!CHAT_WIDGET_URL) {
CHAT_WIDGET_URL = DEFAULT_CHAT_WIDGET_URL;
}
window.CHAT_WIDGET_URL = CHAT_WIDGET_URL;
function onReady(callback) {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", callback);
return;
}
callback();
}
function detectPageType() {
var body = document.body;
var classes;
var i;
var className;
var prefix = "MoveAndStudyCore-";
if (!body) {
return "";
}
if (body.dataset && body.dataset.pageType) {
return body.dataset.pageType;
}
classes = (body.className || "").split(/\s+/);
for (i = 0; i < classes.length; i += 1) {
className = classes[i];
if (className.indexOf(prefix) === 0) {
return className.substring(prefix.length);
}
}
return "";
}
function buildWidgetUrl(source) {
var url;
try {
url = new URL(source, window.location.href);
} catch (error) {
return "";
}
url.searchParams.set("lang", document.documentElement.lang || "");
url.searchParams.set("pageUrl", window.location.href);
url.searchParams.set("pageType", detectPageType());
return url.toString();
}
function bindChatWidget(root) {
var toggle = root.querySelector("[data-mas-chat-toggle]");
var panel = root.querySelector("[data-mas-chat-panel]");
var closeButton = root.querySelector("[data-mas-chat-close]");
var iframe = root.querySelector("[data-mas-chat-iframe]");
var fallback = root.querySelector("[data-mas-chat-fallback]");
var source = window.CHAT_WIDGET_URL || "";
var loaded = false;
var loadAttempted = false;
var loadTimeout = 0;
var unavailable = false;
if (!toggle || !panel || !iframe) {
return;
}
function clearUnavailableState() {
unavailable = false;
iframe.hidden = false;
if (fallback) {
fallback.hidden = true;
}
}
function setUnavailableState() {
unavailable = true;
iframe.hidden = true;
if (fallback) {
fallback.hidden = false;
}
}
function clearLoadTimeout() {
if (loadTimeout) {
window.clearTimeout(loadTimeout);
loadTimeout = 0;
}
}
if (!source) {
toggle.setAttribute("disabled", "disabled");
toggle.setAttribute("title", "Chat non configure");
return;
}
iframe.addEventListener("load", function () {
loaded = true;
clearLoadTimeout();
clearUnavailableState();
});
iframe.addEventListener("error", function () {
clearLoadTimeout();
setUnavailableState();
});
function openPanel() {
if (!loadAttempted) {
var resolvedSource = buildWidgetUrl(source);
if (!resolvedSource) {
return;
}
clearUnavailableState();
iframe.src = resolvedSource;
loadAttempted = true;
loadTimeout = window.setTimeout(function () {
if (!loaded) {
setUnavailableState();
}
}, 10000);
} else if (!loaded && unavailable) {
setUnavailableState();
}
panel.hidden = false;
toggle.setAttribute("aria-expanded", "true");
}
function closePanel() {
panel.hidden = true;
toggle.setAttribute("aria-expanded", "false");
}
toggle.addEventListener("click", function () {
if (panel.hidden) {
openPanel();
return;
}
closePanel();
});
if (closeButton) {
closeButton.addEventListener("click", closePanel);
}
document.addEventListener("keydown", function (event) {
if (event.key === "Escape" && !panel.hidden) {
closePanel();
toggle.focus();
}
});
document.addEventListener("click", function (event) {
if (panel.hidden) {
return;
}
if (!root.contains(event.target)) {
closePanel();
}
});
}
onReady(function () {
var chatWidgets = document.querySelectorAll("[data-mas-chat-widget]");
var i;
for (i = 0; i < chatWidgets.length; i += 1) {
bindChatWidget(chatWidgets[i]);
}
});
}());
/*
* The Booking component uses MooTools class keys from newer versions
* (Extends / Implements), while MoveAndStudyCore serves MooTools 1.12.
* Normalize those keys before the Booking classes are defined.
*/
(function() {
if (!window.Class || Class.__masBookingMooTools12Compat) {
return;
}
var NativeClass = Class;
var normalizeMixins = function(mixins) {
if (!mixins) {
return [];
}
return ($type(mixins) == 'array') ? mixins : [mixins];
};
var applyMixin = function(klass, mixin) {
if (!mixin) {
return;
}
klass.implement(mixin.prototype ? new mixin() : mixin);
};
var BookingCompatibleClass = function(definition) {
definition = definition || {};
var parent = definition.Extends || null;
var mixins = definition.Implements || null;
if (!parent && !mixins) {
return new NativeClass(definition);
}
var normalizedDefinition = {};
for (var key in definition) {
if (key != 'Extends' && key != 'Implements') {
normalizedDefinition[key] = definition[key];
}
}
var klass = parent && parent.extend ? parent.extend(normalizedDefinition) : new NativeClass(normalizedDefinition);
normalizeMixins(mixins).each(function(mixin) {
applyMixin(klass, mixin);
});
return klass;
};
$extend(BookingCompatibleClass, NativeClass);
BookingCompatibleClass.prototype = NativeClass.prototype;
BookingCompatibleClass.empty = NativeClass.empty;
BookingCompatibleClass.Merge = NativeClass.Merge;
BookingCompatibleClass.__masBookingMooTools12Compat = true;
window.Class = BookingCompatibleClass;
if (window.Fx && !Fx.Tween && Fx.Style) {
Fx.Tween = new NativeClass({
initialize: function(element, options) {
this.element = $(element);
this.options = options || {};
this.property = this.options.property || 'opacity';
this.fx = new Fx.Style(this.element, this.property, this.options);
},
start: function(from, to) {
if (!this.fx) {
return this;
}
if (this.options.onStart) {
this.options.onStart();
}
if (arguments.length > 1) {
this.fx.start(from, to);
} else {
this.fx.start(from);
}
return this;
},
set: function(value) {
if (this.fx && this.fx.set) {
this.fx.set(value);
} else if (this.element) {
this.element.setStyle(this.property, value);
}
return this;
},
cancel: function() {
if (this.fx && this.fx.cancel) {
this.fx.cancel();
}
return this;
}
});
}
if (window.Fx && !Fx.Morph && Fx.Styles) {
Fx.Morph = new NativeClass({
initialize: function(element, options) {
this.element = $(element);
this.fx = new Fx.Styles(this.element, options || {});
},
start: function(styles) {
if (this.fx) {
this.fx.start(styles || {});
}
return this;
},
chain: function(callback) {
if (this.fx && this.fx.chain) {
this.fx.chain(callback);
} else if (callback) {
callback.call(this);
}
return this;
},
set: function(styles) {
if (this.element && styles) {
this.element.setStyles(styles);
}
return this;
},
cancel: function() {
if (this.fx && this.fx.cancel) {
this.fx.cancel();
}
return this;
}
});
}
if (window.Element && Element.extend && Element.implement && !Element.__masBookingImplementCompat) {
var nativeElementImplement = Element.implement;
Element.implement = function(methods) {
Element.extend(methods || {});
return nativeElementImplement.apply(this, arguments);
};
Element.__masBookingImplementCompat = true;
}
if (window.Element && !$(document.createElement('div')).store) {
var elementStorage = {};
var elementStorageUid = 1;
var getStorage = function(element) {
var uid = element.uid || (window.$uid ? $uid(element) : null);
if (!uid) {
uid = element.__masBookingStorageUid || (element.__masBookingStorageUid = 'mas-booking-' + elementStorageUid++);
}
if (!elementStorage[uid]) {
elementStorage[uid] = {};
}
return elementStorage[uid];
};
var storageMethods = {
store: function(key, value) {
getStorage(this)[key] = value;
return this;
},
retrieve: function(key, defaultValue) {
var storage = getStorage(this);
return (key in storage) ? storage[key] : defaultValue;
},
eliminate: function(key) {
delete getStorage(this)[key];
return this;
}
};
if (Element.extend) {
Element.extend(storageMethods);
} else if (Element.implement) {
Element.implement(storageMethods);
}
var nativeElementSet = Element.prototype.set;
var elementAccessors = {
get: function(key) {
switch (key) {
case 'tag':
return this.getTag();
case 'html':
return this.innerHTML;
case 'text':
return this.getText();
default:
return this.getProperty(key);
}
},
set: function(key, value) {
if ($type(key) == 'object') {
return nativeElementSet.call(this, key);
}
switch (key) {
case 'html':
return this.setHTML(value);
case 'text':
return this.setText(value);
default:
return this.setProperty(key, value);
}
},
grab: function(element, where) {
element = $(element);
if (element) {
element.inject(this, where);
}
return this;
}
};
if (Element.extend) {
Element.extend(elementAccessors);
} else if (Element.implement) {
Element.implement(elementAccessors);
}
}
if (window.Element && Element.extend && !$(document.createElement('div')).getHeight) {
Element.extend({
getHeight: function() {
var size = this.getSize ? this.getSize() : null;
return size && size.size ? size.size.y : this.offsetHeight;
}
});
}
if (!window.SynergeeTips && window.Tips) {
window.SynergeeTips = window.Tips;
}
if ((!window.Request || !window.Request.prototype || !window.Request.prototype.send) && window.XMLHttpRequest) {
window.Request = function(options) {
this.options = options || {};
this.xhr = null;
this.running = false;
};
window.Request.prototype.send = function(data) {
var method = (this.options.method || 'post').toUpperCase();
var url = this.options.url;
var body = data || this.options.data || null;
var xhr = this.xhr = new XMLHttpRequest();
var self = this;
if (method == 'GET' && body) {
url += (url.indexOf('?') == -1 ? '?' : '&') + body;
body = null;
}
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) {
return;
}
self.running = false;
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 0) {
if (self.options.onSuccess) {
self.options.onSuccess(xhr.responseText, xhr.responseXML);
}
} else if (self.options.onFailure) {
self.options.onFailure(xhr);
}
};
if (this.options.onRequest) {
this.options.onRequest();
}
this.running = true;
xhr.open(method, url, this.options.async !== false);
if (method != 'GET') {
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
}
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.send(body);
return this;
};
window.Request.prototype.cancel = function() {
if (this.xhr && this.running) {
this.xhr.abort();
this.running = false;
}
return this;
};
}
if (!window.Browser) {
window.Browser = {
ie: !!window.ie,
ie6: !!window.ie6,
ie7: !!window.ie7,
webkit: !!window.webkit,
gecko: !!window.gecko,
Engine: {
trident: !!window.ie,
webkit: !!window.webkit,
gecko: !!window.gecko
}
};
}
if (!window.Locale) {
window.Locale = {
get: function(key) {
if (key == 'Chosen.noResults') {
return 'Aucun résultat pour';
}
return key;
}
};
}
if (document && !document.id) {
document.id = function(element) {
return $(element);
};
}
if (!String.uniqueID) {
var uniqueId = 0;
String.uniqueID = function() {
return 'mas-booking-' + (++uniqueId);
};
}
if (window.Events && Events.prototype && !Events.prototype.removeEvents) {
Events.prototype.removeEvents = function(type) {
if (!this.$events) {
return this;
}
if (type) {
delete this.$events[type];
} else {
this.$events = {};
}
return this;
};
}
if (window.Json) {
window.JSON = window.JSON || {};
if (!JSON.encode && Json.toString) {
JSON.encode = function(value) {
return Json.toString(value);
};
}
if (!JSON.decode && Json.evaluate) {
JSON.decode = function(value, secure) {
return Json.evaluate(value, secure);
};
}
}
if (!Object.filter) {
Object.filter = function(object, callback, bind) {
var result = {};
for (var key in object) {
if (Object.prototype.hasOwnProperty.call(object, key) && callback.call(bind, object[key], key, object)) {
result[key] = object[key];
}
}
return result;
};
}
if (!Object.map) {
Object.map = function(object, callback, bind) {
var result = {};
for (var key in object) {
if (Object.prototype.hasOwnProperty.call(object, key)) {
result[key] = callback.call(bind, object[key], key, object);
}
}
return result;
};
}
if (!Object.values) {
Object.values = function(object) {
var result = [];
for (var key in object) {
if (Object.prototype.hasOwnProperty.call(object, key)) {
result.push(object[key]);
}
}
return result;
};
}
if (window.Hash && Hash.prototype) {
if (!Hash.prototype.has && Hash.prototype.hasKey) {
Hash.prototype.has = function(key) {
return this.hasKey(key);
};
}
if (!Hash.prototype.erase && Hash.prototype.remove) {
Hash.prototype.erase = function(key) {
return this.remove(key);
};
}
if (!Hash.prototype.getKeys && Hash.prototype.keys) {
Hash.prototype.getKeys = function() {
return this.keys();
};
}
if (!Hash.prototype.getValues && Hash.prototype.values) {
Hash.prototype.getValues = function() {
return this.values();
};
}
}
if (!Array.prototype.has && Array.prototype.contains) {
Array.extend({
has: function(item) {
return this.contains(item);
},
erase: function(item) {
var index = this.indexOf(item);
while (index != -1) {
this.splice(index, 1);
index = this.indexOf(item);
}
return this;
},
combine: function(items) {
return this.merge(items || []);
}
});
}
})();
/**
* 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 Booking = Events.extend({
var BookingEngine = new Class({
Implements: [Events, Options],
options: {
shoppingCartPage: false, // True if it's a shopping cart page
input: $('bookingOption'), // The input block
output: $('bookingCart'), // The ouput block
schoolsSelectorContainer: $('schoolsSelector'), // The schools Selector Container
header: $('bookingLinks'), // the header block
printOutput: $("schoolPriceEstimationPrint"), // the print output div
courseTypeContainer : '',
accommodationTypeContainer : '',
insuranceContainer : '',
promotionIntroductionContainer : '',
promotionContainer : '',
onlyWebsiteSchools : false,
syncHeight : true
},
/**
* This is the initialization function
*/
initialize : function(options) {
this.setOptions(options);
this.bookingAutoInit = true;
this._customValues = new Hash();
this._selectedSchoolId = null;
this._schools = new Array();
this._courseTypesFilter = [];
this._levelFilter = 0;
if (window.location.href.indexOf('?') != -1) {
var params = window.location.href.substr(window.location.href.indexOf('?') + 1);
}
var me = this;
// translation request
this._xhrTranslateInit = new Request({
url : this.getBookingJsonUrl() + '&' + (params ? params + '&' : '') + 'step=initTranslations&onlyWebsiteSchools=' + (this.options.onlyWebsiteSchools ? 1 : 0) + '&shoppingCartPage=' + (this.options.shoppingCartPage ? 1 : 0),
onRequest: function() {
},
onSuccess: function(responseText) {
me.fireEvent('translaterequestsuccess', responseText);
this.initTranslations(responseText);
}.bind(this),
onFailure: function() {
}
}
);
// the ajax call to init the shopping cart
this._xhrInit = new Request(
{
url: this.getBookingJsonUrl(),
onRequest: function() {
},
onSuccess: function(responseText) {
this.initBooking(responseText);
}.bind(this),
onFailure: function() {
}
});
// the checkout request
this._xhrCheckout = new BookingRequest({
url : this.getBookingJsonUrl(),
onSuccess : function(responseText) {
this._displayOrderFormResult(responseText);
}.bind(this)
});
// the main request that will display the price estimation result
this._xhr = new Request({
url : this.getBookingJsonUrl(),
onRequest: function() {
},
onSuccess: function(responseText) {
this.displayPriceEstimation(responseText);
}.bind(this),
onFailure: function() {
}
});
},
/**
* Start the booking
*/
launch : function () {
// The Init call is made
this.fireEvent('onLauch');
this._xhrTranslateInit.send();
},
/**
* Return the json current url
* todo
*
* return string
*/
getBookingJsonUrl : function () {
//        return 'http://127.0.0.1/synergee/Sources/booking.html?componentName=Booking&componentId=informationText';
return 'http://192.168.1.202/synergee/Sources/booking.html?componentName=Booking&componentId=informationText';
},
/**
* called when a school is loaded
*
*
* @param e
*/
initBooking : function(e) {
eval(e);
//        this.schoolsContainer.empty();
if (typeof(getInit) == 'function') {
var initDTO = getInit();
this._schools = initDTO[0];
this._options = initDTO[2];
this._insurances = initDTO[3];
this._promotions = initDTO[4];
// The schools displayed in the shopping cart are stocked in
if(!this.schools)
this.schools = new Array();
// the menu item translations are set
if (this.options.widgetMode && this.options.shoppingCartPage) {
this.shoppingCartFirstItem.set("html", this._translateDTO.firstItem);
this.shoppingCartFirstItemName.set("html", this._translateDTO.yourShoppingCartMenuItem);
this.formLinkSecondItem.set("html", this._translateDTO.secondItem);
this.formLinkSecondItemName.set("html", this._translateDTO.formMenuItem);
this.confirmationLinkThirdItem.set("html", this._translateDTO.thirdItem);
this.confirmationLinkThirdItemName.set("html", this._translateDTO.confirmationMenuItem);
}
this.insurancesManager = new SchoolInsurances(this._insurances, this);
this.insurancesManager.addEvent('insurancesUpdated', this.refreshPrice.bind(this));
this.promotionsManager =  new SchoolPromotions(this._promotions, this);
this.promotionsManager.addEvent('promotionsUpdated', this.refreshPrice.bind(this));
var schools = [];
// if there is no school added in the shopping cart or the shopping cart is opened in the designer
if (this.options.widgetMode && (!this._schools.length || document.isInDesignMode())) {
if (this.options.shoppingCartPage) {
/* var emptyMessage = new Element('div', {'class': this._classNameBase + 'Empty'});
emptyMessage.set("html", this._translateDTO.empty);
emptyMessage.inject(this.schoolsContainer);*/
}
this.setSameColumnSize(this.options.input, this.options.output);
}
else {
for (var i = 0; i < this._schools.length; i++) {
this._schoolPriceCalculatorDTO = this._schools[i];
var school = new School(this._schools[i], this);
school.addEvent('refreshPrice', this.refreshPrice.bind(this));/*
if (this.options.widgetMode)
school.addEvent('heightModified', this.onHeightModified.bind(this));*/
schools.push(school);
this.schools.push(school);
}
this._oldDTO = JSON.encode(this.getDTO());
// The shopping cart is populated if there are some informations
/*    if (this.options.widgetMode){
this.populateFromDTO.delay(50, this, initDTO[1]);
this.retrieveSchoolItemsDescription();
}*/
}
this.fireEvent('initialized', [schools]);
}
},
getSchoolsSelector : function () {
return this.schoolSelector;
},
/**
* Return the schools
*
* @return School[] The added schools
*/
getSchools : function() {
return this.schools;
},
/**
* Return the insurances manager
*
* @return InsurancesManager The insurances manager
*/
getInsurancesManager : function() {
return this.insurancesManager;
},
/**
* Return the promotions manager
*
*
* @return PromotionsManager The promotions manager
*/
getPromotionsManager : function() {
return this.promotionsManager;
},
/**
* Return the schools DTO
*
* @return School[] The added schools
*/
getSchoolsDTO : function() {
return this._schools;
},
/**
* Refresh the price
*/
refreshPrice : function() {
if (this.options.shoppingCartPage) {
if (this.formLink.active) {
this.saveFormFields();
this.formLink.addClass(this._classNameBase + 'Links-Inactive');
this.formLink.active = false;
this.orderForm.initialized = false;
}
}
this.updateValues();
if (this._oldDTO != JSON.encode(this.getDTO())) {
this.fireEvent('onPriceRefresh');
var params = 'shoppingCartPage=' + this.options.shoppingCartPage;
if (this.options.promotionIntroductionContainer != '') params = params + '&pIntroContainer=' + this.options.promotionIntroductionContainer;
if (this.options.promotionContainer != '') params = params + '&pContainer=' + this.options.promotionContainer;
if (this._selectedSchoolId)params = params + '&schoolId=' + this._selectedSchoolId;
this._xhr.cancel();
this._xhr.send(params + '&format=json&dto=' + JSON.encode(this.getDTO()));
this._oldDTO = JSON.encode(this.getDTO());
}
},
loadSchool : function(schoolId, addSchool){
if(schoolId != this._selectedSchoolId){
if (!addSchool && this.schools) {
this.schools = new Array();
}
if (schoolId) {
this._xhr.cancel();
var xhrLoadSchool = new Request(
{
url: this.getBookingJsonUrl(),
onRequest: function() {
},
onSuccess: function(responseText) {
this.initBooking(responseText);
}.bind(this),
onFailure: function() {
}
});
var xhrParam = 'step=init';
xhrParam += '&schoolId=' + schoolId;
if(this.schools && this.schools.length && addSchool){
var loadedSchools = '';
for(var i = 0; i < this.schools.length; i++){
loadedSchools = loadedSchools + this.schools[i]._schoolDTO.schoolId + (i < this.schools.length-1 ? '|': '');
}
xhrParam += '&alreadyLoadedSchools=' + loadedSchools;
}
this._selectedSchoolId = schoolId;
this.updateSchoolContextBanner();
this.fireEvent('beforeschoolload', schoolId);
// send an ajax call to add the school
this.bookingAutoInit = false;
xhrLoadSchool.send(xhrParam);
}
}
},
/**
* called when the height of a column is modified so the two column are the same size
*
*/
onHeightModified : function (e) {
/*      if(this.options.widgetMode){
this.fireEvent('beforeHeightUpdated');
this.setSameColumnSize(this.options.input, this.options.output);
this.fireEvent('afterHeightUpdated');
}*/
},
/**
*
* create the shopping cart top links components
*
*/
createShoppingCartLinks : function() {
this.shoppingCartLink = new Element('div', {'class':  this._classNameBase + 'Links-Active'});
this.shoppingCartLink.inject(this.header);
this.shoppingCartLink.addEvent("click", this.displayShoppingCart.bind(this));
this.shoppingCartLink.active = true;
this.shoppingCartLink.addClass('Selected');
this.shoppingCartLink.addEvent("mouseenter", function() {
if (this.shoppingCartLink.active) {
this.shoppingCartLink.addClass(this._classNameBase + 'Links-Hover');
}
}.bind(this));
this.shoppingCartLink.addEvent("mouseleave", function() {
if (this.shoppingCartLink.active) {
this.shoppingCartLink.removeClass(this._classNameBase + 'Links-Hover');
}
}.bind(this));
this.shoppingCartFirstItem = new Element('div', {'class':  this._classNameBase + 'Links-Number'});
this.shoppingCartFirstItem.inject(this.shoppingCartLink);
this.shoppingCartFirstItemName = new Element('div', {'class':  this._classNameBase + 'Links-Name'});
this.shoppingCartFirstItemName.inject(this.shoppingCartLink);
// The form link
this.formLink = new Element('div', {'class':  this._classNameBase + 'Links-Active'});
this.formLink.inject(this.header);
this.formLink.addEvent("click", this._displayOrderForm.bind(this));
this.formLink.active = false;
this.formLink.removeClass('Selected');
this.formLinkSecondItem = new Element('div', {'class':  this._classNameBase + 'Links-Number'});
this.formLinkSecondItem.inject(this.formLink);
this.formLinkSecondItemName = new Element('div', {'class':  this._classNameBase + 'Links-Name'});
this.formLinkSecondItemName.inject(this.formLink);
this.formLink.addClass(this._classNameBase + 'Links-Inactive');
this.formLink.addEvent("mouseenter", function() {
if (this.formLink.active) {
this.formLink.addClass(this._classNameBase + 'Links-Hover');
}
}.bind(this));
this.formLink.addEvent("mouseleave", function() {
if (this.formLink.active) {
this.formLink.removeClass(this._classNameBase + 'Links-Hover');
}
}.bind(this));
// The confirmation link
this.confirmationLink = new Element('div', {'class':  this._classNameBase + 'Links-Active'});
this.confirmationLink.inject(this.header);
this.confirmationLink.active = false;
this.confirmationLink.removeClass('Selected');
this.confirmationLinkThirdItem = new Element('div', {'class':  this._classNameBase + 'Links-Number'});
this.confirmationLinkThirdItem.inject(this.confirmationLink);
this.confirmationLinkThirdItemName = new Element('div', {'class':  this._classNameBase + 'Links-Name'});
this.confirmationLinkThirdItemName.inject(this.confirmationLink);
this.confirmationLink.addClass(this._classNameBase + 'Links-Inactive');
this.confirmationLink.addEvent("mouseenter", function() {
if (this.confirmationLink.active) {
this.confirmationLink.addClass(this._classNameBase + 'Links-Hover');
}
}.bind(this));
this.confirmationLink.addEvent("mouseleave", function() {
if (this.confirmationLink.active) {
this.confirmationLink.removeClass(this._classNameBase + 'Links-Hover');
}
}.bind(this));
},
initTranslations : function(e) {
eval(e);
if (typeof(getInit) == 'function') {
this._initDTO = getInit();
this._translateDTO = this._initDTO.translateDTO;
this.participants = new SchoolParticipants(this._translateDTO.participants, this._initDTO.multipleBooking, this);
this.currency = new SchoolCurrencySelector(this._translateDTO.currencies, this._initDTO.defaultCurrency, this._initDTO.websiteCurrencies, this);
this.currency.addEvent('refreshPrice', this.refreshPrice.bind(this));
this._currencyConversionEnabled = this._initDTO.currencyConversionEnabled;
if (!this.options.shoppingCartPage) {
this.schoolSelector = new SchoolSelector(this._translateDTO.schoolSelector, this._initDTO.schoolsList, this, this._initDTO.advancedSchoolList);
// when a school is selected
this.schoolSelector.addEvent('changeSchool', function() {
if (this.schoolSelector.getSelectedSchoolId()) {
this.loadSchool(this.schoolSelector.getSelectedSchoolId());
}
}.bind(this));
this.fireEvent('schoolsSelectorLoaded');
}
this.fireEvent('onTranslationsLoaded');
if (this.schoolSelector) {
if (this._initDTO.schoolsList.length == 1) {
this.schoolSelector.fireEvent('changeSchool');
} else {
this.schoolSelector.updateSelector(this._initDTO.selectedSchool, this._initDTO.selectedProgram, this._initDTO.selectedCountry, this._initDTO.selectedCity);
}
this.updateSchoolContextBanner();
}
}
},
hasSchoolContextParameter : function() {
return window.location.search && /(?:^\?|&)school=([^&]+)/.test(window.location.search);
},
getSelectedSchoolContext : function() {
if (!this.hasSchoolContextParameter() || !this.schoolSelector) {
return null;
}
var schoolId = this.schoolSelector.getSelectedSchoolId();
if (!schoolId) {
return null;
}
var school = null;
if (this.schoolSelector._schoolsHash && this.schoolSelector._schoolsHash.has(schoolId)) {
school = this.schoolSelector._schoolsHash.get(schoolId);
}
if (!school && this._initDTO && this._initDTO.schoolsList) {
for (var i = 0; i < this._initDTO.schoolsList.length; i++) {
if (String(this._initDTO.schoolsList[i].schoolId) == String(schoolId)) {
school = this._initDTO.schoolsList[i];
break;
}
}
}
if (!school || !school.schoolName) {
return null;
}
return {
id: school.schoolId,
name: school.schoolName,
city: school.schoolCityName || '',
country: school.schoolCountryName || ''
};
},
updateSchoolContextBanner : function() {
var banner = document.getElementById('mas-booking-school-context');
if (!banner) {
return;
}
var context = this.getSelectedSchoolContext();
var nameNode = banner.querySelector('[data-mas-booking-school-name]');
var locationNode = banner.querySelector('[data-mas-booking-school-location]');
if (!context || !nameNode || !locationNode) {
$(banner).addClass('is-hidden');
return;
}
nameNode.textContent = context.name;
locationNode.textContent = [context.city, context.country].filter(function(value) {
return !!value;
}).join(', ');
banner.setAttribute('data-school-id', context.id);
$(banner).removeClass('is-hidden');
},
/**
* return the translations
*/
getTranslations : function() {
if(this._translateDTO)
return this._translateDTO;
return null;
},
/**
* Called before the price is updated
*/
updateValues : function() {
if (this.insurancesManager) {
this.insurancesManager.refreshInsurances();
}
},
/**
* Send the request to refresh the price
*/
retrieveSchoolItemsDescription : function() {
this._schoolDescriptionsXHR = new Request({
url : window.getCurrentJsonUrl(this.options.input),
onRequest: function() {
},
onSuccess: function(e) {
this.schoolDescriptions = JSON.decode(e);
this.fireEvent('descriptionsUpdated');
}.bind(this),
onFailure: function() {
}
});
if (this.schools) {
var school = new Object();
school.courseTypeContainer = this.options.courseTypeContainer ? this.options.courseTypeContainer : null;
school.insuranceContainer = this.options.insuranceContainer ? this.options.insuranceContainer : null;
school.accommodationTypeContainer = this.options.accommodationTypeContainer ? this.options.accommodationTypeContainer : null;
school.courseTypes = new Array();
school.accommodationTypes = new Array();
school.insurances = new Array();
for (var j = 0; j < this.schools.length; j ++) {
// variable date course
for (var i = 0; i < this.schools[j]._schoolDTO.schoolVariableDatesCourses.length; i++) {
if (!school.courseTypes.contains(this.schools[j]._schoolDTO.schoolVariableDatesCourses[i]).courseTypeId) {
school.courseTypes.push(this.schools[j]._schoolDTO.schoolVariableDatesCourses[i].courseTypeId);
}
}
// fixed date course
for (var i = 0; i < this.schools[j]._schoolDTO.schoolFixedDatesCourses.length; i++) {
if (!school.courseTypes.contains(this.schools[j]._schoolDTO.schoolFixedDatesCourses[i]).courseTypeId) {
school.courseTypes.push(this.schools[j]._schoolDTO.schoolFixedDatesCourses[i].courseTypeId);
}
}
// optional course
for (var i = 0; i < this.schools[j]._schoolDTO.schoolOptionalCourses.length; i++) {
if (!school.courseTypes.contains(this.schools[j]._schoolDTO.schoolOptionalCourses[i]).courseTypeId) {
school.courseTypes.push(this.schools[j]._schoolDTO.schoolOptionalCourses[i].courseTypeId);
}
}
for (var i = 0; i < this.schools[j]._schoolDTO.schoolAccommodations.length; i++) {
if (!school.accommodationTypes.contains(this.schools[j]._schoolDTO.schoolAccommodations[i]).accommodationType) {
school.accommodationTypes.push(this.schools[j]._schoolDTO.schoolAccommodations[i].accommodationType);
}
}
if (this._insurances) {
for (var i = 0; i < this._insurances.length; i++) {
school.insurances.push(this._insurances[i].id);
}
}
}
this._schoolDescriptionsXHR.cancel();
this._schoolDescriptionsXHR.send('step=initDescriptions&schoolInfos=' + JSON.encode(school));
}
},
getSchoolDescriptions : function() {
if (this.schoolDescriptions)return this.schoolDescriptions;
return null;
},
/**
* Return the description for an item
*
* @param string descriptionType The type  course, accommodation, insurance
* @param integer id The item id
*/
getDescription : function(descriptionType, id) {
var descriptions = this.getSchoolDescriptions();
var description = null;
if (descriptions) {
switch (descriptionType) {
case 'course':
if (descriptions.courses[id]) {
description = descriptions.courses[id].description;
}
break;
case 'accommodation':
if (descriptions.accommodations[id]) {
description = descriptions.accommodations[id].description;
}
break;
case 'insurance':
if (descriptions.insurances[id]) {
description = descriptions.insurances[id].description;
}
break;
}
}
return description;
},
/**
* Return the description for an item
*
* @param string descriptionType The type  course, accommodation, insurance
* @param integer id The item id
*/
getDescriptionDetails : function(descriptionType, id) {
var descriptions = this.getSchoolDescriptions();
var description = null;
if (descriptions) {
switch (descriptionType) {
case 'course':
if (descriptions.courses[id]) {
description = descriptions.courses[id];
}
break;
case 'accommodation':
if (descriptions.accommodations[id]) {
description = descriptions.accommodations[id];
}
break;
case 'insurance':
if (descriptions.insurances[id]) {
description = descriptions.insurances[id];
}
break;
}
}
return description;
},
/**
* Set the level filter
* @param level
*/
setLevelFilter : function(level){
if(this._levelFilter != level){
this._levelFilter = level;
this.schools.each(function(item, index) {
item.courses.onCourseUpdated();
}.bind(this));
}
},
getLevelFilter : function(){
return this._levelFilter;
},
/**
* Set the course type filter
* @param courseTypes
*/
setCourseTypesFilter : function(courseTypes){
if(this._courseTypesFilter != courseTypes){
this._courseTypesFilter = courseTypes;
this.schools.each(function(item, index) {
item.courses.onCourseUpdated();
}.bind(this));
}
},
getCourseTypesFilter : function(){
return this._courseTypesFilter;
},
/**
* Return true if we are on a shopping cart page
*/
getIsShoppingCartPage : function () {
return this.options.shoppingCartPage;
},
/**
* Return the completed courses
*/
getCompletedCourses : function() {
var completedCourses = new Array();
this.schools.each(function(item, index) {
completedCourses = completedCourses.concat(item.getCompletedCourses());
}.bind(this));
return completedCourses;
},
/**
* return the completed accommodations
*/
getCompletedAccommodations : function() {
var completedAccommodations = new Array();
this.schools.each(function(item, index) {
completedAccommodations = completedAccommodations.concat(item.getCompletedAccommodations());
}.bind(this));
return completedAccommodations;
},
/**
* Return the quote start date
*
* @return Date the quote start date
*/
getStartDate : function() {
var startDate = null;
var courses = this.getCompletedCourses();
var accommodations = this.getCompletedAccommodations();
if (courses.length) {
startDate = courses[0].getCourseStartDate();
if (accommodations.length && accommodations[0].getAccommodationStartDate() < startDate) {
startDate = accommodations[0].getAccommodationStartDate();
}
}
return startDate;
},
/**
* Return the quote end date
*
* @return Date the quote end date
*/
getEndDate : function() {
var endDate = null;
var courses = this.getCompletedCourses();
var accommodations = this.getCompletedAccommodations();
if (courses.length) {
for (var i = 0; i < courses.length; i++) {
if (courses[i].getCourseDetails().type != 'optional' && courses[i].getCourseEndDate() > endDate) {
endDate = courses[i].getCourseEndDate();
}
}
if (accommodations.length) {
for (i = 0; i < accommodations.length; i++) {
if (accommodations[i].getAccommodationEndDate() > endDate) {
endDate = accommodations[i].getAccommodationEndDate();
}
}
}
}
return endDate;
},
/**
*  This method return the localized month translations
*
*  @return String[] The localized month translations
*/
getMonthTranslations : function() {
return this._translateDTO.months;
},
/**
* This method send an ajax call to get the generated form
*/
checkout : function() {
if (this.options.shoppingCartPage) {
var completedCourses = 0;
for (var i = 0; i < this.schools.length; i++) {
completedCourses += this.schools[i].getCompletedCourses().length;
}
if (completedCourses > 0) {
if (!this.orderForm.initialized) {
this.fireEvent('onCheckout');
this._xhrCheckout.send('step=checkout&dto=' + JSON.encode(this.getDTO()) + '&shoppingCartPage=' + this.options.shoppingCartPage);
}
else {
this._displayOrderForm();
}
}
}
},
/**
* Display the shopping cart
*
*/
displayShoppingCart : function() {
if (this.options.input.getStyle('display') == 'none') {
this.orderForm.setStyle('display', 'none');
this.orderConfirmation.setStyle('display', 'none');
this.confirmationLink.addClass(this._classNameBase + 'Links-Inactive');
this.confirmationLink.active = false;
this.shoppingCartLink.addClass('Selected');
this.formLink.removeClass('Selected');
this.confirmationLink.removeClass('Selected');
this.options.input.setStyle('display', 'block');
//            this.options.schoolsSelectorContainer.setStyle('display', 'block');
this._outputContainer.setStyle('display', 'block');
this.fireEvent('viewChanged', 'cart');
}
},
/**
* Display the result of the price estimation
*
*/
_displayOrderForm : function() {
if (this.formLink.active) {
if (!this._options.contactForm) $('formSameParticipantContainer').setStyle('display', 'none');
this.options.input.setStyle('display', 'none');
if (!this._displayOutput)this._outputContainer.setStyle('display', 'none');
this.confirmationLink.addClass(this._classNameBase + 'Links-Inactive');
this.confirmationLink.active = false;
this.formLink.addClass('Selected');
this.formLink.addClass('Selected');
this.shoppingCartLink.removeClass('Selected');
this.confirmationLink.removeClass('Selected');
this.orderConfirmation.setStyle('display', 'none');
//            this.options.schoolsSelectorContainer.setStyle('display', 'none');
this.orderForm.setStyle('display', 'block');
this.fireEvent('viewChanged', 'form');
}
else {
return false;
}
},
/**
* Display the result of the price estimation
*
* @param Event e The result of the price estimation
*/
displayPriceEstimation : function(e) {
if(this.options.widgetMode){
this.options.output.set("html", e);
this.onHeightModified();
var infos = this.options.output.getElements('.PromotionMoreInfos');
for (i = 0; i < infos.length; i++) {
new SynergeeTips(infos[i], {'className':'Booking-Tool-Tip Tool-tip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
}
}
// check if there are complete courses
var completedCourses = 0;
if(this.schools){
for (var i = 0; i < this.schools.length; i++) {
completedCourses += this.schools[i].getCompletedCourses().length;
}
}
if (completedCourses) {
if (e.replace(/^\s+|\s+$/g, '') == "") {
this.fireEvent.delay(100, this, 'refreshPrice');
}
else {
if (this.options.shoppingCartPage) {
$('bookingCheckoutButton').setStyle('visibility', '');
}
}
}
this.fireEvent('onPriceRefreshComplete', e);
},
/**
* Display the order form with the ajax call
*
* @param Event e The result of the price estimation
*/
_displayOrderFormResult : function(e) {
this.formLink.removeClass(this._classNameBase + 'Links-Inactive');
this.formLink.active = true;
this.formLink.addClass('Selected');
this.shoppingCartLink.removeClass('Selected');
this.confirmationLink.removeClass('Selected');
this.orderForm.initialized = true;
this.orderForm.set("html", e);
if (!this._options.contactForm) {
$('formSameParticipantContainer').setStyle('display', 'none');
}
var scripts = this.orderForm.getElementsByTagName("script");
for (var i = 0; i < scripts.length; i++) {
eval(scripts[i].innerHTML);
}
this._displayOrderForm();
},
/**
* Display the result of the price estimation
*
* @param Event e The result of the price estimation
*/
displayOrderConfirmationResult : function(data) {
this.options.input.setStyle('display', 'none');
if (!this._displayOutput)this._outputContainer.setStyle('display', 'none');
this.orderForm.setStyle('display', 'none');
this.orderConfirmation.setStyle('display', 'block');
this.confirmationLink.removeClass(this._classNameBase + 'Links-Inactive');
this.confirmationLink.active = true;
this.formLink.removeClass('Selected');
this.shoppingCartLink.removeClass('Selected');
this.confirmationLink.addClass('Selected');
this.orderConfirmation.set("html", data);
var scripts = this.orderConfirmation.getElementsByTagName("script");
for (var i = 0; i < scripts.length; i++) {
eval(scripts[i].innerHTML);
}
this.fireEvent('viewChanged', 'confirmation');
},
/**
*  Send the order form to save the user values in the session
*
**/
saveFormFields : function() {
if (!$('sameParticipant').get('value')) {
$('orderFormRequest').setProperty('action', window.getCurrentPageUrl());
if (!$('orderFormRequest').getChildren().contains($('id_componentName'))) {
if ($('id_componentName')) {
$('id_componentName').destroy();
}
(new Element('input').setProperties({name:'componentName',id:'id_componentName',type:'hidden'})).injectBefore($('orderFormRequest').getChildren()[0]);
}
$('id_componentName').setProperty('value', $('orderFormRequest').getComponentName());
if (!$('orderFormRequest').getChildren().contains($('id_componentId'))) {
if ($('id_componentId')) {
$('id_componentId').destroy();
}
(new Element('input').setProperties({name:'componentId',id:'id_componentId',type:'hidden'})).inject($('orderFormRequest').getChildren()[0], 'before');
}
$('id_componentId').setProperty('value', $('orderFormRequest').getComponentId());
$('id_step').setProperty('value', 'saveFields');
$('orderFormRequest').send();
}
else {
$('orderFormRequestNoContactParticipant').setProperty('action', window.getCurrentPageUrl());
if (!$('orderFormRequestNoContactParticipant').getChildren().contains($('id_componentName'))) {
if ($('id_componentName')) {
$('id_componentName').destroy();
}
(new Element('input').setProperties({name:'componentName',id:'id_componentName',type:'hidden'})).inject($('orderFormRequestNoContactParticipant').getChildren()[0], 'before');
}
$('id_componentName').setProperty('value', $('orderFormRequestNoContactParticipant').getComponentName());
if (!$('orderFormRequestNoContactParticipant').getChildren().contains($('id_componentId'))) {
if ($('id_componentId')) {
$('id_componentId').destroy();
}
(new Element('input').setProperties({name:'componentId',id:'id_componentId',type:'hidden'})).inject($('orderFormRequestNoContactParticipant').getChildren()[0], 'before');
}
$('id_componentId').setProperty('value', $('orderFormRequestNoContactParticipant').getComponentId());
$('orderFormRequestNoContactParticipant').getElement('input[id=id_step]').setProperty('value', 'saveFields');
$('orderFormRequestNoContactParticipant').send();
}
},
/**
*  Display a waiting panel layer on an element given in parameter
* todo remove
*
* @param Element element The element to put the layer on
*/
displayWaitingPanel : function(element) {
},
/**
* Hide the waiting panel
* todo remove
*/
hideWaitingPanel : function() {
},
/**
*  Display a waiting panel layer on an element given in parameter
*
* @param Element element The element to put the layer on
*/
displayMessage : function(sMessage) {
// refresh the height of the waiting panel layer
var coordinates = this.options.input.getParent().getCoordinates();
this._bookingMessagePanel.set("html", sMessage);
var messagePanelCoordinates = this._bookingMessagePanel.getCoordinates();
this._bookingMessagePanel.setStyles({
width : (200),
left : (coordinates.left + (coordinates.width / 2 - 100)),
top : (coordinates.top + (coordinates.height / 2 - messagePanelCoordinates.height / 2))
});
this._bookingMessageFxStyle.start(0, 1);
this._bookingMessageFxStyle.delayedFunction = this._bookingMessageFxStyle.start.delay(3000, this._bookingMessageFxStyle, [1,0]);
},
/**
* 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 = new Array();
priceEstimationDTO.fixedDatesCourses = new Array();
priceEstimationDTO.optionalCourses = new Array();
priceEstimationDTO.accommodations = new Array();
priceEstimationDTO.transfers = new Array();
// For each school, we retrieve all the informations
if (this.schools) {
for (var i = 0; i < this.schools.length; i++) {
priceEstimationDTO.variableDatesCourses = priceEstimationDTO.variableDatesCourses.concat(this.schools[i].courses.getVariableCoursesDTO());
priceEstimationDTO.fixedDatesCourses = priceEstimationDTO.fixedDatesCourses.concat(this.schools[i].courses.getFixedCoursesDTO());
priceEstimationDTO.optionalCourses = priceEstimationDTO.optionalCourses.concat(this.schools[i].courses.getOptionalCoursesDTO());
priceEstimationDTO.accommodations = priceEstimationDTO.accommodations.concat(this.schools[i].accommodations.getDTO());
priceEstimationDTO.transfers = priceEstimationDTO.transfers.concat(this.schools[i].transfers.getDTO());
}
}
priceEstimationDTO.numberOfPeople = this.participants.getParticipant();
if (this._currencyConversionEnabled) {
priceEstimationDTO.currency = this.currency.getCurrency();
}
else {
priceEstimationDTO.currency = null;
}
priceEstimationDTO.insurances = new Object();
if (this.insurancesManager) {
priceEstimationDTO.insurances = this.insurancesManager.getDTO();
}
priceEstimationDTO.promotions = new Array();
if (this.promotionsManager) {
priceEstimationDTO.promotions = this.promotionsManager.getDTO();
}
priceEstimationDTO.customValues = new Array();
this._customValues.each(function(value, key, hash) {
var valueDTO = new Object();
valueDTO.key = key;
valueDTO.value = html_entity_decode(value);
priceEstimationDTO.customValues.push(valueDTO);
}.bind(this));
return priceEstimationDTO;
},
/**
* populate the price calculator with the DTO given in parameter
*
* @param ShoppingCartDTO The DTO To populate the shopping cart
*/
populateFromDTO : function(toPopulateDTO) {
this.fireEvent('beforePopulate', [this, toPopulateDTO]);
this.participants.setParticipant(toPopulateDTO.numberOfPeople);
for (var i = 0; i < this.schools.length; i++) {
this.schools[i].populateFromDTO(toPopulateDTO);
}
this.insurancesManager.populateFromDTO(toPopulateDTO.insurances);
this.promotionsManager.populateFromDTO(toPopulateDTO.promotions);
this._customValues = new Hash();
if(toPopulateDTO.customValues){
toPopulateDTO.customValues.each(function(item, index){
this.setCustomValue(item.key, html_entity_decode(item.value));
}.bind(this));
}
this.fireEvent('populated');
this.fireEvent('refreshPrice');
},
/**
* Set a custom value that will be saved in the form
*
* @param string key the key
* @param mixed value The value
*/
setCustomValue : function(key, value) {
if(key != 'undefined'){
if (this._customValues.has(key))
this._customValues.erase(key);
this._customValues.set(key, value);
}
},
getCustomValue : function(key, value){
if(this._customValues.has(key))
return this._customValues.get(key);
return null;
},
/**
* Remove a school from the shopping cart
*
* @param Element school Remove the school given in param
*/
removeSchool : function(school) {
this.schools.erase(school);
//        this.displayWaitingPanel(this.options.output);
// The price must be refreshed to update the session
if(this.options.widgetMode){
this._xhr.cancel();
this._xhr.send(window.getCurrentJsonUrl(this.options.input), 'dto=' + JSON.encode(this.getDTO()) + '&shoppingCartPage=' + this.options.shoppingCartPage + '&sId=' + school._schoolPriceCalculatorDTO.schoolId + '&sPrg=' + school._schoolPriceCalculatorDTO.schoolProgram);
// if the shopping cart is empty
if (!this.schools.length) {
var emptyMessage = new Element('div', {'class': this._classNameBase + 'Empty'});
emptyMessage.set("html", this._translateDTO.empty);
// clean the input
this.options.input.set("html", '');
// set the initialization to false
this.formLink.addClass(this._classNameBase + 'Links-Inactive');
this.formLink.active = false;
this.orderForm.initialized = false;
// inject the empty shopping cart message
emptyMessage.inject(this.options.input);
this.setSameColumnSize(this.options.input, this.options.output);
}
}
},
/**
* function called to sort an array of courses
*
* @param courseDTO a The first course to compare
* @param courseDTO b The second course to compare
*/
sortByPositionFunction : function(a, b) {
return a.position - b.position;
},
/**
*  This method return the localized dateFormat
*
*  @return String The localized date format
*/
getDateFormat : function() {
return this._schoolPriceCalculatorDTO.dateFormat;
},
/**
*  Return the classNameBase
*/
getClassNameBase : function() {
return this._classNameBase;
},
/**
*  Return the type
*/
getType : function() {
return 'ShoppingCart';
},
/**
* refresh accommodations object
*
*/
refreshAccommodations : function() {
for (var i = 0; i < this.schools.length; i++) {
this.schools[i].accommodations.refreshAccommodations();
}
},
/**
* Returns the number of participant
*
* @return number The number of participants
*
*/
getParticipants : function() {
return this.participants.getParticipant() ? this.participants.getParticipant() : 1;
},
/**
* This method return the list container
*
* @return Element The element containing the lists
*/
getListContainer : function() {
return this._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) {
if(this.options.syncHeight){
column1.setStyle('height', 'auto');
column2.setStyle('height', 'auto');
var firstColumnHeight = parseInt(column1.getCoordinates().height, 10);
var secondColumnHeight = parseInt(column2.getCoordinates().height, 10);
if (firstColumnHeight > secondColumnHeight) {
column2.setStyle('height', firstColumnHeight - parseInt(column2.getStyle('margin-top')) - column2.getStyle('padding-top').toInt() - column2.getStyle('padding-bottom').toInt() - column2.getStyle('border-top-width').toInt() - column2.getStyle('border-bottom-width').toInt());
}
else if (firstColumnHeight < secondColumnHeight) {
column1.setStyle('height', secondColumnHeight - parseInt(column1.getStyle('margin-top')) - column1.getStyle('padding-top').toInt() - column1.getStyle('padding-bottom').toInt() - column1.getStyle('border-top-width').toInt() - column1.getStyle('border-bottom-width').toInt());
}
}
// refresh the size of the waiting panel
/*    if (this._waitingPanelLayer.elementTo) {
var coordinates = this._waitingPanelLayer.elementTo.getCoordinates();
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)
});
}*/
},
/**
* Return the contact information for a given form id
* @param integer contactId The contact form id
*
* @return contactId The contact informations
*/
getContactInformation : function(contactId) {
var contactInformations = new Array();
// retrieve the input type one
var inputs = $('participant' + contactId + 'Form').getElements('input');
for (var i = 0; i < inputs.length; i++) {
var information = new Object();
if(inputs[i].get('type') == 'checkbox' || inputs[i].get('type') == 'radio'){
if(inputs[i].checked) {
information.id = inputs[i].getProperty('id');
information.value = inputs[i].get('value');
contactInformations.push(information);
}
}else {
information.id = inputs[i].getProperty('id');
information.value = inputs[i].get('value');
contactInformations.push(information);
}
}
// retrieve the select type one
var inputs = $('participant' + contactId + 'Form').getElements('select');
for (var i = 0; i < inputs.length; i++) {
var information = new Object();
information.id = inputs[i].getProperty('id');
information.value = inputs[i].get('value');
contactInformations.push(information);
}
// retrieve the textarea type one
var inputs = $('participant' + contactId + 'Form').getElements('textarea');
for (var i = 0; i < inputs.length; i++) {
var information = new Object();
information.id = inputs[i].getProperty('id');
information.value = inputs[i].get('value');
contactInformations.push(information);
}
return contactInformations;
},
/**
* Populate a contact form from another one
*
* @param string sourceId The source contact form id
* @param string targetId The target contact form id
*/
populateContactForm : function(sourceId, targetId) {
if (sourceId != '00') {
var contactInformation = this.getContactInformation(sourceId);
for (var i = 0; i < contactInformation.length; i++) {
var fieldId = contactInformation[i].id.slice(contactInformation[i].id.indexOf("."));
var field = $("id_" + targetId + fieldId);
if (field) {
if (field.getAttribute('type') == 'radio' || field.getAttribute('type') == 'checkbox') {
if (contactInformation[i].value) {
field.setAttribute("checked", "checked");
}
}
else {
field.value = contactInformation[i].value;
}
}
}
$('id_' + targetId + '.contact.firstName').fireEvent('change');
}
},
/**
* Display the right participant form
*/
displayParticipantsForm :  function() {
this._currentForm = ($('sameParticipant').checked ? $('orderFormRequestNoContactParticipant') : $('orderFormRequest'));
if ($('sameParticipant').checked) {
if (this._selectedParticipantForm.participantId)this.populateContactForm(this._selectedParticipantForm.participantId, '0' + this._selectedParticipantForm.participantId);
$('participant0').setStyle('display', 'none');
$('multiProfileFormBottom').setStyle('display', 'none');
$('standardForms').setStyle('display', 'none');
if ($('orderFormRequestNoContactParticipant'))$('orderFormRequestNoContactParticipant').setStyle('display', 'block');
}
else {
if (this._selectedParticipantForm.participantId)this.populateContactForm('0' + this._selectedParticipantForm.participantId, this._selectedParticipantForm.participantId);
$('participant0').setStyle('display', 'block');
$('multiProfileFormBottom').setStyle('display', 'block');
$('standardForms').setStyle('display', 'block');
if ($('orderFormRequestNoContactParticipant'))$('orderFormRequestNoContactParticipant').setStyle('display', 'none');
}
if (!$('participant2Form') && $('sameParticipant').checked) {
$('formParticipantsContainer').setStyle('display', 'none');
$('multiProfileForm').setStyle('display', 'none');
}
else {
$('formParticipantsContainer').setStyle('display', 'block');
$('multiProfileForm').setStyle('display', 'block');
}
if ($('sameParticipant').checked) {
$('participant1').fireEvent('click');
$('participant0').optionElement.setStyle('display', 'none');
}
else {
$('participant0').fireEvent('click');
}
this.updateButtonText($('participant0'), this.emptyParticipantName);
$('orderFormRequest').getValidator().validate(false, true, true);
},
/**
* Update the text button
* @param button button The item to update
* @param string emptyParticipantName The empty participant name translation
*/
updateButtonText : function(button, emptyParticipantName) {
if ($('sameParticipant').checked) {
var participantId = '0' + button.participantId;
}
else {
var participantId = button.participantId;
}
if ($('id_' + participantId + '.contact.firstName')) {
var text = button.textValue;
if (!text) text = '';
if (!$('id_' + participantId + '.contact.firstName').get('value') && !$('id_' + participantId + '.contact.lastName').get('value')) {
text = text.replace("%0", emptyParticipantName);
text = text.replace("%1", '');
}
else {
text = text.replace("%0", $('id_' + participantId + '.contact.firstName').get('value'));
text = text.replace("%1", ' ' + $('id_' + participantId + '.contact.lastName').get('value'));
}
$('participant' + (button.participantId ? button.participantId : '0')).getElements('span')[1].set("html", text);
button.optionElement.set("html", text);
}
this.updateCopyFromButton();
},
/**
*  Update the copy from button
*/
updateCopyFromButton : function() {
for (var i = 0; i < $('copyFrom').getChildren().length; i++) {
if (this._selectedParticipantForm.participantId == $('copyFrom').getChildren()[i].getAttribute('value')) {
$('copyFrom').getChildren()[i].setStyle('display', 'none');
}
else {
if ($('id_' + ($('sameParticipant').checked ? '0' : '') + i + '.contact.firstName') && $('id_' + ($('sameParticipant').checked ? '0' : '') + i + '.contact.firstName').get('value') && $('id_' + ($('sameParticipant').checked ? '0' : '') + i + '.contact.lastName').get('value')) {
$('copyFrom').getChildren()[i].setStyle('display', 'block');
}
else {
$('copyFrom').getChildren()[i].setStyle('display', 'none');
}
}
}
for (var i = 0; i < $('copyFrom').getChildren().length; i++) {
if ($('copyFrom').getChildren()[i].getStyle('display') != 'none') {
$('copyFromContainer').setStyle('display', 'inline');
break;
}
if (i == $('copyFrom').getChildren().length - 1) {
if ($('copyFrom').getChildren()[i].getStyle('display') == 'none') {
$('copyFromContainer').setStyle('display', 'none');
}
}
}
},
/**
* initialize the form button event
*
* @param string nextParticipantButtonName  The translation
* @param string previousParticipantButtonName The translation
* @param string firstParticipantButtonName The translation
* @param string toContactButtonName The translation
* @param string emptyParticipantName The translation
*/
addFormButtonEvents : function (nextParticipantButtonName, previousParticipantButtonName, firstParticipantButtonName, toContactButtonName, emptyParticipantName, participantNr) {
this._currentForm = ($('sameParticipant').checked ? $('orderFormRequestNoContactParticipant') : $('orderFormRequest'));
this.nextParticipantButtonName = nextParticipantButtonName;
this.previousParticipantButtonName = previousParticipantButtonName;
this.firstParticipantButtonName = firstParticipantButtonName;
this.toContactButtonName = toContactButtonName;
this.emptyParticipantName = emptyParticipantName;
this.participantNr = participantNr;
this.overrideFormMethod();
// Add the event on the selector
$('copyFromButton').addEvent('click', function(e) {
var from = ($('sameParticipant').checked ? '0' : '') + $('copyFrom').value;
var to = ($('sameParticipant').checked ? '0' : '') + this._selectedParticipantForm.participantId;
this.populateContactForm(from, to);
}.bind(this));
this._selectedParticipantForm = $('participant01Form');
// Add the events on the buttons
$$('.Component-Form-Contact-Button').each(function(item, index) {
item.setIsValid = function(isValid, displayErrorMessage) {
if (!isValid) {
item.addClass('Component-Form-Contact-Button-Invalid');
if (displayErrorMessage) {
item.displayErrorMessage = true;
}
}
else {
item.removeClass('Component-Form-Contact-Button-Invalid');
item.displayErrorMessage = false;
}
};
item.textValue = item.getElements('span')[1].innerHTML;
item.participantId = parseInt(item.getProperty('id').replace('participant', ''), 10);
// Add the style event on the buttons
item.addEvent("mouseenter", function() {
item.getElements('span')[0].addClass('Component-Links-Number-Hover');
item.getElements('span')[1].addClass('Component-Links-Name-Hover');
}.bind(this));
item.addEvent("mouseleave", function() {
if (item.participantId != this._selectedParticipantForm.participantId) {
item.getElements('span')[0].removeClass('Component-Links-Number-Hover');
item.getElements('span')[1].removeClass('Component-Links-Name-Hover');
}
}.bind(this));
// Add the click event on the button
item.addEvent('click', function() {
this.participantButtonEvent(item);
}.bind(this));
var optionElement = new Element('option');
optionElement.setProperty('value', item.participantId);
item.optionElement = optionElement;
optionElement.setStyle('display', 'none');
item.optionElement.inject($('copyFrom'));
this.updateButtonText(item, this.emptyParticipantName);
$('id_' + item.participantId + '.contact.firstName').addEvent('change', function() {
this.updateButtonText(item, this.emptyParticipantName);
}.bind(this));
$('id_' + item.participantId + '.contact.lastName').addEvent('change', function() {
this.updateButtonText(item, this.emptyParticipantName);
}.bind(this));
if (item.participantId) {
$('id_0' + item.participantId + '.contact.firstName').addEvent('change', function() {
this.updateButtonText(item, this.emptyParticipantName);
}.bind(this));
$('id_0' + item.participantId + '.contact.lastName').addEvent('change', function() {
this.updateButtonText(item, this.emptyParticipantName);
}.bind(this));
}
}.bind(this));
// The navigations shortcuts events
$('nextParticipantTop').addEvent('click', function(item) {
$('nextParticipant').fireEvent('click');
}.bind(this));
$('previousParticipantTop').addEvent('click', function(item) {
$('previousParticipant').fireEvent('click');
}.bind(this));
$('nextParticipant').addEvent('click', this.goToNextParticipant.bind(this));
$('previousParticipant').addEvent('click', this.goToPreviousParticipant.bind(this));
$('nextParticipantNoContact').addEvent('click', this.goToNextParticipant.bind(this));
$('previousParticipantNoContact').addEvent('click', this.goToPreviousParticipant.bind(this));
// The submit shortcuts event
$('submitFormTop').addEvent('click', function() {
if ($('sameParticipant').checked) {
$('id_submitNoContact').click();
}
else {
$('id_submit').click();
}
}.bind(this));
$('orderFormRequest').addEvent('ajaxcall', function() {
this.fireEvent('onAjaxCall');
}.bind(this));
$('orderFormRequest').addEvent('invalidfield', function() {
this.fireEvent('onAjaxResponse')
//            this.hideWaitingPanel();
}.bind(this));
$('orderFormRequestNoContactParticipant').addEvent('ajaxcall', function() {
this.fireEvent('onAjaxCall');
//            this.displayWaitingPanel($$(".Synergee-Web-Page-Component-Booking-Container")[0]);
}.bind(this));
$('orderFormRequestNoContactParticipant').addEvent('invalidfield', function() {
this.fireEvent('onAjaxResponse');
//            this.hideWaitingPanel();
}.bind(this));
$('sameParticipant').addEvent('click', function() {
this.displayParticipantsForm();
}.bind(this));
$('notSameParticipant').addEvent('click', function() {
this.displayParticipantsForm();
}.bind(this));
//        this.hideWaitingPanel();
this.displayParticipantsForm();
},
/**
* Go to the next participant form
*/
goToNextParticipant : function() {
if ($('participant' + (this._selectedParticipantForm.participantId + 1))) {
$('participant' + (this._selectedParticipantForm.participantId + 1)).fireEvent('click');
}
},
/**
* Go to the previous participant form
*/
goToPreviousParticipant : function() {
var participantId = (this._selectedParticipantForm.participantId - 1);
if (!participantId) participantId = '0';
if ($('participant' + participantId)) {
$('participant' + participantId).fireEvent('click');
}
},
/**
* Override some of the form methods
*/
overrideFormMethod : function() {
// override the validate method
$('orderFormRequest').getValidator()._validate = $('orderFormRequest').getValidator().validate;
$('orderFormRequest').getValidator().validate = this.formValidate;
// The validate Form method
$('orderFormRequest').getValidator().validateForm = this.validateForm;
// override the focus method and displayErrorMessage on form items
$('orderFormRequest').getValidator()._fields.each(this.overrideFieldMethod.bind(this));
// override the validate method
$('orderFormRequestNoContactParticipant').getValidator()._validate = $('orderFormRequestNoContactParticipant').getValidator().validate;
$('orderFormRequestNoContactParticipant').getValidator().validate = this.formValidate;
// The validate Form method
$('orderFormRequestNoContactParticipant').getValidator().validateForm = this.validateForm;
// override the focus method and displayErrorMessage on form items
$('orderFormRequestNoContactParticipant').getValidator()._fields.each(this.overrideFieldMethod.bind(this));
},
/**
* Valid a form
*
* @param boolean  ajaxCall true if the validation must be made by the backend
* @param boolean forButton True if it's just for a button
* @param boolean notDisplayErrorMsg To not display error msg when not needed
*/
formValidate : function(ajaxCall, forButton, notDisplayErrorMsg) {
// if this is not the button that calls that method
$$('.Component-Form-Contact-Button').each(function(item) {
item.setIsValid(true);
}.bind(this));
if (!forButton) {
this._validate(ajaxCall);
// if it's the button that calls that method, just displaying the error messages
}
else {
// 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) {
for (var i = 0; i < invalidFields.length; i++) {
invalidFields[i].displayErrorMessage(notDisplayErrorMsg);
}
}
}
},
/**
* Validate a form
* @param integer formId The form id
* @param boolean displayErrorMessages True to display the error msg
*/
validateForm : function(formId, displayErrorMessages) {
// The error message of the form is hidden
this._formElement.hideErrorMessage();
$('participant' + (formId ? formId : '0')).setIsValid(true, false);
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])) {
var name = this._fields[i].getProperty('name');
if (parseInt(name.split(".", 1)[0], 10) == formId) {
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) {
$('participant' + (formId ? formId : '0')).setIsValid(false, false);
if (displayErrorMessages) {
for (var i = 0; i < invalidFields.length; i++) {
invalidFields[i].displayErrorMessage(false);
}
}
}
},
/**
* Override the field methods
* @param FieldElement item The Field
*/
overrideFieldMethod : function(item) {
item._focus = item.focus;
item.focus = function() {
var name = this.getProperty('name');
var fieldParticipantId = parseInt(name.split(".", 1)[0], 10);
if ($('participant' + fieldParticipantId)) {
$('participant' + fieldParticipantId).fireEvent('click');
}
this._focus();
};
item._displayErrorMessage = item.displayErrorMessage;
item.displayErrorMessage = function(notDisplayErrorMsg) {
var button = parseInt(this.getProperty('name').split(".", 1)[0]);
if ($('participant' + button)) {
$('participant' + button).setIsValid(false, !notDisplayErrorMsg);
if ($('participant' + button).displayErrorMessage) {
this._displayErrorMessage();
}
}
else {
this._displayErrorMessage();
}
};
item.addEvent('change', function(e) {
var button = item.getProperty('name').split(".", 1)[0];
this._currentForm.getValidator().validateForm(parseInt(button, 10));
}.bind(this));
},
/**
* Add the event on the participant buttons
* @param Element item The button
*/
participantButtonEvent : function(item) {
var nav = navigator.appVersion.split("MSIE");
var navVersion = parseFloat(nav[1]);
if (!((navVersion >= 5.5) && (navVersion < 7))) {
//            this.displayWaitingPanel(this._selectedParticipantForm);
}
// hide the current active form
var oldSelectedButton = $('participant' + this._selectedParticipantForm.participantId);
oldSelectedButton.removeClass('Component-Form-Participant-Button-Selected');
this._selectedParticipantForm.setStyle('display', 'none');
this._selectedParticipantForm.setStyle('opacity', 0);
// select the new active form
item.addClass('Component-Form-Participant-Button-Selected');
if ($('sameParticipant').checked) {
if (this._selectedParticipantForm.participantId)this.populateContactForm('0' + this._selectedParticipantForm.participantId, this._selectedParticipantForm.participantId);
this._selectedParticipantForm = $('participant0' + item.getProperty('id').replace('participant', '') + 'Form');
}
else {
if (this._selectedParticipantForm.participantId)this.populateContactForm(this._selectedParticipantForm.participantId, '0' + this._selectedParticipantForm.participantId);
this._selectedParticipantForm = $(item.getProperty('id') + 'Form');
}
oldSelectedButton.fireEvent("mouseleave");
this._selectedParticipantForm.setStyle('opacity', 1);
this._selectedParticipantForm.setStyle('display', 'block');
item.fireEvent('mouseenter');
// if the button is "invalid" state, ask the form to validate the fields
// in order to display the right values
if (item.displayErrorMessage) {
this._currentForm.getValidator().validateForm(this._selectedParticipantForm.participantId, true);
}
if (!((navVersion >= 5.5) && (navVersion < 7))) {
//            this.hideWaitingPanel.delay(400, this);
}
// update the navigation buttons, depends of its position
if (this._selectedParticipantForm.participantId == 0) {
$('previousParticipant').setStyle('display', 'none');
$('previousParticipantNoContact').setStyle('display', 'none');
$('previousParticipantTop').setStyle('display', 'none');
$('nextParticipant').setAttribute('value', this.firstParticipantButtonName);
$('nextParticipantNoContact').setAttribute('value', this.firstParticipantButtonName);
$('nextParticipantTop').setAttribute('value', this.firstParticipantButtonName);
}
else {
$('previousParticipantTop').setStyle('display', 'inline');
$('previousParticipant').setStyle('display', 'inline');
$('previousParticipantNoContact').setStyle('display', 'inline');
$('nextParticipantTop').setAttribute('value', this.nextParticipantButtonName);
$('nextParticipant').setAttribute('value', this.nextParticipantButtonName);
$('nextParticipantNoContact').setAttribute('value', this.nextParticipantButtonName);
}
if (this._selectedParticipantForm.participantId == 1) {
if ($('sameParticipant').checked) {
$('previousParticipant').setStyle('display', 'none');
$('previousParticipantNoContact').setStyle('display', 'none');
$('previousParticipantTop').setStyle('display', 'none');
}
else {
$('previousParticipantTop').setAttribute('value', this.toContactButtonName);
$('previousParticipant').setAttribute('value', this.toContactButtonName);
$('previousParticipantNoContact').setAttribute('value', this.toContactButtonName);
}
}
else {
$('previousParticipantTop').setAttribute('value', this.previousParticipantButtonName);
$('previousParticipant').setAttribute('value', this.previousParticipantButtonName);
$('previousParticipantNoContact').setAttribute('value', this.previousParticipantButtonName);
}
if ((this._selectedParticipantForm.participantId + 1) == $$('.Component-Form-Contact-Button').length) {
$('nextParticipant').setStyle('display', 'none');
$('nextParticipantNoContact').setStyle('display', 'none');
$('nextParticipantTop').setStyle('display', 'none');
$('id_submit').setStyle('display', 'inline');
$('id_submitNoContact').setStyle('display', 'inline');
$('submitFormTop').setStyle('display', 'inline');
}
else {
$('nextParticipant').setStyle('display', 'inline');
$('nextParticipantNoContact').setStyle('display', 'inline');
$('nextParticipantTop').setStyle('display', 'inline');
$('id_submit').setStyle('display', 'none');
$('id_submitNoContact').setStyle('display', 'none');
$('submitFormTop').setStyle('display', 'none');
}
this.updateCopyFromButton();
},
/**
* Display the price estimation in a printing window
*
* Note : Not used anymore
*/
print : function() {
var xhr = new Request({
url : window.getCurrentJsonUrl(this.options.input),
onSuccess : function(html) {
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.options.output.contentWindow;
} catch(ex) {
}
var d = w ? w.document : null;
} else {
try {
var d = this.options.output.contentDocument;
}
catch (ex) {
}	// in case of cross domain scripting
var w = d ? d.defaultView : null;
}
if (d) {
try {
// We set the content
d.open();
d.write(html);
d.close();
var body = d.getElementsByTagName("body")[0];
body.style.textAlign = 'left';
body.className = 'Synergee-Web-Page-Component-Booking-Print-Body';
// We add the stylesheets
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);
}
}
// We print the window
w.focus();
w.printTimout = function(ms) {
var _self = this;
setTimeout(function(ms) {
_self.print();
}, ms);
};
w.printTimout(2000);
} catch (ex) {
}
}
}.bind(this)
});
xhr.send('format=print&dto=' + JSON.encode(this.getDTO()) + '&schoolId=' + this.schoolSelector.getSelectedSchoolId());
Lightbox.show('{hiddenId|' + this.options.output.id + '}', '', 'width=750, height=370');
},
/**
* Display the price estimation in a printing window
*/
mailQuote : function() {
var xhr = new Request(
{
url : window.getCurrentJsonUrl(this.options.input),
onSuccess : function(html) {
this.messageWindow.displayMessage(this._translateDTO.mailSent, this._translateDTO.mailWindowTitle, 4000);
}.bind(this)
}
);
if (!this.messageWindow)this.messageWindow = new WindowMessagePanel(this.options.input);
this.messageWindow.displayMessage('<form><label  class="Synergee-Web-Page-Form-Label Synergee-Web-Page-SchoolPriceEstimation-Print-Label"  for="quoteNameInput">' + this._translateDTO.recipientMail + '</label><input id="recipientMailInput" class="Synergee-Web-Page-Form-Text Synergee-Web-Page-SchoolPriceEstimation-Print-TextInput" type="text"></input>' +
'<label  class="Synergee-Web-Page-Form-Label Synergee-Web-Page-SchoolPriceEstimation-Print-Label"  for="quoteNameSubject">' + this._translateDTO.mailSubjectLabel + '</label><input id="quoteNameSubject" class="Synergee-Web-Page-Form-Text Synergee-Web-Page-SchoolPriceEstimation-Print-TextInput" type="text" value="' + this._translateDTO.mailSubject + '"></input>' +
'<label  class="Synergee-Web-Page-Form-Label Synergee-Web-Page-SchoolPriceEstimation-Print-Label"  for="quoteNameContent">' + this._translateDTO.mailContentLabel + '</label><textarea id="quoteNameContent" class="Synergee-Web-Page-Form-Textarea Synergee-Web-Page-SchoolPriceEstimation-Print-TextInput Synergee-Web-Page-SchoolPriceEstimation-Print-TextArea" >' + this._translateDTO.mailContent + '</textarea>' +
'<input type="submit" class="Synergee-Web-Page-Form-Submit Synergee-Web-Page-SchoolPriceEstimation-Print-Submit" value="Send"/></form>', this._translateDTO.mailWindowTitle);
var form = this.messageWindow.getContent().getElement('form');
var mailTo = this.messageWindow.getContent().getElement('input[id=recipientMailInput]');
var mailSubject = this.messageWindow.getContent().getElement('input[id=quoteNameSubject]');
var mailMessage = this.messageWindow.getContent().getElement('textarea[id=quoteNameContent]');
form.addEvent('submit', function(e) {
e = new Event(e);
xhr.send('format=mail&dto=' + JSON.encode(this.getDTO()) + '&schoolId=' + this._selectedSchoolId + '&mailTo=' + mailTo.get('value') + '&mailSubject=' + mailSubject.get('value') + '&mailMessage=' + mailMessage.get('value'));
this.messageWindow.hideMessage();
e.stop();
}.bind(this));
this.messageWindow.getContent().getElement('input').focus.delay(300, this.messageWindow.getContent().getElement('input'));
},
/**
* Add the quote to the quotes manager
*/
addToMyQuotes : function() {
var xhr = new Request({
url : window.getCurrentJsonUrl(this.options.input),
onSuccess : function(quotesNumber) {
document.fireEvent('quoteChanged', quotesNumber);
}.bind(this)
});
var params = 'step=addToQuotes';
if (this._selectedSchoolId) {
params = params + '&schoolId=' + this._selectedSchoolId;
}
xhr.send(params);
},
addToCart : function() {
var xhr = new Request({
url : window.getCurrentJsonUrl(this.options.input),
onSuccess : function(quotesNumber) {
document.fireEvent('cartChanged', quotesNumber);
}.bind(this)
});
xhr.send('step=addToCart&schoolId=' + this._selectedSchoolId);
},
emptyCart : function () {
var xhr = new Request({
url : window.getCurrentJsonUrl(this.options.input),
onSuccess : function() {
document.fireEvent('cartChanged', 0);
this.fireEvent('cartEmpty');
}.bind(this)
});
xhr.send('step=emptyCart');
}
});
/**
* Display the price estimation in a printing window
*/
function printConfirmation() {
var printOutput = $('shoppingCartConfirmationPrint');
Lightbox.show('{hiddenId|' + printOutput.id + '}', '', 'width=750, height=370');
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 = printOutput.contentWindow;
}
catch(ex) {
}
var d = w ? w.document : null;
}
else {
try {
var d = printOutput.contentDocument;
}
catch (ex) {
}	// in case of cross domain scripting
var w = d ? d.defaultView : null;
}
if (d) {
try {
var shoppingCartContainer = new Element('div');
shoppingCartContainer.addClass('Synergee-Web-Page-Component-ShoppingCart');
var child = $('formConfirmationContent').clone();
child.addClass('Component-Print-Container');
child.inject(shoppingCartContainer);
child.removeChild(child.getElement('script'));
d.open();
d.write('<html><head/><body>' + shoppingCartContainer.innerHTML + '</body></html>');
d.close();
var body = d.getElementsByTagName("body")[0];
body.style.textAlign = 'left';
var printHeader = d.getElementById('printHeader');
if (printHeader)printHeader.setAttribute('class', 'Synergee-Web-Page-Component-Text');
var printBottom = d.getElementById('printBottom');
if (printBottom)printBottom.setAttribute('class', 'Synergee-Web-Page-Component-Text Component-BottomText');
if (d.getElementById('printButtonContainer')) {
d.getElementById('printButtonContainer').removeChild(d.getElementById('printButtonContainer').childNodes[0]);
}
// We add the stylesheets
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) {
}
}
};
/**
* 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 Booking = Events.extend({
var Booking = new Class({
Extends:BookingEngine,
/**
* This is the initialization function
*/
initialize:function (options) {
this.parent(options);
this.getProgramsListTemplate = this.options.getProgramsListTemplateCallback;
this.getCountriesListTemplate = this.options.getCountriesListTemplateCallback;
this.getCitiesListTemplate = this.options.getCitiesListTemplateCallback;
this.getSchoolsListTemplate = this.options.getSchoolsListTemplateCallback;
this._outputContainer = this.options.output;
this._directives = new Hash();
// retrieve the right result div
while (!this._outputContainer.hasClass('Component-Cart')) {
this._outputContainer = this._outputContainer.getParent();
}
this.header = this.options.header;
if (!this.options.shoppingCartPage && this.header) {
this.header.setStyle('display', 'none');
}
this.shoppingCartContainer = this.options.input.getParent();
this._displayOutput = false;
this._listContainer = new Element('div', {'id':'lists'});
this._listContainer.inject(document.getElement('body'));
this._classNameBase = 'Component-';
this._bookingMessagePanel = new Element('div', {'class':this._classNameBase + 'bookingToolTip Tool-tip', 'id':'bookingMessagePanel'});
this._bookingMessageFxStyle = new Fx.Tween(this._bookingMessagePanel, {
duration:100,
property:'opacity'
});
this._bookingMessagePanel.inject(document.getElement('body'));
this._bookingMessagePanel.setStyle('position', 'absolute');
this._bookingMessagePanel.setStyles({
opacity:0,
top:0
});
this._bookingMessagePanel.addEvent('click', function () {
clearTimeout(this._bookingMessageFxStyle.delayedFunction);
this._bookingMessageFxStyle.start(1, 0);
}.bind(this));
// the top links are created
// the shopping cart link
if (this.options.shoppingCartPage) {
this.createShoppingCartLinks();
// add the order form container
this.orderForm = new Element('div');
this.orderForm.inject(this.shoppingCartContainer);
this.orderForm.setStyle('display', 'none');
this.orderForm.initialized = false;
// add the order confirmation page container
this.orderConfirmation = new Element('div');
this.orderConfirmation.inject(this.shoppingCartContainer);
this.orderConfirmation.setStyle('display', 'none');
}
this._fxStyle = new Fx.Tween(this.options.output, {
duration:100,
property:'opacity'
});
},
/**
* Start the booking
*/
launch:function () {
// The Init call is made
if (!document.isInDesignMode()) {
this.parent();
}
},
/**
* Return the json current url
*
* return string
*/
getBookingJsonUrl:function () {
return window.getCurrentJsonUrl(this.options.input);
},
/**
* called when a school is loaded
*
*
* @param e
*/
initBooking:function (e) {
eval(e);
//        this.schoolsContainer.empty();
if (typeof(getInit) == 'function') {
var initDTO = getInit();
this._schools = initDTO[0];
this._options = initDTO[2];
this._insurances = initDTO[3];
this._promotions = initDTO[4];
// The schools displayed in the shopping cart are stocked in
if (!this.schools)
this.schools = new Array();
// the menu item translations are set
if (this.options.shoppingCartPage) {
this.shoppingCartFirstItem.set("html", this._translateDTO.firstItem);
this.shoppingCartFirstItemName.set("html", this._translateDTO.yourShoppingCartMenuItem);
this.formLinkSecondItem.set("html", this._translateDTO.secondItem);
this.formLinkSecondItemName.set("html", this._translateDTO.formMenuItem);
this.confirmationLinkThirdItem.set("html", this._translateDTO.thirdItem);
this.confirmationLinkThirdItemName.set("html", this._translateDTO.confirmationMenuItem);
}
this.insurancesManager = new SchoolInsurances(this._insurances, this);
this.insurancesManager.addEvent('insurancesUpdated', this.refreshPrice.bind(this));
this.promotionsManager = new SchoolPromotions(this._promotions, this);
this.promotionsManager.addEvent('promotionsUpdated', this.refreshPrice.bind(this));
var schools = [];
// if there is no school added in the shopping cart or the shopping cart is opened in the designer
if (!this._schools.length || document.isInDesignMode()) {
if (this.options.shoppingCartPage) {
/* var emptyMessage = new Element('div', {'class': this._classNameBase + 'Empty'});
emptyMessage.set("html", this._translateDTO.empty);
emptyMessage.inject(this.schoolsContainer);*/
}
this.setSameColumnSize(this.options.input, this.options.output);
}
else {
for (var i = 0; i < this._schools.length; i++) {
this._schoolPriceCalculatorDTO = this._schools[i];
var school = new School(this._schools[i], this);
school.addEvent('refreshPrice', this.refreshPrice.bind(this));
//                            if (this.options.widgetMode)
school.addEvent('heightModified', this.onHeightModified.bind(this));
schools.push(school);
this.schools.push(school);
}
this._oldDTO = JSON.encode(this.getDTO());
// The shopping cart is populated if there are some informations
//                      if (this.options.widgetMode){
this.populateFromDTO.delay(50, this, initDTO[1]);
this.retrieveSchoolItemsDescription();
//                      }
}
this.fireEvent('initialized', [schools]);
}
},
initTranslations:function (e) {
eval(e);
if (typeof(getInit) == 'function') {
this._initDTO = getInit();
this._translateDTO = this._initDTO.translateDTO;
this.participants = new SchoolParticipants(this._translateDTO.participants, this._initDTO.multipleBooking, this);
this.currency = new SchoolCurrencySelector(this._translateDTO.currencies, this._initDTO.defaultCurrency, this._initDTO.websiteCurrencies, this);
this.currency.addEvent('refreshPrice', this.refreshPrice.bind(this));
this._currencyConversionEnabled = this._initDTO.currencyConversionEnabled;
if (!this.options.shoppingCartPage) {
this.schoolSelector = new SchoolSelector(this._translateDTO.schoolSelector, this._initDTO.schoolsList, this, this._initDTO.advancedSchoolList);
//                        if(this.options.widgetMode)
this.schoolSelector.render();
// when a school is selected
this.schoolSelector.addEvent('changeSchool', function () {
if (this.schoolSelector.getSelectedSchoolId()) {
this.loadSchool(this.schoolSelector.getSelectedSchoolId());
}
}.bind(this));
this.fireEvent('schoolsSelectorLoaded');
}
/*
if(!this.options.widgetMode){
this._initDTO.schoolsList.each(function(item, index){
item.schoolCountryName = html_entity_decode(item.schoolCountryName);
item.schoolCityName = html_entity_decode(item.schoolCityName);
item.schoolName = html_entity_decode(item.schoolName);
item.schoolProgramName = html_entity_decode(item.schoolProgramName);
item.schoolGroupName = html_entity_decode(item.schoolGroupName);
});
}*/
//                    if(this.options.widgetMode)
this.participants.getHtml().inject(this.options.input);
this.fireEvent('onTranslationsLoaded');
if (this.schoolSelector) {
if (this._initDTO.schoolsList.length == 1) {
this.schoolSelector.fireEvent('changeSchool');
} else {
this.schoolSelector.updateSelector(this._initDTO.selectedSchool, this._initDTO.selectedProgram, this._initDTO.selectedCountry, this._initDTO.selectedCity);
}
this.updateSchoolContextBanner();
}
//                    if(this.options.shoppingCartPage)
if(this.bookingAutoInit){
this.bookingAutoInit = false;
this._xhrInit.send('step=init&shoppingCartPage=' + this.options.shoppingCartPage);
}
}
},
/**
* Refresh the price
*/
refreshPrice:function () {
if (this.options.shoppingCartPage) {
if (this.formLink.active) {
this.saveFormFields();
this.formLink.addClass(this._classNameBase + 'Links-Inactive');
this.formLink.active = false;
this.orderForm.initialized = false;
}
}
this.updateValues();
if (this._oldDTO != JSON.encode(this.getDTO())) {
this.fireEvent('onPriceRefresh');
var params = 'shoppingCartPage=' + this.options.shoppingCartPage;
if (this.options.promotionIntroductionContainer != '') params = params + '&pIntroContainer=' + this.options.promotionIntroductionContainer;
if (this.options.promotionContainer != '') params = params + '&pContainer=' + this.options.promotionContainer;
if (this._selectedSchoolId)params = params + '&schoolId=' + this._selectedSchoolId;
this._xhr.cancel();
this._xhr.send(params + '&dto=' + JSON.encode(this.getDTO()));
this._oldDTO = JSON.encode(this.getDTO());
}
},
loadSchool : function (schoolId, addSchool) {
if (schoolId != this._selectedSchoolId) {
if (!addSchool && this.schools) {
this.schools = new Array();
}
if (schoolId) {
this.options.output.empty();
this._xhrInit.cancel();
this._xhr.cancel();
var xhrLoadSchool = new Request(
{
url:this.getBookingJsonUrl(),
onRequest:function () {
},
onSuccess:function (responseText) {
this.initBooking(responseText);
}.bind(this),
onFailure:function () {
}
});
var xhrParam = 'step=init';
xhrParam += '&schoolId=' + schoolId;
if(this.schools && this.schools.length && addSchool){
var loadedSchools = '';
for(var i = 0; i < this.schools.length; i++){
loadedSchools = loadedSchools + this.schools[i]._schoolDTO.schoolId + (i < this.schools.length-1 ? '|': '');
}
xhrParam += '&alreadyLoadedSchools=' + loadedSchools;
}
this._selectedSchoolId = schoolId;
this.updateSchoolContextBanner();
this.fireEvent('beforeschoolload', schoolId);
// send an ajax call to add the school
this.bookingAutoInit = false;
xhrLoadSchool.send(xhrParam);
}
}
},
/**
* called when the height of a column is modified so the two column are the same size
*
*/
onHeightModified:function (e) {
//                if(this.options.widgetMode){
this.fireEvent('beforeHeightUpdated');
this.setSameColumnSize(this.options.input, this.options.output);
this.fireEvent('afterHeightUpdated');
//                }
},
/**
* Display the result of the price estimation
*
* @param Event e The result of the price estimation
*/
displayPriceEstimation:function (e) {
//                if(this.options.widgetMode){
this.options.output.set("html", e);
this.onHeightModified();
var infos = this.options.output.getElements('.PromotionMoreInfos');
for (i = 0; i < infos.length; i++) {
new SynergeeTips(infos[i], {'className':'Booking-Tool-Tip Tool-tip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
}
//                }
// check if there are complete courses
var completedCourses = 0;
for (var i = 0; i < this.schools.length; i++) {
completedCourses += this.schools[i].getCompletedCourses().length;
}
if (completedCourses) {
if (e.replace(/^\s+|\s+$/g, '') == "") {
this.fireEvent.delay(100, this, 'refreshPrice');
}
else {
if (this.options.shoppingCartPage) {
$('bookingCheckoutButton').setStyle('visibility', '');
}
}
}
this.fireEvent('onPriceRefreshComplete', e);
},
/**
* Remove a school from the shopping cart
*
* @param Element school Remove the school given in param
*/
removeSchool:function (school) {
this.schools.erase(school);
//        this.displayWaitingPanel(this.options.output);
// The price must be refreshed to update the session
//                if(this.options.widgetMode){
this._xhr.cancel();
this._xhr.send(window.getCurrentJsonUrl(this.options.input), 'dto=' + JSON.encode(this.getDTO()) + '&shoppingCartPage=' + this.options.shoppingCartPage + '&sId=' + school._schoolPriceCalculatorDTO.schoolId + '&sPrg=' + school._schoolPriceCalculatorDTO.schoolProgram);
// if the shopping cart is empty
if (!this.schools.length) {
var emptyMessage = new Element('div', {'class':this._classNameBase + 'Empty'});
emptyMessage.set("html", this._translateDTO.empty);
// clean the input
this.options.input.set("html", '');
// set the initialization to false
this.formLink.addClass(this._classNameBase + 'Links-Inactive');
this.formLink.active = false;
this.orderForm.initialized = false;
// inject the empty shopping cart message
emptyMessage.inject(this.options.input);
this.setSameColumnSize(this.options.input, this.options.output);
}
//                }
}
}
);
var BookingCalendar = new Class({
Implements : [Events, Options],
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');
this.calendar.inject(document.body);
this.calendar.setStyles({ left: '-1000px', opacity: 0, display:'none', position: 'absolute', top: '-1000px', zIndex: 1000 });
this.calendar.addClass('BookingCalendar Component-List');
// initialize fade method
this.fx = new Fx.Tween(this.calendar ,
{
property : '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 Component-List-Item').inject(this.calendar);
this.calendarNextMenu = new Element('input').setProperties({'type':'button' , value: '>'}).addClass('NavButton NextMonth Component-List-Item').inject(this.calendar);
this.calendarInner = new Element('div',{}).addClass('CalendarInner').inject(this.calendar);
this.calendarFirstMonthContainer = new SynergeeCalendarMonth(this.options, this);
this.calendarFirstMonthContainer.getContainer().inject(this.calendarInner);
this.calendarSecondMonthContainer = new SynergeeCalendarMonth(this.options, this);
this.calendarSecondMonthContainer.getContainer().inject(this.calendarInner);
this.calendarPreviousMenu.addEvent('click', this.prevMonth.bind(this));
this.calendarNextMenu.addEvent('click', this.nextMonth.bind(this));
if(Browser.ie6){
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(Browser.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(){
clearTimeout(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;
}
clearTimeout(this._updateFirstCalendarTimer);
clearTimeout(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.set("html", 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.set("html", 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, callback, bind){
this._callback = callback;
this._bind = bind;
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);
},
getBind : function(){
return this._bind;
},
getCallBackMethod : function () {
return this._callback;
},
/**
* 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.setDate(1);
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.setDate(1);
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);
//BookingCalendar.implement(new Options);
var SynergeeCalendarMonth = new Class({
Implements : [Events, Options],
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').inject(this.calendarFirstMonthContainer);
this.calendarTitleRow = new Element('div',{}).addClass('CalendarTitleRow').inject(this.calendarHeaders);
this.calendarTitle  = new Element('div',{}).addClass('CalendarTitle').inject(this.calendarTitleRow);
this.calendarWeekDaysHeader = new Element('div').addClass('WeekDaysHeader').inject(this.calendarHeaders);
this.calendarContent = new Element('div',{}).addClass('CalendarContent').inject(this.calendarFirstMonthContainer);
this.calendarContentScroller = new Element('div', {}).addClass('CalendarContentScroller').inject(this.calendarContent);
this.calendarContent.addEvent('click', this._onClick.bind(this));
//        this.fxScroll = new Fx.Styles(this.calendarContentScroller,  {duration: 100, transition: Fx.Transitions.linear});
this.fxScroll = new Fx.Morph(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').inject(this.calendarWeekDaysHeader);
dayName = dayName.replace(/"/g, '');
dayTitle.set("html", dayName.substr(0,2));
}
for(var l = 0; l < 6; l++){
var line = new Element('div').addClass('WeekElement').inject(this.calendarContentScroller);
for(i = 0; i < 7; i++){
var day = new Element('div').addClass('DayElement').inject(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.has(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++) {
if (line.getChildren()[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.set("html", dayElement.date);
dayElement.removeClass('MainDate');
dayElement.removeClass('NotCurrentMonth');
if ((validDates.has(dayElement.year + '-' + dayElement.month + '-' + dayElement.date) )) {
dayElement.addClass('Component-List-Item');
dayElement.removeClass('Component-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');
dayElement.removeClass('Component-List-Item');
dayElement.valid = false;
}
if (dayElement.month != this.month) {
dayElement.addClass('NotCurrentMonth');
}
}
d.setDate(d.getDate() + 1);
}
}
},
_onClick : function(e){
if(Browser.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);
//SynergeeCalendarMonth.implement(new Options);
/**
* 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 BookingList = new Class({
Implements: Events,
/**
* This is the initialization function
* @param Element eListElement The main list element
* @param sOptionsSelector The options selector
*/
initialize : function(eListElement, values,  sOptionsSelector, sButtonSelector) {
this._list = eListElement;
this._listElement = eListElement;
this._buttonSelector = sButtonSelector;
this._values = null;
if(values)
this._values = values;
this._optionsSelector = sOptionsSelector;
this._listOptions = new Array();
this._selected = null;
this._listChangeElement = null;
this._listChangeHandler = null;
this.updateListOptions(this._list, this._values);
},
/**
*
*/
updateListOptions : function (eListElement, values, sOptionsSelector, eButton) {
if (eListElement){
this._list = eListElement;
}
if(this._list.get('tag') != 'select' && this._list.getElement('select')){
this._list = this._list.getElement('select');
}
if (sOptionsSelector)
this._optionsSelector = sOptionsSelector;
if (values){
this._values = values;
}else {
this._values = null;
}
if(this._buttonSelector && this._list.getElement(this._buttonSelector)){
this._button = new BookingListButton(this._list.getElement(this._buttonSelector));
this._button.addEvent('click', function(){
}.bind(this));
}
this._listOptions = new Array();
if (this._listChangeElement && this._listChangeHandler) {
this._listChangeElement.removeEvent('change', this._listChangeHandler);
}
this._listChangeElement = this._list;
this._listChangeHandler = function(item, index){
this.setValue(this._list.get('value'));
}.bind(this);
this._list.addEvent('change', this._listChangeHandler);
var optionsElements = this._list.getElements(this._optionsSelector);
for (var i = 0; i < optionsElements.length; i++) {
var value = (this._values ? this._values[i] : optionsElements[i].getAttribute('value'));
var listItem = new BookingListItem(value, optionsElements[i]);
this._listOptions.push(listItem);
listItem.addEvent('selected', function (e) {
if (!this._selected || this._selected != e) {
this._selected = e;
for (var j = 0; j < this._listOptions.length; j++) {
if (this._listOptions[j] != this._selected)
this._listOptions[j].setSelected(false);
}
if (this._button) {
if (this._selected.getValue() && this._selected.getValue() != '') {
this._button.setText(this._selected.getText());
} else {
this._button.reset();
}
}
this.fireEvent('change');
}
}.bind(this));
}
/*if(this._list.hasClass('item-selector')){
this._list.addEvent('change', function(){
this.setValue(this._list.getSelected()[0].getAttribute('value'));
this.fireEvent('change');
}.bind(this));
}else {
this._listElement = this._list.getElement('.item-selector');
this._listElement.addEvent('change', function(){
this.setValue(this._listElement.getSelected()[0].getAttribute('value'));
this.fireEvent('change');
}.bind(this));
}*/
},
setValidOptions : function (validOptions) {
this._listOptions.each(function(option, index){
option.setIsValid(validOptions.contains(option.getValue()));
}.bind(this));
},
/**
*  Return the selected item
*
*  @return BookingListItem The list item
*/
getSelectedItem : function () {
return this._selected;
},
/**
*  Return the selected item
*
*  @return BookingListItem The list item
*/
getValue : function () {
return this._selected.getValue();
},
/**
* Set selected the value
* @param value
* @return true if the value is found
*/
setValue : function(value) {
var valueFound = false;
for(var i = 0; i < this._listOptions.length; i++) {
if(this._listOptions[i].getValue() == value){
this._listOptions[i].setSelected(true);
this._selected = this._listOptions[i];
valueFound = true;
}
}
if(!valueFound){
for (var j = 0; j < this._listOptions.length; j++) {
this._listOptions[j].setSelected(false);
}
}
return valueFound;
}
});
var BookingListItem = new Class({
Implements: Events,
/**
* This is the initialization function
* @param value String The list item value
* @param element Element The options selector
*/
initialize : function(value, element) {
this._value = value;
this._element = element;
this._originalText = this._text = element.get('html');
this._isValid = true;
if (this._element.get('tag') != 'option') {
this._element.addEvent('click', function() {
if (this._isValid) {
this.setSelected(true);
} else {
this.setSelected(false);
}
}.bind(this));
}
},
/**
* Return the item value
*
* @return string The value
*/
getValue : function () {
return this._value;
},
/**
*  Set the validity status
*/
setIsValid : function (isValid){
this._isValid = isValid;
if(this._isValid) {
this._element.removeAttribute('disabled');
} else {
this._element.setAttribute('disabled', 'disabled');
}
},
/**
* Return true if valid
*/
getIsValid : function() {
return this._isValid;
},
/**
* Return list item text value
*
* @return String the item text value
*/
getText : function () {
return this._text;
},
/**
* Set the item selected
*
* @param boolean selected True if the item should be selected
*/
setSelected : function (selected) {
if(this._selected != selected) {
this._selected = selected;
if (this._selected) {
if (this._element.get('tag') == 'option') {
this._element.setAttribute('selected', 'selected');
}
this._element.addClass('selected');
this.fireEvent('selected', this);
} else {
if (this._element.get('tag') == 'option') {
this._element.removeAttribute('selected');
}
this._element.removeClass('selected');
}
}
}
});
var BookingListButton = new Class({
Implements: Events,
/**
* This is the initialization function
* @param Element element The button Element
*/
initialize : function(element) {
this._button = element;
this._originalText = element.get('html');
this._button.addEvent('click', function(){
this.fireEvent('click');
}.bind(this));
},
setText : function(text) {
this._button.set('html', text);
},
reset : function () {
this._button.set('html', this._originalText);
}
});
/**
* 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 BookingRequest = new Class({
Extends: Request,
success: function(text, xml){
this.onSuccess(text, xml);
}
});
/**
* 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 BookingTemplateObject = new Class({
Implements: Options,
options: {
element : null,
selector : '',
directive : null
},
/**
* This is the initialization function
*/
initialize : function(options) {
this.setOptions(options);
},
getElement : function() {
return this.options.element;
},
getDirective : function() {
return this.options.directive;
},
getSelector : function() {
return this.options.selector;
}
});
/*
---
name: Chosen
description: Creates a Picker, which can be used for anything
authors: Patrick Filler, Jules Janssen, Jonnathan Soares
requires: [Core/*, More/Locale]
provides: Chosen
...
*/
Elements.implement({
chosen: function(data, options){
if(Browser.ie7) {
return;
}
return this.each(function(el){
if (!el.hasClass("chzn-done")) {
return new Chosen(el, data, options);
}
});
}
});
var Chosen = new Class({
active_field: false,
mouse_on_container: false,
results_showing: false,
result_highlighted: null,
result_single_selected: null,
choices: 0,
initialize: function(elmn){
this.click_test_action = this.test_active_click.bind(this);
this.form_field = elmn;
this.is_multiple = this.form_field.multiple;
this.is_rtl = this.form_field.hasClass("chzn-rtl");
this.set_up_html();
this.register_observers();
},
set_up_html: function(){
var container_div, dd_top, dd_width, sf_width;
if (!this.form_field.id) this.form_field.id = String.uniqueID();
this.container_id = this.form_field.id.replace(/(:|\.)/g, '_') + "_chzn";
this.f_width = this.form_field.getCoordinates().width;
this.default_text = this.form_field.get('data-placeholder') ? this.form_field.get('data-placeholder') : Locale.get('Chosen.placeholder', this.form_field.multiple);
container_div = new Element('div', {
'id': 		this.container_id,
'class': 	'chzn-container'+ (this.is_rtl ? ' chzn-rtl' : '')
}).setStyle('width', this.f_width);
if (this.is_multiple){
container_div.set('html', '<ul class="chzn-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" style="width:25px;" /></li></ul><div class="chzn-drop" style="left:-9000px;"><ul class="chzn-results"></ul></div>');
} else {
container_div.set('html', '<a href="javascript:void(0)" class="chzn-single"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chzn-drop" style="left:-9000px;"><div class="chzn-search"><input type="text" /></div><ul class="chzn-results"></ul></div>');
}
this.form_field.setStyle('display', 'none').grab(container_div, 'after');
this.container = document.id(this.container_id);
this.container.addClass("chzn-container-" + (this.is_multiple ? "multi" : "single"));
this.dropdown = this.container.getElement('div.chzn-drop');
dd_top = this.container.getCoordinates().height;
dd_width = this.f_width - this.dropdown.get_side_border_padding();
this.dropdown.setStyles({
'width': 	dd_width,
'top': 		dd_top
});
this.search_field = this.container.getElement('input');
this.search_results = this.container.getElement('ul.chzn-results');
this.search_field_scale();
this.search_no_results = this.container.getElement('li.no-results');
if (this.is_multiple){
this.search_choices = this.container.getElement('ul.chzn-choices');
this.search_container = this.container.getElement('li.search-field');
} else {
this.search_container = this.container.getElement('div.chzn-search');
this.selected_item = this.container.getElement('.chzn-single');
sf_width = dd_width - this.search_container.get_side_border_padding() - this.search_field.get_side_border_padding();
this.search_field.setStyle('width', sf_width);
}
this.results_build();
this.set_tab_index();
},
register_observers: function(){
this.container.addEvents({
click: this.container_click.bind(this),
mouseenter: this.mouse_enter.bind(this),
mouseleave: this.mouse_leave.bind(this)
});
this.search_results.addEvents({
click: this.search_results_click.bind(this),
mouseover: this.search_results_mouseover.bind(this),
mouseout: this.search_results_mouseout.bind(this)
});
this.form_field.addEvent("liszt:updated", this.results_update_field.bind(this));
this.search_field.addEvents({
blur: this.input_blur.bind(this),
keyup: this.keyup_checker.bind(this),
keydown: this.keydown_checker.bind(this)
});
if (this.is_multiple){
this.search_choices.addEvent("click", this.choices_click.bind(this));
this.search_field.addEvent("focus", this.input_focus.bind(this));
} else {
this.selected_item.addEvent("focus", this.activate_field.bind(this));
}
},
container_click: function(evt){
if (!this.pending_destroy_click){
if (!this.active_field){
if (this.is_multiple){
this.search_field.value = '';
}
document.addEvent('click', this.click_test_action);
this.results_toggle();
}else if (!this.is_multiple && evt && (evt.target === this.selected_item || evt.target.getParents('a.chzn-single').length)){
document.addEvent('click', this.click_test_action);
evt.preventDefault();
this.results_show();
}
this.activate_field();
} else {
this.pending_destroy_click = false;
}
if (evt && evt.type === "click"){
evt.stopPropagation();
}
},
mouse_enter: function(){
this.mouse_on_container = true;
},
mouse_leave: function(){
this.mouse_on_container = false;
},
input_focus: function(evt){
if (!this.active_field){
setTimeout(this.container_click.bind(this), 50);
}
},
input_blur: function(evt){
if (!this.mouse_on_container){
this.active_field = false;
setTimeout(this.blur_test.bind(this), 100);
}
},
blur_test: function(evt){
if (!this.active_field && this.container.hasClass("chzn-container-active")){
this.close_field();
}
},
close_field: function(){
document.removeEvent('click', this.click_test_action);
if (!this.is_multiple){
this.selected_item.set('tabindex', this.search_field.get('tabindex'));
this.search_field.set('tabindex', -1);
}
this.active_field = false;
this.results_hide();
this.container.removeClass("chzn-container-active");
this.winnow_results_clear();
this.clear_backstroke();
this.show_search_field_default();
this.search_field_scale();
},
activate_field: function(){
if (!this.is_multiple && !this.active_field){
this.search_field.set('tabindex', this.selected_item.get('tabindex'));
this.selected_item.set('tabindex', -1);
}
this.container.addClass("chzn-container-active");
this.active_field = true;
this.search_field.set('value', this.search_field.get('value'));
this.search_field.focus();
},
test_active_click: function(evt){
if (evt.target.getParents('#' + this.container_id).length){
this.active_field = true;
} else {
this.close_field();
}
},
results_build: function(){
this.parsing = true;
this.results_data = this.form_field.select_to_array();
if (this.is_multiple && this.choices > 0){
this.search_choices.getElements("li.search-choice").destroy();
this.choices = 0;
}else if (!this.is_multiple){
this.selected_item.getElements("span").set('text', this.default_text);
}
var content = '';
this.results_data.each(function(data){
if (data.group){
content += this.result_add_group(data);
}else if (!data.empty){
content += this.result_add_option(data);
if (data.selected && this.is_multiple){
this.choice_build(data);
}else if (data.selected && !this.is_multiple){
this.selected_item.getElements("span").set('text', data.text);
}
}
}, this);
this.show_search_field_default();
this.search_field_scale();
this.search_results.set('html', content);
this.parsing = false;
},
result_add_group: function(group){
if (!group.disabled){
group.dom_id =  this.container_id + "_g_" + group.array_index;
return '<li id="' + group.dom_id + '" class="group-result"><div>'+ group.label + '</div></li>';
} else {
return '';
}
},
result_add_option: function(option){
var classes;
if (!option.disabled){
option.dom_id =  this.container_id + "_o_" + option.array_index;
classes = option.selected && this.is_multiple ? [] : ["active-result"];
if (option.selected){
classes.push("result-selected");
}
if (option.group_array_index != null){
classes.push("group-option");
}
return '<li id="' + option.dom_id + '" class="' + classes.join(' ') + '"><div>'+ option.html + '</div></li>';
} else {
return '';
}
},
results_update_field: function(){
this.result_clear_highlight();
this.result_single_selected = null;
this.results_build();
},
result_do_highlight: function(el){
var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
if (el){
this.result_clear_highlight();
this.result_highlight = el;
this.result_highlight.addClass("highlightened");
maxHeight = parseInt(this.search_results.getStyle("maxHeight"), 10);
visible_top = this.search_results.getScroll().y;
visible_bottom = maxHeight + visible_top;
high_top = this.result_highlight.getPosition(this.search_results).y + this.search_results.getScroll().y;
high_bottom = high_top + this.result_highlight.getCoordinates().height;
if (high_bottom >= visible_bottom){
this.search_results.scrollTo(0, (high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
}else if (high_top < visible_top){
this.search_results.scrollTo(0, high_top);
}
}
},
result_clear_highlight: function(){
if (this.result_highlight){
this.result_highlight.removeClass("highlightened");
}
this.result_highlight = null;
},
results_toggle: function(){
if (this.results_showing) {
this.results_hide();
} else {
this.results_show();
}
},
results_show: function(){
var dd_top;
if (!this.is_multiple){
this.selected_item.addClass("chzn-single-with-drop");
if (this.result_single_selected){
this.result_do_highlight(this.result_single_selected);
}
}
dd_top = this.is_multiple ? this.container.getCoordinates().height : this.container.getCoordinates().height - 1;
this.dropdown.setStyles({
"top": dd_top,
"left": 0
});
this.results_showing = true;
this.search_field.focus();
this.search_field.set('value', this.search_field.get('value'));
this.winnow_results();
},
results_hide: function(){
if (!this.is_multiple){
this.selected_item.removeClass("chzn-single-with-drop");
}
this.result_clear_highlight();
this.dropdown.setStyle('left', -9000);
this.results_showing = false;
},
set_tab_index: function(el){
var ti;
if (this.form_field.get('tabindex')){
ti = this.form_field.get('tabindex');
this.form_field.set('tabindex', -1);
if (this.is_multiple){
this.search_field.set('tabindex', ti);
} else {
this.selected_item.set('tabindex', ti);
this.search_field.set('tabindex', -1);
}
}
},
show_search_field_default: function(){
if (this.is_multiple && this.choices < 1 && !this.active_field){
this.search_field.set('value', this.default_text);
this.search_field.addClass("default");
} else {
this.search_field.set('value', "");
this.search_field.removeClass("default");
}
},
search_results_click: function(evt){
var target = evt.target.hasClass("active-result") ? evt.target : evt.target.getParent(".active-result");
if (target){
this.result_highlight = target;
this.result_select();
}
},
search_results_mouseover: function(evt){
var target = evt.target.hasClass("active-result") ? evt.target : evt.target.getParent(".active-result");
if (target){
this.result_do_highlight(target);
}
},
search_results_mouseout: function(evt){
if (evt.target.hasClass("active-result") || evt.target.getParent('.active-result')){
this.result_clear_highlight();
}
},
choices_click: function(evt){
evt.preventDefault();
if (this.active_field && !(evt.target.hasClass("search-choice") || evt.target.getParent('.search-choice')) && !this.results_showing){
this.results_show();
}
},
choice_build: function(item){
var choice_id = this.container_id + "_c_" + item.array_index;
this.choices += 1;
var el = new Element('li', {'id': choice_id})
.addClass('search-choice')
.set('html', '<span>' + item.html + '</span><a href="#" class="search-choice-close" rel="' + item.array_index + '"></a>');
this.search_container.grab(el, 'before');
document.id(choice_id).getElement("a")
.addEvent('click', this.choice_destroy_link_click.bind(this));
},
choice_destroy_link_click: function(evt){
evt.preventDefault();
this.pending_destroy_click = true;
this.choice_destroy(evt.target);
},
choice_destroy: function(link){
this.choices -= 1;
this.show_search_field_default();
if (this.is_multiple && this.choices > 0 && this.search_field.value.length < 1){
this.results_hide();
}
this.result_deselect(link.get("rel"));
link.getParent('li').destroy();
},
result_select: function(){
var high, high_id, item, position;
if (this.result_highlight){
high = this.result_highlight;
high_id = high.get("id");
this.result_clear_highlight();
high.addClass("result-selected");
if (this.is_multiple){
this.result_deactivate(high);
} else {
this.result_single_selected = high;
}
position = high_id.substr(high_id.lastIndexOf("_") + 1);
item = this.results_data[position];
item.selected = true;
this.form_field.options[item.options_index].selected = true;
if (this.is_multiple){
this.choice_build(item);
} else {
this.selected_item.getElement("span").set('text', item.text);
}
this.results_hide();
this.search_field.set('value', "");
this.form_field.fireEvent("change");
this.search_field_scale();
}
},
result_activate: function(el){
el.addClass("active-result").setStyle('display', 'block');
},
result_deactivate: function(el){
el.removeClass("active-result").setStyle('display', 'none');
},
result_deselect: function(pos){
var result, result_data;
result_data = this.results_data[pos];
result_data.selected = false;
this.form_field.options[result_data.options_index].selected = false;
result = document.id( this.container_id + "_o_" + pos);
result.removeClass("result-selected").addClass("active-result").setStyle('display', 'block');
this.result_clear_highlight();
this.winnow_results();
this.form_field.fireEvent("change");
this.search_field_scale();
},
results_search: function(evt){
if (this.results_showing){
this.winnow_results();
} else {
this.results_show();
}
},
winnow_results: function(){
var found, option, parts, regex, result_id, results, searchText, startpos, text, zregex;
this.no_results_clear();
results = 0;
searchText = this.search_field.get('value') === this.default_text ? "" : new Element('div', {text: this.search_field.get('value').trim()}).get('html');
regex = new RegExp('^' + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
this.results_data.each(function(option){
if (!option.disabled && !option.empty){
if (option.group){
document.id(option.dom_id).setStyle('display', 'none');
}else if (!(this.is_multiple && option.selected)){
found = false;
result_id = option.dom_id
if (regex.test(option.html)){
found = true;
results += 1;
}else if (option.html.indexOf(" ") >= 0 || option.html.indexOf("[") === 0){
parts = option.html.replace(/\[|\]/g, "").split(" ");
if (parts.length){
parts.each(function(part){
if (regex.test(part)){
found = true;
results += 1;
}
});
}
}
if (found){
if (searchText.length){
startpos = option.html.search(zregex);
text = option.html.substr(0, startpos + searchText.length) + '</em>' + option.html.substr(startpos + searchText.length);
text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
} else {
text = option.html;
}
if (document.id(result_id).get('html') !== text){
document.id(result_id).set('html', text);
}
this.result_activate(document.id(result_id));
if (option.group_array_index != null){
document.id(this.results_data[option.group_array_index].dom_id).setStyle('display', 'block');
}
} else {
if (this.result_highlight && result_id === this.result_highlight.get('id')){
this.result_clear_highlight();
}
this.result_deactivate(document.id(result_id));
}
}
}
}, this);
if (results < 1 && searchText.length){
this.no_results(searchText);
} else {
this.winnow_results_set_highlight();
}
},
winnow_results_clear: function(){
this.search_field.set('value', '');
this.search_results.getElements("li").each(function(li){
li.hasClass("group-result") ? li.setStyle('display', 'block') : !this.is_multiple || !li.hasClass("result-selected") ? this.result_activate(li) : void 0;
}, this);
},
winnow_results_set_highlight: function(){
var do_high;
if (!this.result_highlight){
do_high = this.search_results.getElement(".active-result");
if (do_high){
this.result_do_highlight(do_high);
}
}
},
no_results: function(terms){
var no_results_html = new Element('li', {'class': 'no-results'}).set('html', Locale.get('Chosen.noResults')+' "<span></span>"');
no_results_html.getElement("span").set('html', terms);
this.search_results.grab(no_results_html);
},
no_results_clear: function(){
this.search_results.getElements(".no-results").destroy();
},
keydown_arrow: function(){
var first_active, next_sib;
if (!this.result_highlight){
first_active = this.search_results.getElement("li.active-result");
if (first_active){
this.result_do_highlight(first_active);
}
}else if (this.results_showing){
next_sib = this.result_highlight.getNext("li.active-result");
if (next_sib){
this.result_do_highlight(next_sib);
}
}
if (!this.results_showing){
this.results_show();
}
},
keyup_arrow: function(){
if (!this.results_showing && !this.is_multiple){
this.results_show();
}else if (this.result_highlight){
var prev_sibs = this.result_highlight.getAllPrevious("li.active-result");
if (prev_sibs.length){
this.result_do_highlight(prev_sibs[0]);
} else {
if (this.choices > 0){
this.results_hide();
}
this.result_clear_highlight();
}
}
},
keydown_backstroke: function(){
if (this.pending_backstroke){
this.choice_destroy(this.pending_backstroke.getElement("a"));
this.clear_backstroke();
} else {
this.pending_backstroke = this.search_choices.getLast("li.search-choice");
this.pending_backstroke.addClass("search-choice-focus");
}
},
clear_backstroke: function(){
if (this.pending_backstroke){
this.pending_backstroke.removeClass("search-choice-focus");
}
this.pending_backstroke = null;
},
keyup_checker: function(evt){
this.search_field_scale();
switch (evt.key){
case 'backspace':
if (this.is_multiple && this.backstroke_length < 1 && this.choices > 0){
this.keydown_backstroke();
}else if (!this.pending_backstroke){
this.result_clear_highlight();
this.results_search();
}
break;
case 'enter':
evt.preventDefault();
if (this.results_showing){
this.result_select();
}
break;
case 'esc':
if (this.results_showing) {
this.results_hide();
}
break;
case 'tab':
case 'up':
case 'down':
case 'shift':
break;
default:
this.results_search();
}
},
keydown_checker: function(evt){
this.search_field_scale();
if (evt.key !== 'backspace' && this.pending_backstroke){
this.clear_backstroke();
}
switch(evt.key){
case 'backspace':
this.backstroke_length = this.search_field.value.length;
break;
case 'tab':
this.mouse_on_container = false;
break;
case 'enter':
evt.preventDefault();
break;
case 'up':
evt.preventDefault();
this.keyup_arrow();
break;
case 'down':
this.keydown_arrow();
break;
}
},
search_field_scale: function(){
var dd_top, div, h, style, style_block, styles, w, _i, _len;
if (this.is_multiple){
h = 0;
w = 0;
style_block = {
position: 'absolute',
visibility: 'hidden'
};
styles = this.search_field.getStyles('font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing');
Object.merge(style_block, styles);
div = new Element('div', {
'styles': style_block
});
div.set('text', this.search_field.get('value'));
document.body.grab(div);
w = div.getCoordinates().width + 25;
div.destroy();
if (w > this.f_width - 10) {
w = this.f_width - 10;
}
this.search_field.setStyle('width', w);
dd_top = this.container.getCoordinates().height;
this.dropdown.setStyle('top', dd_top);
}
}
});
Element.implement({
get_side_border_padding: function(){
var styles = this.getStyles('padding-left', 'padding-right', 'border-left-width', 'border-right-width');
var notNull = Object.filter(styles, function(value){
return (typeof(value) == 'string');
});
var mapped = Object.map(notNull, function(s){ return s.toInt();});
var array = Object.values(mapped);
var result = 0, l = array.length;
if (l){
while (l--) result += array[l];
}
return result;
},
select_to_array: function(){
var parser = new SelectParser();
this.getChildren().each(function(child){
parser.add_node(child);
});
return parser.parsed;
}
});
var SelectParser = new Class({
options_index: 0,
parsed: [],
initialize: function(){
this.options_index = 0;
this.parsed = [];
},
add_node: function(child){
if (child.nodeName === "OPTGROUP"){
this.add_group(child);
} else {
this.add_option(child);
}
},
add_group: function(group){
var group_position = this.parsed.length;
this.parsed.push({
array_index: group_position,
group: true,
label: group.label,
children: 0,
disabled: group.disabled
});
group.getChildren().each(function(option){
this.add_option(option, group_position, group.disabled);
}, this);
},
add_option: function(option, group_position, group_disabled){
if (option.nodeName === "OPTION") {
if (option.text !== ""){
if (group_position != null) {
this.parsed[group_position].children += 1;
}
this.parsed.push({
array_index: this.parsed.length,
options_index: this.options_index,
value: option.value,
text: option.text,
html: option.innerHTML,
selected: option.selected,
disabled: group_disabled === true ? group_disabled : option.disabled,
group_array_index: group_position
});
} else {
this.parsed.push({
array_index: this.parsed.length,
options_index: this.options_index,
empty: true
});
}
this.options_index += 1;
}
}
});
/*!
PURE Unobtrusive Rendering Engine for HTML
Licensed under the MIT licenses.
More information at: http://www.opensource.org
Copyright (c) 2011 Michael Cvilic - BeeBole.com
Thanks to Rog Peppe for the functional JS jump
revision: 2.71
*/
var $p, pure = $p = function(){
var sel = arguments[0],
ctxt = false;
if(typeof sel === 'string'){
ctxt = arguments[1] || false;
}else if(sel && !sel[0] && !sel.length){
sel = [sel];
}
return $p.core(sel, ctxt);
};
$p.core = function(sel, ctxt, plugins){
//get an instance of the plugins
var templates = [];
plugins = plugins || getPlugins();
//search for the template node(s)
switch(typeof sel){
case 'string':
templates = plugins.find(ctxt || document, sel);
if(templates.length === 0) {
error('The template "' + sel + '" was not found');
}
break;
case 'undefined':
error('The root of the template is undefined, check your selector');
break;
default:
templates = sel;
}
for(var i = 0, ii = templates.length; i < ii; i++){
plugins[i] = templates[i];
}
plugins.length = ii;
// set the signature string that will be replaced at render time
var Sig = '_s' + Math.floor( Math.random() * 1000000 ) + '_',
// another signature to prepend to attributes and avoid checks: style, height, on[events]...
attPfx = '_a' + Math.floor( Math.random() * 1000000 ) + '_',
// rx to parse selectors, e.g. "+tr.foo[class]"
selRx = /^(\+)?([^\@\+]+)?\@?([^\+]+)?(\+)?$/,
// set automatically attributes for some tags
autoAttr = {
IMG:'src',
INPUT:'value'
},
// check if the argument is an array - thanks salty-horse (Ori Avtalion)
isArray = Array.isArray ?
function(o) {
return Array.isArray(o);
} :
function(o) {
return Object.prototype.toString.call(o) === "[object Array]";
};
/* * * * * * * * * * * * * * * * * * * * * * * * * *
core functions
* * * * * * * * * * * * * * * * * * * * * * * * * */
// error utility
function error(e){
if(typeof console !== 'undefined'){
console.log(e);
debugger;
}
throw('pure error: ' + e);
}
//return a new instance of plugins
function getPlugins(){
var plugins = $p.plugins,
f = function(){};
f.prototype = plugins;
// do not overwrite functions if external definition
f.prototype.compile    = plugins.compile || compile;
f.prototype.render     = plugins.render || render;
f.prototype.autoRender = plugins.autoRender || autoRender;
f.prototype.find       = plugins.find || find;
// give the compiler and the error handling to the plugin context
f.prototype._compiler  = compiler;
f.prototype._error     = error;
return new f();
}
// returns the outer HTML of a node
function outerHTML(node){
// if IE, Chrome take the internal method otherwise build one
return node.outerHTML || (
function(n){
var div = document.createElement('div'), h;
div.appendChild( n.cloneNode(true) );
h = div.innerHTML;
div = null;
return h;
})(node);
}
// returns the string generator function
function wrapquote(qfn, f){
return function(ctxt){
return qfn('' + f.call(ctxt.item || ctxt.context, ctxt));
};
}
// default find using querySelector when available on the browser
function find(n, sel){
if(typeof n === 'string'){
sel = n;
n = false;
}
if(typeof document.querySelectorAll !== 'undefined'){
return (n||document).querySelectorAll( sel );
}else{
return error('You can test PURE standalone with: iPhone, FF3.5+, Safari4+ and IE8+\n\nTo run PURE on your browser, you need a JS library/framework with a CSS selector engine');
}
}
// create a function that concatenates constant string
// sections (given in parts) and the results of called
// functions to fill in the gaps between parts (fns).
// fns[n] fills in the gap between parts[n-1] and parts[n];
// fns[0] is unused.
// this is the inner template evaluation loop.
function concatenator(parts, fns){
return function(ctxt){
var strs = [ parts[ 0 ] ],
n = parts.length,
fnVal, pVal, attLine, pos;
for(var i = 1; i < n; i++){
fnVal = fns[i].call( this, ctxt );
pVal = parts[i];
// if the value is empty and attribute, remove it
if(fnVal === ''){
attLine = strs[ strs.length - 1 ];
if( ( pos = attLine.search( /[^\s]+=\"?$/ ) ) > -1){
strs[ strs.length - 1 ] = attLine.substring( 0, pos );
pVal = pVal.substr( 1 );
}
}
strs[ strs.length ] = fnVal;
strs[ strs.length ] = pVal;
}
return strs.join('');
};
}
// parse and check the loop directive
function parseloopspec(p){
var m = p.match( /^(\w+)\s*<-\s*(\S+)?$/ );
if(m === null){
error('bad loop spec: "' + p + '"');
}
if(m[1] === 'item'){
error('"item<-..." is a reserved word for the current running iteration.\n\nPlease choose another name for your loop.');
}
if( !m[2] || (m[2] && (/context/i).test(m[2]))){ //undefined or space(IE)
m[2] = function(ctxt){return ctxt.context;};
}
return {name: m[1], sel: m[2]};
}
// parse a data selector and return a function that
// can traverse the data accordingly, given a context.
function dataselectfn(sel){
if(typeof(sel) === 'function'){
return sel;
}
//check for a valid js variable name with hyphen(for properties only), $, _ and :
var m = sel.match(/^[a-zA-Z\$_\@][\w\$:-]*(\.[\w\$:-]*[^\.])*$/);
if(m === null){
var found = false, s = sel, parts = [], pfns = [], i = 0, retStr;
// check if literal
if(/\'|\"/.test( s.charAt(0) )){
if(/\'|\"/.test( s.charAt(s.length-1) )){
retStr = s.substring(1, s.length-1);
return function(){ return retStr; };
}
}else{
// check if literal + #{var}
while((m = s.match(/#\{([^{}]+)\}/)) !== null){
found = true;
parts[i++] = s.slice(0, m.index);
pfns[i] = dataselectfn(m[1]);
s = s.slice(m.index + m[0].length, s.length);
}
}
if(!found){
return function(){ return sel; };
}
parts[i] = s;
return concatenator(parts, pfns);
}
m = sel.split('.');
return function(ctxt){
var data = ctxt.context || ctxt,
v = ctxt[m[0]],
i = 0;
if(v && v.item){
i += 1;
if(m[i] === 'pos'){
//allow pos to be kept by string. Tx to Adam Freidin
return v.pos;
}else{
data = v.item;
}
}
var n = m.length;
for(; i < n; i++){
if(!data){break;}
data = data[m[i]];
}
return (!data && data !== 0) ? '':data;
};
}
// wrap in an object the target node/attr and their properties
function gettarget(dom, sel, isloop){
var osel, prepend, selector, attr, append, target = [];
if( typeof sel === 'string' ){
osel = sel;
var m = sel.match(selRx);
if( !m ){
error( 'bad selector syntax: ' + sel );
}
prepend = m[1];
selector = m[2];
attr = m[3];
append = m[4];
if(selector === '.' || ( !selector && attr ) ){
target[0] = dom;
}else{
target = plugins.find(dom, selector);
}
if(!target || target.length === 0){
return error('The node "' + sel + '" was not found in the template:\n' + outerHTML(dom).replace(/\t/g,'  '));
}
}else{
// autoRender node
prepend = sel.prepend;
attr = sel.attr;
append = sel.append;
target = [dom];
}
if( prepend || append ){
if( prepend && append ){
error('append/prepend cannot take place at the same time');
}else if( isloop ){
error('no append/prepend/replace modifiers allowed for loop target');
}else if( append && isloop ){
error('cannot append with loop (sel: ' + osel + ')');
}
}
var setstr, getstr, quotefn, isStyle, isClass, attName, setfn;
if(attr){
isStyle = (/^style$/i).test(attr);
isClass = (/^class$/i).test(attr);
attName = isClass ? 'className' : attr;
setstr = function(node, s) {
node.setAttribute(attPfx + attr, s);
if (attName in node && !isStyle) {
try{node[attName] = '';}catch(e){} //FF4 gives an error sometimes
}
if (node.nodeType === 1) {
node.removeAttribute(attr);
isClass && node.removeAttribute(attName);
}
};
if (isStyle || isClass) {//IE no quotes special care
if(isStyle){
getstr = function(n){ return n.style.cssText; };
}else{
getstr = function(n){ return n.className;	};
}
}else {
getstr = function(n){ return n.getAttribute(attr); };
}
quotefn = function(s){ return s.replace(/\"/g, '&quot;'); };
if(prepend){
setfn = function(node, s){ setstr( node, s + getstr( node )); };
}else if(append){
setfn = function(node, s){ setstr( node, getstr( node ) + s); };
}else{
setfn = function(node, s){ setstr( node, s ); };
}
}else{
if (isloop) {
setfn = function(node, s) {
var pn = node.parentNode;
if (pn) {
//replace node with s
pn.insertBefore(document.createTextNode(s), node.nextSibling);
pn.removeChild(node);
}
};
} else {
if (prepend) {
setfn = function(node, s) { node.insertBefore(document.createTextNode(s), node.firstChild);	};
} else if (append) {
setfn = function(node, s) { node.appendChild(document.createTextNode(s));};
} else {
setfn = function(node, s) {
while (node.firstChild) { node.removeChild(node.firstChild); }
node.appendChild(document.createTextNode(s));
};
}
}
quotefn = function(s) { return s; };
}
return { attr: attr, nodes: target, set: setfn, sel: osel, quotefn: quotefn };
}
function setsig(target, n){
var sig = Sig + n + ':';
for(var i = 0; i < target.nodes.length; i++){
// could check for overlapping targets here.
target.set( target.nodes[i], sig );
}
}
// read de loop data, and pass it to the inner rendering function
function loopfn(name, dselect, inner, sorter, filter){
return function(ctxt){
var a = dselect(ctxt),
old = ctxt[name],
temp = { items : a },
filtered = 0,
length,
strs = [],
buildArg = function(idx, temp, ftr, len){
//keep the current loop. Tx to Adam Freidin
var save_pos = ctxt.pos,
save_item = ctxt.item,
save_items = ctxt.items;
ctxt.pos = temp.pos = idx;
ctxt.item = temp.item = a[ idx ];
ctxt.items = a;
//if array, set a length property - filtered items
typeof len !== 'undefined' &&  (ctxt.length = len);
//if filter directive
if(typeof ftr === 'function' && ftr.call(ctxt.item, ctxt) === false){
filtered++;
return;
}
strs.push( inner.call(ctxt.item, ctxt ) );
//restore the current loop
ctxt.pos = save_pos;
ctxt.item = save_item;
ctxt.items = save_items;
};
ctxt[name] = temp;
if( isArray(a) ){
length = a.length || 0;
// if sort directive
if(typeof sorter === 'function'){
a.sort(sorter);
}
//loop on array
for(var i = 0, ii = length; i < ii; i++){
buildArg(i, temp, filter, length - filtered);
}
}else{
if(a && typeof sorter !== 'undefined'){
error('sort is only available on arrays, not objects');
}
//loop on collections
for(var prop in a){
a.hasOwnProperty( prop ) && buildArg(prop, temp, filter);
}
}
typeof old !== 'undefined' ? ctxt[name] = old : delete ctxt[name];
return strs.join('');
};
}
// generate the template for a loop node
function loopgen(dom, sel, loop, fns){
var already = false, ls, sorter, filter, prop;
for(prop in loop){
if(loop.hasOwnProperty(prop)){
if(prop === 'sort'){
sorter = loop.sort;
continue;
}else if(prop === 'filter'){
filter = loop.filter;
continue;
}
if(already){
error('cannot have more than one loop on a target');
}
ls = prop;
already = true;
}
}
if(!ls){
error('Error in the selector: ' + sel + '\nA directive action must be a string, a function or a loop(<-)');
}
var dsel = loop[ls];
// if it's a simple data selector then we default to contents, not replacement.
if(typeof(dsel) === 'string' || typeof(dsel) === 'function'){
loop = {};
loop[ls] = {root: dsel};
return loopgen(dom, sel, loop, fns);
}
var spec = parseloopspec(ls),
itersel = dataselectfn(spec.sel),
target = gettarget(dom, sel, true),
nodes = target.nodes;
for(i = 0; i < nodes.length; i++){
var node = nodes[i],
inner = compiler(node, dsel);
fns[fns.length] = wrapquote(target.quotefn, loopfn(spec.name, itersel, inner, sorter, filter));
target.nodes = [node];		// N.B. side effect on target.
setsig(target, fns.length - 1);
}
return target;
}
function getAutoNodes(n, data){
var ns = n.getElementsByTagName('*'),
an = [],
openLoops = {a:[],l:{}},
cspec,
isNodeValue,
i, ii, j, jj, ni, cs, cj;
//for each node found in the template
for(i = -1, ii = ns.length; i < ii; i++){
ni = i > -1 ?ns[i]:n;
if(ni.nodeType === 1 && ni.className !== ''){
//when a className is found
cs = ni.className.split(' ');
// for each className
for(j = 0, jj=cs.length;j<jj;j++){
cj = cs[j];
// check if it is related to a context property
cspec = checkClass(cj, ni.tagName);
// if so, store the node, plus the type of data
if(cspec !== false){
isNodeValue = (/nodevalue/i).test(cspec.attr);
if(cspec.sel.indexOf('@') > -1 || isNodeValue){
ni.className = ni.className.replace('@'+cspec.attr, '');
if(isNodeValue){
cspec.attr = false;
}
}
an.push({n:ni, cspec:cspec});
}
}
}
}
function checkClass(c, tagName){
// read the class
var ca = c.match(selRx),
attr = ca[3] || autoAttr[tagName],
cspec = {prepend:!!ca[1], prop:ca[2], attr:attr, append:!!ca[4], sel:c},
i, ii, loopi, loopil, val;
// check in existing open loops
for(i = openLoops.a.length-1; i >= 0; i--){
loopi = openLoops.a[i];
loopil = loopi.l[0];
val = loopil && loopil[cspec.prop];
if(typeof val !== 'undefined'){
cspec.prop = loopi.p + '.' + cspec.prop;
if(openLoops.l[cspec.prop] === true){
val = val[0];
}
break;
}
}
// not found check first level of data
if(typeof val === 'undefined'){
val = dataselectfn(cspec.prop)(isArray(data) ? data[0] : data);
// nothing found return
if(val === ''){
return false;
}
}
// set the spec for autoNode
if(isArray(val)){
openLoops.a.push( {l:val, p:cspec.prop} );
openLoops.l[cspec.prop] = true;
cspec.t = 'loop';
}else{
cspec.t = 'str';
}
return cspec;
}
return an;
}
// returns a function that, given a context argument,
// will render the template defined by dom and directive.
function compiler(dom, directive, data, ans){
var fns = [], j, jj, cspec, n, target, nodes, itersel, node, inner, dsel, sels, sel, sl, i, h, parts,  pfns = [], p;
// autoRendering nodes parsing -> auto-nodes
ans = ans || data && getAutoNodes(dom, data);
if(data){
// for each auto-nodes
while(ans.length > 0){
cspec = ans[0].cspec;
n = ans[0].n;
ans.splice(0, 1);
if(cspec.t === 'str'){
// if the target is a value
target = gettarget(n, cspec, false);
setsig(target, fns.length);
fns[fns.length] = wrapquote(target.quotefn, dataselectfn(cspec.prop));
}else{
// if the target is a loop
itersel = dataselectfn(cspec.sel);
target = gettarget(n, cspec, true);
nodes = target.nodes;
for(j = 0, jj = nodes.length; j < jj; j++){
node = nodes[j];
inner = compiler(node, false, data, ans);
fns[fns.length] = wrapquote(target.quotefn, loopfn(cspec.sel, itersel, inner));
target.nodes = [node];
setsig(target, fns.length - 1);
}
}
}
}
// read directives
for(sel in directive){
if(directive.hasOwnProperty(sel)){
i = 0;
dsel = directive[sel];
sels = sel.split(/\s*,\s*/); //allow selector separation by quotes
sl = sels.length;
do{
if(typeof(dsel) === 'function' || typeof(dsel) === 'string'){
// set the value for the node/attr
sel = sels[i];
target = gettarget(dom, sel, false);
setsig(target, fns.length);
fns[fns.length] = wrapquote(target.quotefn, dataselectfn(dsel));
}else{
// loop on node
loopgen(dom, sel, dsel, fns);
}
}while(++i < sl);
}
}
// convert node to a string
h = outerHTML(dom);
// IE adds an unremovable "selected, value" attribute
// hard replace while waiting for a better solution
h = h.replace(/<([^>]+)\s(value\=""|selected)\s?([^>]*)>/ig, "<$1 $3>");
// remove attribute prefix
h = h.split(attPfx).join('');
// slice the html string at "Sig"
parts = h.split( Sig );
// for each slice add the return string of
for(i = 1; i < parts.length; i++){
p = parts[i];
// part is of the form "fn-number:..." as placed there by setsig.
pfns[i] = fns[ parseInt(p, 10) ];
parts[i] = p.substring( p.indexOf(':') + 1 );
}
return concatenator(parts, pfns);
}
// compile the template with directive
// if a context is passed, the autoRendering is triggered automatically
// return a function waiting the data as argument
function compile(directive, ctxt, template){
var rfn = compiler( ( template || this[0] ).cloneNode(true), directive, ctxt);
return function(context){
return rfn({context:context});
};
}
//compile with the directive as argument
// run the template function on the context argument
// return an HTML string
// should replace the template and return this
function render(ctxt, directive){
var fn = typeof directive === 'function' && directive, i = 0, ii = this.length;
for(; i < ii; i++){
this[i] = replaceWith( this[i], (fn || plugins.compile( directive, false, this[i] ))( ctxt, false ));
}
context = null;
return this;
}
// compile the template with autoRender
// run the template function on the context argument
// return an HTML string
function autoRender(ctxt, directive){
var fn = plugins.compile( directive, ctxt, this[0] );
for(var i = 0, ii = this.length; i < ii; i++){
this[i] = replaceWith( this[i], fn( ctxt, false));
}
context = null;
return this;
}
function replaceWith(elm, html) {
var ne,
ep = elm.parentNode,
depth = 0;
if(!ep){ //if no parents
ep = document.createElement('DIV');
ep.appendChild(elm);
}
switch (elm.tagName) {
case 'TBODY': case 'THEAD': case 'TFOOT':
html = '<TABLE>' + html + '</TABLE>';
depth = 1;
break;
case 'TR':
html = '<TABLE><TBODY>' + html + '</TBODY></TABLE>';
depth = 2;
break;
case 'TD': case 'TH':
html = '<TABLE><TBODY><TR>' + html + '</TR></TBODY></TABLE>';
depth = 3;
break;
}
tmp = document.createElement('SPAN');
tmp.style.display = 'none';
document.body.appendChild(tmp);
tmp.innerHTML = html;
ne = tmp.firstChild;
while (depth--) {
ne = ne.firstChild;
}
ep.insertBefore(ne, elm);
ep.removeChild(elm);
document.body.removeChild(tmp);
elm = ne;
ne = ep = null;
return elm;
}
return plugins;
};
$p.plugins = {};
$p.libs = {
dojo:function(){
if(typeof document.querySelector === 'undefined'){
$p.plugins.find = function(n, sel){
return dojo.query(sel, n);
};
}
},
domassistant:function(){
if(typeof document.querySelector === 'undefined'){
$p.plugins.find = function(n, sel){
return $(n).cssSelect(sel);
};
}
DOMAssistant.attach({
publicMethods : [ 'compile', 'render', 'autoRender'],
compile:function(directive, ctxt){
return $p([this]).compile(directive, ctxt);
},
render:function(ctxt, directive){
return $( $p([this]).render(ctxt, directive) )[0];
},
autoRender:function(ctxt, directive){
return $( $p([this]).autoRender(ctxt, directive) )[0];
}
});
},
jquery:function(){
if(typeof document.querySelector === 'undefined'){
$p.plugins.find = function(n, sel){
return jQuery(n).find(sel);
};
}
jQuery.fn.extend({
directives:function(directive){
this._pure_d = directive; return this;
},
compile:function(directive, ctxt){
return $p(this).compile(this._pure_d || directive, ctxt);
},
render:function(ctxt, directive){
return jQuery( $p( this ).render( ctxt, this._pure_d || directive ) );
},
autoRender:function(ctxt, directive){
return jQuery( $p( this ).autoRender( ctxt, this._pure_d || directive ) );
}
});
},
mootools:function(){
if(typeof document.querySelector === 'undefined'){
$p.plugins.find = function(n, sel){
return $(n).getElements(sel);
};
}
Element.implement({
compile:function(directive, ctxt){
return $p(this).compile(directive, ctxt);
},
render:function(ctxt, directive){
return $p([this]).render(ctxt, directive);
},
autoRender:function(ctxt, directive){
return $p([this]).autoRender(ctxt, directive);
}
});
},
prototype:function(){
if(typeof document.querySelector === 'undefined'){
$p.plugins.find = function(n, sel){
n = n === document ? n.body : n;
return typeof n === 'string' ? $$(n) : $(n).select(sel);
};
}
Element.addMethods({
compile:function(element, directive, ctxt){
return $p([element]).compile(directive, ctxt);
},
render:function(element, ctxt, directive){
return $p([element]).render(ctxt, directive);
},
autoRender:function(element, ctxt, directive){
return $p([element]).autoRender(ctxt, directive);
}
});
},
sizzle:function(){
if(typeof document.querySelector === 'undefined'){
$p.plugins.find = function(n, sel){
return Sizzle(sel, n);
};
}
},
sly:function(){
if(typeof document.querySelector === 'undefined'){
$p.plugins.find = function(n, sel){
return Sly(sel, n);
};
}
},
yui:function(){ //Thanks to https://github.com/soljin
if(typeof document.querySelector === 'undefined'){
YUI().use("node",function(Y){
$p.plugins.find = function(n, sel){
return Y.NodeList.getDOMNodes(Y.one(n).all(sel));
};
});
}
YUI.add("pure-yui",function(Y){
Y.Node.prototype.directives = function(directive){
this._pure_d = directive; return this;
};
Y.Node.prototype.compile = function(directive, ctxt){
return $p([this._node]).compile(this._pure_d || directive, ctxt);
};
Y.Node.prototype.render = function(ctxt, directive){
return Y.one($p([this._node]).render(ctxt, this._pure_d || directive));
};
Y.Node.prototype.autoRender = function(ctxt, directive){
return Y.one($p([this._node]).autoRender(ctxt, this._pure_d || directive));
};
},"0.1",{requires:["node"]});
}
};
// get lib specifics if available
(function(){
var libkey =
typeof dojo         !== 'undefined' && 'dojo' ||
typeof DOMAssistant !== 'undefined' && 'domassistant' ||
typeof jQuery       !== 'undefined' && 'jquery' ||
typeof MooTools     !== 'undefined' && 'mootools' ||
typeof Prototype    !== 'undefined' && 'prototype' ||
typeof Sizzle       !== 'undefined' && 'sizzle' ||
typeof Sly          !== 'undefined' && 'sly' ||
typeof YUI          !== 'undefined' && 'yui';
libkey && $p.libs[libkey]();
//for node.js
if(typeof exports !== 'undefined'){
exports.$p = $p;
}
})();/**
* 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 = new Class({
Implements: Events,
/**
* This is the initialization function
*/
initialize : function(oSchoolDTO,  oBooking) {
this._booking = this._parent = oBooking;
this._schoolDTO = oSchoolDTO;
this._customValues = new Hash();
// create the courses part
this.courses = new SchoolCourses(this._schoolDTO.schoolFixedDatesCourses, this._schoolDTO.schoolVariableDatesCourses, this._schoolDTO.schoolOptionalCourses, this);
this.accommodations = new SchoolAccommodations(this._schoolDTO.schoolAccommodations, this);
this.transfers = new SchoolTransfers(this._schoolDTO.schoolTransfers, this);
this.courses.addEvent('coursesUpdated', function() {
this.accommodations.refreshAccommodations();
this.refreshPrice();
}.bind(this));
this.courses.addEvent('heightModified', function() {
this.fireEvent('heightModified');
}.bind(this));
this.accommodations.addEvent('accommodationsUpdated', function() {
this.transfers.refreshTransfers();
this.checkMandatoryCourseAccommodations();
this.refreshPrice();
}.bind(this));
this.accommodations.addEvent('heightModified', function() {
this.fireEvent('heightModified');
}.bind(this));
this.transfers.addEvent('transfersUpdated', function() {
this.refreshPrice();
this.fireEvent('heightModified');
}.bind(this));
return '';
this._listContainer = new Element('div');
//        this._classNameBase = this._booking.getClassNameBase();
this._schoolPriceCalculatorDTO = oSchoolDTO;
this._translateDTO = {};
this.transfers = new SchoolTransfers(this._schoolPriceCalculatorDTO.schoolTransfers, this._translateDTO.transfers, this);
this.courses.addEvent('refreshPrice', function() {
this.transfers.refreshTransfers();
this.fireEvent('refreshPrice');
this.fireEvent('schoolUpdated');
}.bind(this));
this.courses.addEvent('heightModified', function() {
this.fireEvent('heightModified');
}.bind(this));
this.accommodations.addEvent('refreshAccommodations', function() {
this.transfers.refreshTransfers();
this.fireEvent('refreshPrice');
}.bind(this));
this.transfers.addEvent('refreshPrice', function() {
this.fireEvent('refreshPrice');
}.bind(this));
this.addEvent('refreshAccommodations', function() {
this.accommodations.refreshAccommodations('lists');
this.transfers.refreshTransfers();
this.checkMandatoryCourseAccommodations();
});
},
/**
* Return the courses manager
*/
getCoursesManager : function () {
return this.courses;
},
/**
* Return the courses manager
*/
getTransfersManager : function () {
return this.transfers;
},
/**
* Return the courses manager
*/
getAccommodationsManager : function () {
return this.accommodations;
},
refreshPrice : function ( ){
clearTimeout(this._refreshPrice);
this._refreshPrice = this.fireEvent.delay(300, this, 'refreshPrice')
},
getBooking : function(){
return this._booking;
},
/**
* 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");
this.courses.onCourseUpdated();
},
/**
* Check the mandatory accommodations
*
*
*/
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].getCourseValidDurations();
for(var i = 0; i < durations.length; i++){
if(parseInt(durations[i]) > parseInt(courseToCheck[0].getCourseDuration())){
courseToCheck[0].setCourseDuration(durations[i]);
//                                durations[i].getHtml().fireEvent('click');
break;
}
}
if(i == durations.length){
courseToCheck[0].deleteCourse();
}
}else{
courseToCheck[0].deleteCourse();
}
}*/
}
}
},
/**
* 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.getValidAddedCourses().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(true);
if (courses.length) {
switch (coursePosition) {
case -1 :
return courses.getLast().getCourseType() == 'fixed';
break;
default :
if (courses[coursePosition]) {
return courses[coursePosition].getCourseType() == 'fixed';
} 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._booking.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();
},
/**
* Returns the  parent
*
* @return Object the parent
*
*/
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 2011 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 = new Class({
Implements: Events,
/**
* This is the initialization function
*/
initialize : function(accommodationDetails, accommodationOptionDetails, oSchoolAccommodationsContainer) {
this._created = false;
this._translateDTO = {};
this._accommodationDetails = accommodationDetails;
this._accommodationOptionDetails = accommodationOptionDetails;
this._schoolAccommodations = oSchoolAccommodationsContainer;
this._booking = this._schoolAccommodations.getSchool().getBooking();
this._booking.addEvent('descriptionsUpdated', function(){
this.updateDescriptions();
}.bind(this));
this._dateFormat = this._booking.getDateFormat();
this._monthsTranslations = this._booking.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.refreshValidStartDates();
// check if it's the first accommodation :
if (this._schoolAccommodations.getAccommodations().length == 0 /**&& !attachedAccommodation**/) {
// if it is the first to be added, set the right date
// find the earliest start date
var startDate;
if (this._validStartDates.length) {
startDate = this._validStartDates[0];
}
if (startDate) {
this.setStartDate(startDate);
// find the longest duration
var duration;
for (var i = this._validDurations.length - 1; i >= 0; i--) {
duration = parseInt( this._validDurations[i]);
break;
}
if (duration) {
this.setDuration(duration);
}
}
}
},
/**
* Set the start date
*
*
* @param startDate
* @param additionalNightsBefore
*/
setStartDate : function(startDate, additionalNightsBefore) {
if(typeof(additionalNightsBefore)=='undefined'){
additionalNightsBefore = this._additionalNightsBefore;
}
if ((!this._accommodationStartDate || this._accommodationStartDate.toIso() != startDate.toIso()) || additionalNightsBefore != this._additionalNightsBefore) {
this._accommodationStartDate = startDate;
this._additionalNightsBefore = additionalNightsBefore;
this.updateStartDate();
this._onStartDateChange();
}
},
/**
* Set the duration
*
* @param integer the accommodation duration
*/
setDuration : function(duration){
if(parseInt(this._accommodationDuration) != parseInt(duration)){
// check if the duration is valid
if(this.getValidDurations().contains(parseInt(duration))){
this._accommodationDuration = duration;
this._onDurationChange();
}else {
this.deleteAccommodation();
}
}
},
/**
* Set the end date
*
* @param endDate
* @param additionalNightsAfter
*/
setEndDate : function(endDate, additionalNightsAfter) {
if (typeof(additionalNightsAfter) == 'undefined') {
additionalNightsAfter = this._additionalNightsAfter;
}
if ((!this._accommodationEndDate || this._accommodationEndDate.getTime() != endDate.getTime()) || additionalNightsAfter != this._additionalNightsAfter) {
this._accommodationEndDate = endDate;
this._additionalNightsAfter = additionalNightsAfter;
this.updateEndDate();
this._onEndDateChange();
}
},
/**
* When the duration change
*/
_onDurationChange : function () {
// if there is a start date, we need to update the end date
if(this._accommodationStartDate) {
this._accommodationEndDate = this.getCalculatedEndDate();
}
this.updateEndDate();
this.fireEvent('accommodationUpdated');
},
/**
* When the start date change
*/
_onStartDateChange : function () {
this.refreshValidDurations();
// if there is a start date, we need to update the end date
if(this._accommodationEndDate) {
var duration = this._schoolAccommodations.getDurationInWeeks(this._accommodationEndDate, this._accommodationStartDate);
if (duration < this.getAccommodationOptionDetails().minimumDurationInWeeks){
this.setDuration(this.getAccommodationOptionDetails().minimumDurationInWeeks);
}else {
this._accommodationDuration = duration;
}
}
this.fireEvent('accommodationUpdated');
},
/**
* When the end date change
*/
_onEndDateChange : function () {
this.refreshValidDurations();
// if there is a start date, we need to update the end date
if (this._accommodationStartDate) {
this.updateEndDate();
var duration = this._schoolAccommodations.getDurationInWeeks(this._accommodationEndDate, this._accommodationStartDate);
if (duration < this.getAccommodationOptionDetails().minimumDurationInWeeks) {
this.setDuration(this.getAccommodationOptionDetails().minimumDurationInWeeks);
} else {
this._accommodationDuration = duration;
}
}
this.fireEvent('accommodationUpdated');
},
/**
* Return the accommodation details DTO
*
* @return AccommodationDetailsDTO The Accommodation details
*/
getAccommodationDetails : function() {
return this._accommodationDetails;
},
/**
* Return the accommodation details DTO
*
* @return AccommodationOptionDetailsDTO The Accommodation option details
*/
getAccommodationOptionDetails : function() {
return this._accommodationOptionDetails;
},
/**
* 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 ? this._accommodationStartDate.toIso() : null;
accommodationDTO.endDate = this._accommodationEndDate ? this._accommodationEndDate.toIso() : null;
accommodationDTO.additionalNightsBefore = this._additionalNightsBefore;
accommodationDTO.additionalNightsAfter = this._additionalNightsAfter;
return accommodationDTO;
},
/**
* Populate the accommodation from the given DTO
*
*
* @param AccommodationDTO toPopulateDTO The DTO to populate from
*/
populateFromDTO : function(toPopulateDTO) {
var startDate = toPopulateDTO.startDate;
var endDate = toPopulateDTO.endDate;
if(!(startDate instanceof Date)){
startDate = (new Date()).fromIso(startDate);
}
if(!(endDate instanceof Date)){
endDate = (new Date()).fromIso(endDate);
}
this.setStartDate(startDate , toPopulateDTO.additionalNightsBefore ? parseInt(toPopulateDTO.additionalNightsBefore) : 0);
this.setEndDate(endDate , toPopulateDTO.additionalNightsAfter ? parseInt(toPopulateDTO.additionalNightsAfter) : 0);
this.fireEvent('accommodationUpdated');
},
/**
* Return the number of days available before
*/
getAvailableDaysBefore : function() {
/* if(this._accommodationOptionDetails.additionalNightsOnBounds && !this.getAttachedToCourse()){
var accommodations = this._schoolAccommodations.getAccommodations();
if(accommodations.length > 1 && accommodations.indexOf(this) != 0){
return 0;
}
}*/
return this._accommodationOptionDetails.additionalNightsBefore;
},
/**
* return the numbers of days available after
*/
getAvailableDaysAfter : function() {
/*if(this._accommodationOptionDetails.additionalNightsOnBounds){
var accommodations = this._schoolAccommodations.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.updateStartDate();
},
/**
* set The accommodations duration for the given accommodation
*
* @param integer duration The duration
*/
setAttachedAccommodationDuration : function(duration) {
this._accommodationDuration = duration;
this._accommodationEndDate = this.getCalculatedEndDate();
this.updateEndDate();
},
/**
* Update the descriptions
*/
updateDescriptions : function(){
if (this._moreInfo && this._booking.getDescription && this._booking.getDescription('accommodation', this._accommodationDetails.accommodationType) && this._booking.getDescription('accommodation', this._accommodationDetails.accommodationType) != '') {
this._moreInfo.setAttribute('title', this._accommodationDetails.name + ' :: ' + this._booking.getDescription('accommodation', this._accommodationDetails.accommodationType));
this._moreInfo.setStyle('display','');
if(!this._descriptionToolTip ){
this._descriptionToolTip = new SynergeeTips(this._moreInfo, {'className':'Booking-Tool-Tip Tool-tip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
}else {
this._descriptionToolTip.build(this._moreInfo);
}
}else {
if(this._moreInfo)
this._moreInfo.setStyle('display','none');
}
},
/**
* Refresh the list for the possible durations of this accommodation
*
* @param SchoolList The duration list
*/
refreshValidDurations : function() {
this._validDurations = this._schoolAccommodations.getAccommodationValidDuration(this, this.getDurations());
},
/**
* Return the valid durations
*/
getValidDurations : function () {
this.refreshValidDurations();
if(!this._validDurations)
this._validDurations = new Array();
return this._validDurations;
},
/**
* Refresh the list of possible startdates
*
* @param Array list The list of possible startdates
*/
refreshValidStartDates :  function(){
this._validStartDates = this._schoolAccommodations.getAccommodationValidStartDates(this);
},
/**
* return the valid start dates for this accommodation
*
* @return Array of valid start dates
*/
getValidStartDates : function() {
if(!this._validStartDates){
this.refreshValidStartDates();
}
return this._validStartDates;
},
/**
* 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._schoolAccommodations.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._schoolAccommodations.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.set("html", this._accommodationDetails.name);
this._subTitle.set("html", 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.updateStartDate();
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().inject(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().inject(this._listContainer);
this._accommodationDurationsList.initializeEvents();
if(!this._accommodationOptionDetails.additionalNightsOnBounds && this._accommodationDuration != this.getValidDurations().getLast()){
this._additionalNightsAfter = 0;
}
this.updateStartDate();
this.updateEndDate();
// we ask the parent to check if the other accommodations are ok
this._schoolAccommodations.checkAccommodations(this);
// and the fireAnEvent to the parent to refresh the accommodations
this._schoolAccommodations.fireEvent('refreshAccommodations');*/
},
/**
* Update the start date label
*/
updateStartDate : function () {
if (this._additionalNightsBefore && !this.getAvailableDaysBefore()) {
this._additionalNightsBefore = 0;
}
if (this._accommodationStartDate) {
this._calculatedStartDate.setDate(1);
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);
}
},
/**
* Update the end date label
*/
updateEndDate : function () {
if (this._additionalNightsAfter && !this.getAvailableDaysAfter()) {
this._additionalNightsAfter = 0;
}
if (this._accommodationEndDate) {
// We set the date at 1, because if it's at 31 and we set a 30days month it won't set the right month
this._calculatedEndDate.setDate(1);
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);
}
},
/**
* Returns an array of startDates depending of the course added
*
* @return Array An array of Dates
*/
getStartDates : function() {
var startDatesList = new Array();
var startDate = this._schoolAccommodations.getSchool().getAccommodationStartDate();
var endDate = this._schoolAccommodations.getSchool().getAccommodationEndDate();
if(!startDate) return startDatesList;
// if the first course is not a fixed one
if (!this._schoolAccommodations.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._schoolAccommodations.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);
}
if(startDate && endDate){
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._schoolAccommodations.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._schoolAccommodations.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._schoolAccommodations.getDurationInWeeks(this._accommodationEndDate, this._accommodationStartDate);
}
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() {
return this._accommodationDuration && this._accommodationStartDate && this._accommodationEndDate;
},
/**
* 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;
},
/**
* 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
*/
getValidEndDates : function() {
var validEndDates = new Array();
if(this._accommodationStartDate){
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.getValidDurations().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;
},
/**
* Set the element container of this accommodation
*
* @param element
*/
setElement : function(element){
this._element = element;
},
/**
* Return the element container of this accommodation
*
* @param element
*/
getElement : function(){
return this._element;
},
/**
* Delete this accommodation
*/
deleteAccommodation : function () {
this.fireEvent('delete');
}
});/**
* 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 = new Class({
Implements: Events,
/**
* This is the initialization function
*/
initialize : function(schoolAccommodationsDTO, oSchool) {
this._schoolAccommodationsDTO = schoolAccommodationsDTO;
this._accommodations = new Array();
this._school = oSchool;
this._booking = this._school.getParent();
this._accommodationsOptions = new Hash();
this._schoolAccommodationsDTO.each(function(accommodation, index){
accommodation.option.each(function(option, index){
this._accommodationsOptions.set(option.id,{accommodationDTO: accommodation, optionDTO : option });
}.bind(this));
}.bind(this));
this._calendar = new BookingCalendar({
days: this._booking._translateDTO.days, // days of the week starting at sunday
months: this._booking._translateDTO.months,
offset: this._booking._translateDTO.firstDayOfWeek
});
this._calendar.addEvent('dateselected', function(e){
this._calendar.hide();
this._calendar.getCallBackMethod().call(this._calendar.getBind(), this._calendar.getSelectedDate());
}.bind(this));
this.addEvent('refreshAccommodations', function(item, index) {
this.refreshAccommodations();
}.bind(this));
},
/**
* Update the rendering of the accommodations
*/
render : function () {
if(!this._schoolAccommodationsList){
var schoolAccommodationsList = this._booking.getSchoolAccommodationsListTemplate(this._schoolDTO);
if(schoolAccommodationsList){
$p(schoolAccommodationsList.getSelector(), this._school.getSchoolElement()).render(this._schoolAccommodationsDTO, schoolAccommodationsList.getDirective());
this._schoolAccommodationsList = this._booking.populateList(this._school.getSchoolElement().getElement(schoolAccommodationsList.getSelector()));
this._schoolAccommodationsList.addEvent('change', function(e) {
var value = this._accommodationsOptions.get(parseInt(this._schoolAccommodationsList.getValue()));
this.addAccommodation(value.accommodationDTO.id, value.optionDTO.id);
}.bind(this));
}
}
var accommodationsTemplate = this._booking.getSchoolAccommodationsTemplate(this._accommodations);
$p(accommodationsTemplate.getSelector(), this._school.getSchoolElement()).render(this._accommodations, accommodationsTemplate.getDirective());
this._accommodations.each(function(accommodation, index) {
// todo find a way to retrieve the right accommodation container
accommodation.setElement(this._school.getSchoolElement().getElements('.accommodation-container')[index]);
this._school.getSchoolElement().getElements('.accommodation-container')[index].getElement('.accommodation-delete-button').addEvent('click', function() {
this.deleteAccommodation(accommodation);
}.bind(this));
accommodation.render();
}.bind(this));
},
/**
* Return the calendar
*/
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;
},
/**
* return the accommodation option information
* @param optionId
*/
getAccommodationOptionInformations : function (optionId) {
if (this._accommodationsOptions.has(optionId)) {
return this._accommodationsOptions.get(optionId);
}
return null;
},
getValidAccommodationsList : function () {
var availableAccommodations = this.getAvailableAccommodations();
var accommodationStartDate = this.getSchoolAccommodationStartDate();
var accommodationEndDate = this.getAccommodationEndDate();
var validAccommodations = new Array();
if(availableAccommodations.length){
this._accommodationsOptions.each(function(item, key) {
if (availableAccommodations.contains(parseInt(item.accommodationDTO.id))) {
var startDate = new Date(accommodationStartDate);
var day = startDate.getDay();
if (day == 0)day = 7;
while (parseInt(item.optionDTO.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.optionDTO.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.optionDTO.availabilities && item.optionDTO.availabilities.length) {
var availabilities = item.optionDTO.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 {
// if there are no accommodations added and the accommodation is not available the first possible week it's removed
if(!this.getAccommodations().length && availabilities[startYear + '' + startWeek] === 0){
available = false;
} else {
// otherwise we test if the accommodation is available
while (duration > 0 && startWeek != endWeek && !available) {
if (availabilities[startYear + '' + startWeek] == undefined) {
available = true;
break;
}
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 (available && availableAccommodations.contains(parseInt(item.accommodationDTO.id))
&& this.getDurationInWeeks(endDate, startDate) >= item.optionDTO.minimumDurationInWeeks
&& this.getSchoolParticipants() >= item.optionDTO.minimumNumberOfPeople) {
validAccommodations.push(parseInt(key));
}
}.bind(this));
}
return validAccommodations;
},
/**
* 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 accommodationsDetailsDTO = Array.from(this._schoolAccommodationsDTO);
var accommodationDetailsDTO = null;
for (var i = 0; i < accommodationsDetailsDTO.length; i++) {
var accommodation = accommodationsDetailsDTO[i];
var accommodationOptionDetails = accommodation.option.filter(function(item, index) {
return item.id == optionId;
}.bind(this));
if (accommodationOptionDetails.length) {
accommodationDetailsDTO = accommodation;
break;
}
}
if(accommodationDetailsDTO) {
var newAccommodation = new SchoolAccommodationObject(accommodationDetailsDTO, accommodationOptionDetails[0], this);
// if the accommodation has valid start dates it is added
if (newAccommodation.getStartDates().length) {
this._accommodations.push(newAccommodation);
newAccommodation.addEvent('accommodationUpdated', function() {
this.checkAccommodations(newAccommodation);
this.refreshAccommodations();
}.bind(this));
newAccommodation.addEvent('deleteAccommodation', function(e) {
this.deleteAccommodation(newAccommodation);
}.bind(this));
// if the newly added accommodation is populated from course infos
if (newAccommodation.isComplete()) {
this.checkAccommodations(newAccommodation);
this.refreshAccommodations();
}
this.fireEvent('accommodationAdded', newAccommodation);
return newAccommodation;
}
}
return false;
},
replaceAccommodation : function (oldAccommodation, newAccommodationId) {
var accommodationIndex = this._accommodations.indexOf(oldAccommodation);
var dto = oldAccommodation.getDTO();
var accommodationsDetailsDTO = Array.from(this._schoolAccommodationsDTO);
var accommodationDetailsDTO = null;
for (var i = 0; i < accommodationsDetailsDTO.length; i++) {
var accommodation = accommodationsDetailsDTO[i];
var accommodationOptionDetails = accommodation.option.filter(function(item, index) {
return item.id == newAccommodationId;
}.bind(this));
if (accommodationOptionDetails.length) {
accommodationDetailsDTO = accommodation;
break;
}
}
if (accommodationDetailsDTO) {
var newAccommodation = new SchoolAccommodationObject(accommodationDetailsDTO, accommodationOptionDetails[0], this);
this._accommodations.splice(accommodationIndex, 1, newAccommodation);
newAccommodation.populateFromDTO(dto);
newAccommodation.addEvent('accommodationUpdated', function() {
this.checkAccommodations(newAccommodation);
this.refreshAccommodations();
}.bind(this));
newAccommodation.addEvent('deleteAccommodation', function(e) {
this.deleteAccommodation(newAccommodation);
}.bind(this));
// if the newly added accommodation is populated from course infos
if (newAccommodation.isComplete()) {
this.checkAccommodations(newAccommodation);
this.refreshAccommodations();
}
this.fireEvent('accommodationAdded', newAccommodation);
return newAccommodation;
}
},
/**
* 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() {
var mandatoryAccommodations = this._school.getMandatoryAccommodations();
this.refreshVisualAccommodationList(this.accommodationsList);
if (this._accommodations.length || mandatoryAccommodations.length) {
// if an accommodation 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.deleteAccommodation(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.deleteAccommodation(this._accommodations[i]);
i--;
}
}
// 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.deleteAccommodation(this._accommodations[i], true);
i--;
}
}
for (var i = 0; i < this._accommodations.length; i++) {
this._accommodations[i].setIsAttachedToCourse(false);
}
// if there are mandatory accommodations
if (mandatoryAccommodations.length) {
this.checkMandatoryAccommodations(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.deleteAccommodation(this._accommodations[i], true);
}
}
// 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.deleteAccommodation(this._accommodations.getLast(), true);
} else {
this._accommodations.getLast().setEndDate(endDate);
}
} else {
this._accommodations.getLast().setEndDate(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()) {
// delete the accommodation with a start date smaller than the new course start date
for (var i = 0; i < this._accommodations.length; i++) {
if (this._accommodations[i].getAccommodationStartDate() < startDate) {
this.deleteAccommodation(this._accommodations[i], true);
i--;
}
}
// if there are still accommodations the start is updated
if (this._accommodations.length) {
this._accommodations[0].setStartDate(startDate);
}
}
/* for (var i = 0; i < this._accommodations.length; i++) {
if (this._accommodations[i].isComplete()) {
refreshPrice = true;
break;
}
}*/
// 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.getCoursesManager().getValidAddedCourses(true).getLast().getCourseDetails().id)) {
} else {
}
}
}
this.fireEvent('accommodationsUpdated');
},
/**
* 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
*
*/
checkMandatoryAccommodations : 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].getDurations());
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].deleteAccommodation();
this._accommodations.erase(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].getDurations());
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.deleteAccommodation(accommodationsAlreadyAdded[0]);
i--;
}
}
}
}
},
/**
* Check all the accommodations and modify them to fit the accommodation passed in parameter
*
* Called when an accommodation is updated
*
* @param SchoolAccommodationsObject accommodation The accommodation to check
*
*/
checkAccommodations : function(accommodation) {
if (accommodation.isComplete()) {
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 nextAccommodation = this._accommodations[index + 1];
// set the new data for the next accommodation
if (!nextAccommodation.getIsAttachedToCourse()) {
nextAccommodation.setStartDate(accommodation.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 prevAccommodation = this._accommodations[index - 1];
// set the new data for this accommodation
if (!prevAccommodation.getIsAttachedToCourse()) {
prevAccommodation.setEndDate(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()) {
// set the new data for this accommodation
nextAccommodation = this._accommodations[index + 1];
if (!nextAccommodation.getIsAttachedToCourse()) {
nextAccommodation.setStartDate(accommodation.getAccommodationEndDate());
}
}
}
}
},
/**
* Return the school accommodation start date
*
* @return Date the school accommodations start date
*/
getSchoolAccommodationStartDate : function() {
return this._school.getAccommodationStartDate();
},
/**
* Return the participants number
*/
getSchoolParticipants : function() {
return this._school.getParticipants();
},
/**
* Returns the possible startDate for the accommodations
*
*
* @return Date The possible startdates
*/
getAccommodationStartDate : function() {
var startDate = this.getSchoolAccommodationStartDate();
if(startDate && 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 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.length && this._accommodations.indexOf(accommodation) != 0  ) {
var accommodationPosition = this._accommodations.indexOf(accommodation);
if(accommodationPosition == -1) accommodationPosition = this._accommodations.length;
for (var i = 0; i < accommodationPosition; 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 && this._accommodations.indexOf(accommodation) != -1) {
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 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) {
return [this.getDurationInWeeks(accommodationEndDate, accommodation._accommodationStartDate)];
} else {
return [];
}
}
// if the accommodations is not attached
var validDurations = new Array();
var durations = durationList;
var durationsToRemove = 0;
if(!durations)
return validDurations;
// if the accommodation has a start date
if (accommodation.getAccommodationStartDate()) {
var difference = this.getDurationInWeeks(this.getAccommodationEndDate(accommodation), accommodation.getAccommodationStartDate());
durationsToRemove = durations.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.length - durationsToRemove); i++){
var value = durations[i], currentYear = '', currentWeek = '';
if(week != -1){
currentWeek = week + parseInt(value)-1;
currentYear = currentWeek > 52 ? accommodation.getAccommodationStartDate().getFullYear()+1 : accommodation.getAccommodationStartDate().getFullYear();
currentWeek = currentWeek > 52 ? week-52 : week;
}
if(week == -1 || !accommodation.getAccommodationOptionDetails().availabilities ||
accommodation.getAccommodationOptionDetails().availabilities[currentYear + '' + currentWeek] != 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 SchoolAccommodationObject accommodation The accommodation to delete
* @param boolean silentDelete True to not send the event
*/
deleteAccommodation : function(accommodation, silentDelete) {
this._accommodations.erase(accommodation);
this.refreshAccommodations();
/*  this._school.fireEvent('heightModified');
if (!this._accommodations.length && !silentDelete) {
this._school.fireEvent('refreshPrice');
}*/
},
/**
* Remove all the courses
*/
removeAllAccommodations : function (noRefresh) {
this._accommodations = new Array();
if(!noRefresh)this.refreshAccommodations();
},
/**
*  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.combine(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);
},
/**
* 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 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 SchoolCourseObject = new Class({
Implements: Events,
/**
* This is the initialization function
*
*/
initialize : function(courseDetails, schoolCourses, courseType) {
this._translateDTO = {};
this._courseDetails = courseDetails;
this._schoolCourses = this._parent = schoolCourses;
this._courseType = courseType;
this._booking = this._schoolCourses.getSchool().getBooking();
this._booking.addEvent('descriptionsUpdated', function(){
this.updateDescriptions();
}.bind(this));
this._dateFormat = this._booking.getDateFormat();
this._monthsTranslations = this._booking.getMonthTranslations();
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;
}
},
updateDescriptions : function() {
if (this._booking.getDescription && this._booking.getDescription('course', this._courseDetails.courseTypeId) && this._booking.getDescription('course', this._courseDetails.courseTypeId) != '') {
this._descriptionText = this._booking.getDescription('course', this._courseDetails.courseTypeId);
/*   this._moreInfo.setAttribute('title', this._courseDetails.name + ' :: ' + this._booking.getDescription('course', this._courseDetails.courseTypeId));
this._moreInfo.setStyle('display', '');
if (!this._descriptionToolTip) {
this._descriptionToolTip = new SynergeeTips(this._moreInfo, {'className':'Booking-Tool-Tip Tool-tip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
} else {
this._descriptionToolTip.build(this._moreInfo);
}
*/
} else {
//            this._moreInfo.setStyle('display', 'none');
}
},
getDescriptionText : function () {
return this._descriptionText;
},
/*
updateDescriptions : function() {
if (this._booking.getDescription && this._booking.getDescription('course', this._courseDetails.courseTypeId) && this._booking.getDescription('course', this._courseDetails.courseTypeId) != '') {
this._moreInfo.setAttribute('title', this._courseDetails.name + ' :: ' + this._booking.getDescription('course', this._courseDetails.courseTypeId));
this._moreInfo.setStyle('display', '');
if (!this._descriptionToolTip) {
this._descriptionToolTip = new SynergeeTips(this._moreInfo, {'className':'Booking-Tool-Tip Tool-tip', '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 course duration
*
* @return integer The course duration
*/
getCourseDuration : function() {
return this._courseDuration;
},
/**
*  Returns the available accommodations for this course
*
* @return Array of integer The Accommodation IDs
*/
getAvailableAccommodations : function() {
return this._courseDetails.availableAccommodations;
},
/**
* 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 ? this._courseStartDate.toIso() : null;
courseDTO.endDate = this._courseEndDate ? this._courseEndDate.toIso() : null;
return courseDTO;
},
/**
* 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) {
var numberOfWeeks = 0;
if(startDate && endDate){
var refStartDate = startDate.getTime();
var refEndDate = endDate.getTime() - (86400 * 3 *1000) ;
while (refStartDate <= refEndDate) {
numberOfWeeks++;
refStartDate += (86400 * 7 * 1000);
}
if(numberOfWeeks == 0 && startDate.getTime() < endDate.getTime() ){
numberOfWeeks = 1;
}
}
return numberOfWeeks;
},
/**
* return the accommodation end date for this course
*
* @return Date The accommodation end date date
*/
getAccommodationEndDate : function() {
return new Date(this._courseEndDate);
},
/**
* return the course type
*
* @return string the course type
*/
getCourseType : function () {
return this._courseType;
},
/**
* return the parent
*
* @return SchoolCourses The parent
*/
getParent : function() {
return this._parent;
},
/**
* Set the element container of this course
*
* @param element
*/
setElement : function(element){
this._element = element;
},
/**
* Set the element container of this course
*
* @return  The element containing this course
*/
getElement : function(){
return this._element;
},
/**
* delete this course
*
*/
deleteCourse : function (){
this.fireEvent('delete');
}
});/**
* 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 = new Class({
Implements: Events,
/**
* This is the initialization function
*
*/
initialize : function(schoolFixedCoursesDTO, schoolVariableCoursesDTO, schoolOptionalCoursesDTO, oSchool) {
this._schoolFixedCoursesDTO = schoolFixedCoursesDTO;
this._schoolVariableCoursesDTO = schoolVariableCoursesDTO;
this._schoolOptionalCoursesDTO = schoolOptionalCoursesDTO;
this._courses = new Array();
this._optionalCourses = new Array();
this._school = this._parent = oSchool;
this._booking = this._school.getParent();
},
/**
* Return the school component
*/
getSchool : function () {
return this._school;
},
/**
* 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.getCourseType() == 'fixed' && 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.getCourseType() == 'variable' && 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._optionalCourses.each(function(item, index) {
if ( 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]) {
var newCourse = this.addCourse(course[0], item, true);
}
}.bind(this));
},
/**
* Return the course information dto from its id
*
* @param integer courseId The course id
*/
getCourseInformationDTO : function (courseId) {
var course = this._schoolVariableCoursesDTO.filter(function(itemDTO, indexDTO) {
return itemDTO.id == courseId;
}.bind(this));
if(!course.length)
course = this._schoolFixedCoursesDTO.filter(function(itemDTO, indexDTO) {
return itemDTO.id == courseId;
}.bind(this));
if(!course.length)
course = this._schoolOptionalCoursesDTO.filter(function(itemDTO, indexDTO) {
return itemDTO.id == courseId;
}.bind(this));
return course.length ? course[0] : null;
},
/**
* Refresh all the courses
*
*/
refreshCourses : function() {
var availableOptionalCourses = this.getValidOptionalCourses();
// remove the optionals course not allowed to be there
this._optionalCourses.each(function(item, index) {
if (!availableOptionalCourses.contains(parseInt(item.getCourseDetails().id))) {
this._optionalCourses.erase(item);
}else {
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.erase(item);
}
//                if (modified) item.refreshOptionalCourseData();
}
}.bind(this));
this.refreshCoursesList();
if(this.optionalCoursesList){
this.refreshVisualOptionalCoursesList(this.optionalCoursesList);
}
this._courses.each(function(item, index) {
item.refreshLists();
});
this.fireEvent('heightModified');
},
/**
* Refresh the courses list
*
* @param SchoolList list the list we want to populate
*
*/
refreshCoursesList : function() {
this._validCourses = this.getValidCourses();
},
/**
* Return the valid courses list
*
*/
getValidCoursesList : function () {
if(!this._validCourses)
this._validCourses = new Array();
return this._validCourses;
},
/**
* return the list of available optional course
*
* @return integer[] Array of optional course IDs
*/
getValidOptionalCourses : 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]);
}
}
}
var validOptionalCourses = [];
if(completedCourses.length){
var startDate = completedCourses[0]._courseStartDate;
var endDate = completedCourses[completedCourses.length-1]._courseEndDate;
this._schoolOptionalCoursesDTO.each(function(optCourse){
if(availableOptionalCourses.contains(parseInt(optCourse.id))){
var valid = false;
optCourse.startDates.each(function(start){
if(start >= startDate && start <= endDate){
valid = true;
}
}.bind(this));
if(valid)
validOptionalCourses.push(parseInt(optCourse.id));
}
}.bind(this));
}
return validOptionalCourses;
},
/**
* Add a selected course
*
* @param Object course The course DTO
*/
addCourse : function(course, dto, noEvent) {
var newCourse;
switch (course.type) {
case 'fixedDate' :
newCourse = new SchoolFixedCourseObject(course, this);
this._courses.push(newCourse);
break;
case 'variableDate' :
newCourse = new SchoolVariableCourseObject(course, this);
this._courses.push(newCourse);
break;
case 'optional' :
newCourse = new SchoolOptionalCourseObject(course, this);
this._optionalCourses.push(newCourse);
break;
}
newCourse.addEvent('deleteCourse', function(e) {
this.deleteCourse(newCourse);
this.onCourseUpdated();
}.bind(this));
if(dto){
newCourse.populateFromDTO(dto);
}
this.fireEvent('courseAdded', newCourse);
newCourse.addEvent('courseUpdated', this.onCourseUpdated.bind(this));
if(!noEvent){
newCourse.fireEvent('courseUpdated');
this.fireEvent('heightModified');
}
return newCourse;
},
/**
* Add a course from its ID
*
* @param integer courseId the course id
*/
addCourseFromId : function(courseId, dto, noEvent, courseType) {
var courseItem = [];
if (!courseType || courseType == 'variableDates' || courseType == 'variableDate') {
courseItem = this._schoolVariableCoursesDTO.filter(function (item, index) {
return item.id == courseId;
}.bind(this));
}
if (!courseType || courseType == 'fixedDates' || courseType == 'fixedDate') {
if (!courseItem.length) {
courseItem = this._schoolFixedCoursesDTO.filter(function (item, index) {
return  item.id == courseId;
}.bind(this));
}
}
if (!courseType || courseType == 'optional') {
if (!courseItem.length) {
courseItem = this._schoolOptionalCoursesDTO.filter(function (item, index) {
return  item.id == courseId;
}.bind(this));
}
}
if(courseItem.length) {
return this.addCourse(courseItem[0], dto, noEvent);
}
return null;
},
/**
* Delete the course given in parameter
*
* @param SchoolCourseObject course The course to delete
*/
deleteCourse : function(course) {
if (course.getCourseType() == 'optional') {
if (course.isComplete()) {
this._optionalCourses.erase(course);
this.onCourseUpdated();
} else {
this._optionalCourses.erase(course);
}
} else {
if (course.isComplete()) {
this._courses.erase(course);
this.onCourseUpdated();
} else {
this._courses.erase(course);
}
}
this.fireEvent('coursesUpdated');
},
/**
* Remove all the courses
*/
removeAllCourses : function (includeOptional, noEvent) {
if(includeOptional)this._optionalCourses = new Array();
this._courses = new Array();
if(!noEvent){
this.onCourseUpdated();
this.fireEvent('coursesUpdated');
}
},
/**
* Called when a course is modified
*/
onCourseUpdated : function() {
this.refreshCourses();
this.fireEvent('coursesUpdated');
},
/**
* Returns all the courses stocked in the DTO
*
* @return Array An array containing all the courses
*/
getCourses : function(noFilter) {
var validCourses = new Array();
// retrieving the valid fixed courses
this._schoolFixedCoursesDTO.each(function(item, index) {
// check if there are course type filter
if(noFilter || this.isValidFromFilter(item)){
validCourses.include(item);
}
}.bind(this));
// retrieving the variable courses
this._schoolVariableCoursesDTO.each(function(item, index) {
// check if there are course type filter
if(noFilter || this.isValidFromFilter(item)){
validCourses.include(item);
}
}.bind(this));
validCourses = validCourses.sort(this.sortFunction);
return validCourses;
},
/**
* Check if the given course is valid with the booking filters
*
* @param course
* @return {Boolean}
*/
isValidFromFilter : function(course){
if(!this._booking.getCourseTypesFilter().length || this._booking.getCourseTypesFilter().indexOf(parseInt(course.courseTypeId)) != -1){
if(this._booking.getLevelFilter() == 0 ||
(this._booking.getLevelFilter() >= course.minimumAcceptedLevel && this._booking.getLevelFilter() <= course.maximumAcceptedLevel)){
return true;
}
}
return false
},
/**
* Returns all the optional courses stored 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
*
* @param Boolean ignoreOptionalCourses true if it shouldnt return the optional courses
*
* @return SchoolCourseObject The courses completed
*/
getCompletedCourses : function(ignoreOptionalCourses) {
var completedCourses = new Array();
if (this._courses.length) {
this._courses.each(function(item, index) {
if (item.isComplete()) {
completedCourses.push(item);
}
});
}
if (!ignoreOptionalCourses && this._optionalCourses.length) {
this._optionalCourses.each(function(item, index) {
if (item.isComplete()) {
completedCourses.push(item);
}
});
}
return completedCourses;
},
/**
* Return all the valid courses added in the cart
*
* @param Boolean bIgnoreOptional True to ignore the optional courses
*
* @return SchoolCourse[] Return an array of valid course in the cart
*/
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]);
}
}
}
if(!bIgnoreOptional){
for (var i = 0; i < this._optionalCourses.length; i++) {
if (this._optionalCourses[i].isComplete()) {
validCourses.push(this._optionalCourses[i]);
}
}
}
return validCourses;
},
/**
* Returns the valid courses for a given period based on a courseObject
*
* @param SchoolCourseObject course The course object, if empty we consider that we want to add a new course
* @param boolean optionalCourse True to check only the optional courses
*
* @return Array Return an array of course DTO (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;
if(this.isValidFromFilter(item)){
item.sessions.each(function(item, index) {
//alert(item.courseStartDate);
if (item.courseStartDate >= startDate && item.courseEndDate <= endDate) {
validCourses.include(courseItem);
}
});
}
}.bind(this));
// retrieving the valid variable courses
this._schoolVariableCoursesDTO.each(function(item, index) {
var itemDuration = item.duration[0];
var courseItem = item;
if (this.isValidFromFilter(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));
}
}.bind(this));
} else {
// retrieving the valid optional courses
this._schoolOptionalCoursesDTO.each(function(item, index) {
if(this.isValidFromFilter(item)){
// 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));
}
}.bind(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;
},
/**
* todo add the course type filter
* @param originalCourse
* @param newCourseId
* @param courseType
* @return {*}
*/
replaceCourse : function(originalCourse, newCourseId, courseType){
if(originalCourse.getCourseType() == 'optional'){
var courseIndex = this._optionalCourses.indexOf(originalCourse);
}else {
var courseIndex = this._courses.indexOf(originalCourse);
}
var dto = originalCourse.getDTO();
if (courseIndex != -1) {
var courseItem = this._schoolVariableCoursesDTO.filter(function(item, index) {
return item.id == newCourseId;
}.bind(this));
if (!courseItem.length) {
courseItem = this._schoolFixedCoursesDTO.filter(function(item, index) {
return  item.id == newCourseId;
}.bind(this));
}
if (!courseItem.length) {
courseItem = this._schoolOptionalCoursesDTO.filter(function(item, index) {
return  item.id == newCourseId;
}.bind(this));
}
if (courseItem.length) {
courseItem = courseItem[0];
var newCourse;
switch (courseItem.type) {
case 'fixedDate' :
newCourse = new SchoolFixedCourseObject(courseItem, this);
break;
case 'variableDate' :
newCourse = new SchoolVariableCourseObject(courseItem, this);
break;
case 'optional' :
newCourse = new SchoolOptionalCourseObject(courseItem, this);
break;
}
if(newCourse){
if(originalCourse.getCourseType() == 'optional'){
this._optionalCourses.splice(courseIndex, 1, newCourse);
} else {
this._courses.splice(courseIndex, 1, newCourse);
}
newCourse.addEvent('courseUpdated', this.onCourseUpdated.bind(this));
newCourse.addEvent('deleteCourse', function(e) {
this.deleteCourse(newCourse);
this.onCourseUpdated();
}.bind(this));
this.fireEvent('courseAdded', newCourse);
newCourse.populateFromDTO(dto);
newCourse.fireEvent('courseUpdated');
this.fireEvent('heightModified');
return newCourse;
}
}
}
},
/**
* 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
var daysPerWeek = (course.getCourseDetails().oneDayCourse ? 1 : 7);
if (course._courseStartDate) {
optionEndDate = new Date(course._courseStartDate.getFullYear(), course._courseStartDate.getMonth(), course._courseStartDate.getDate() + daysPerWeek * value);
optionEndDate = course.getOptionalCourseEndDate(optionEndDate);
} else {
optionEndDate = new Date(periods[0].startDate.getFullYear(), periods[0].startDate.getMonth(), periods[0].startDate.getDate() + daysPerWeek * 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 = calculatedEndDate.getFullYear();
var currentWeek = calculatedEndDate.getWeek();
if(course.getCourseDetails().courseStartDay == 7){
if(currentWeek > 1)currentWeek = currentWeek+1;
}
if(currentWeek > 52){
currentWeek = currentWeek - 52;
currentYear = currentYear + 1;
}
if(currentWeek > 1)
currentWeek = currentWeek - 1;
if (currentWeek == -1 || !availabilities ||
availabilities[currentYear + '' + (currentWeek)] != 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.getCourseType() == 'fixed') {
// if this accommodation is available with this course
if (newDate > item.getSession().accommodationStartDate || newDate == null) {
newDate = new Date(item.getSession().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].getCourseType() == 'fixed') {
endDate = new Date(this._courses[i].getSession().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++) {
availableAccommodations = availableAccommodations.combine(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].isComplete() && 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().transferMandatory == true) {
mandatory = true;
}
}
return mandatory;
},
/**
* 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 = new Class({
Implements: Events,
/**
* 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 available currencies
*/
getAvailableCurrencies : function () {
return this._currencyAvailableList;
},
/**
* return the visual transfer container
*/
getHtml : function() {
this._currencyContainer = new Element('div', {'class': this._classNameBase + 'Section' + " " + this._classNameBase + 'Currency-Section'});
this._currencyTitle = new Element('div', {'class': this._classNameBase + 'Section-Title'});
this._currencyButtons = new Element('div', {'class': this._classNameBase + 'Button' + ' ' + this._classNameBase + 'AddButton'});
this._currencyTitle.inject(this._currencyContainer);
//        this._currencyButtons.inject(this._currencyContainer);
this._currencyTitle.set("html", this._translateDTO.title);
this._currencyButtons.set("html", this._currency);
this._currencyButtons.inject(this._currencyContainer);
this._currencyList = new SchoolList(this._currencyButtons, this._classNameBase);
this.createVisualList(this._currencyList);
this._currencyList.getHtml().inject(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.set("html", item.getHtmlValue());
list.setSelectedItem(item);
}
item.getHtml().addEvent('click', function(event) {
this._currencyButtons.set("html", 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) {
if (currency != this._currency) {
this._currency = currency;
if(this._parent.getSchools() && this._parent.getSchools().length){
this.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 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 = new Class({
Extends: SchoolCourseObject,
/**
* This is the initialization function
*
*/
initialize : function(courseDetails, schoolCourses) {
this.parent(courseDetails, schoolCourses, 'fixed');
this._session = -1;
this.type = 'fixed';
// the course start dates
this._sessionsObjects = new Array();
this._startDatesObject = new Array();
var addedStartDates = new Array();
var addedDurations = new Array();
this._courseDetails.sessions.each(function(session, index) {
var startDateName = session.courseStartDate.format(this._dateFormat, this._monthsTranslations);
this._sessionsObjects.push({id : index , name : startDateName});
if(!addedStartDates.contains(session.courseStartDate.getTime())){
this._startDatesObject.push({id : session.courseStartDate.getTime() + '', name : startDateName});
addedStartDates.push(session.courseStartDate.getTime())
}
var duration = this.getCalculatedDuration(session.courseStartDate, session.courseEndDate)
if(!addedDurations.contains(parseInt(duration))){
addedDurations.push(parseInt(duration));
}
// we store the dates values so the list is populated with the right object not the value stored in the dom object
}.bind(this));
addedDurations.sort(function(a,b){return a-b});
this._durations = [];
for(var i = 0; i < addedDurations.length; i++) {
this._durations.push({id : addedDurations[i], name : addedDurations[i]});
}
},
render : function () {
// start date template
var startDatesListTemplate = this._booking.getSchoolCourseStartDatesListTemplate(this._courseStartDate, this);
if(startDatesListTemplate){
$p(startDatesListTemplate.getSelector(), this._element).render(this._sessionsObjects, startDatesListTemplate.getDirective());
// the start dates list
if(this._startDatesList)
this._startDatesList.removeEvents('change');
this._startDatesList = this._booking.populateList(this._element.getElement(startDatesListTemplate.getSelector()));
if(this._session){
this._startDatesList.setValue(this._courseDetails.sessions.indexOf(this._session));
}
this._startDatesList.addEvent('change', function(e) {
var sessionIndex = parseInt(this._startDatesList.getValue());
if(this._courseDetails.sessions[sessionIndex]) {
this._session = this._courseDetails.sessions[sessionIndex];
}
this.refreshCourseData();
}.bind(this));
}
this.refreshCourseData();
},
/**
* Set the session
*
* @param session
*/
setSession : function(session) {
this._session = session;
this.refreshCourseData();
},
/**
* return the current session
*
* @return  session
*/
getSession : function() {
return this._session;
},
/**
* Set the session from its index
*/
setSessionIndex : function(sessionIndex){
if(this._courseDetails.sessions[sessionIndex]) {
this._session = this._courseDetails.sessions[sessionIndex];
}
this.refreshCourseData();
},
/*
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':'Booking-Tool-Tip Tool-tip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
} else {
this._descriptionToolTip.build(this._moreInfo);
}
}
},
*/
/**
* return the accommodation end date for this course
*
* @return Date The accommodation end date date
*/
getAccommodationEndDate : function() {
return this._courseDetails.sessions[this._session].accommodationEndDate;
},
/**
* Populate the fixed course from a dto
*
* @param Object The fixed course informations needed to populate
*/
populateFromDTO : function(toPopulateDTO) {
this._session = null;
var startDate = toPopulateDTO.startDate;
var endDate = toPopulateDTO.endDate;
if(!(startDate instanceof Date)){
startDate = (new Date()).fromIso(startDate);
}
if(!(endDate instanceof Date)){
endDate = (new Date()).fromIso(endDate);
}
// Set the variables for this course
this._courseStartDate = startDate;
this._courseEndDate = endDate;
this._courseDuration = this.getCalculatedDuration(this._courseStartDate, this._courseEndDate);
// 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) == this._courseStartDate.format(this._dateFormat, this._monthsTranslations) &&
item.courseEndDate.format(this._dateFormat, this._monthsTranslations) == this._courseEndDate.format(this._dateFormat, this._monthsTranslations)) {
this._session = item;
}
}.bind(this));
if (!this._session) {
var diff = -1;
for (var i = 0; i < this._courseDetails.sessions.length; i++) {
var session = this._courseDetails.sessions[i];
if (i == 0 || diff > Math.abs(this._courseStartDate.getTime() - session.courseStartDate.getTime())) {
diff = Math.abs(this._courseStartDate.getTime() - session.courseStartDate.getTime());
this._session = session;
}
}
}
this.refreshCourseData();
},
/**
* Refresh all the lists of this course
*
*/
refreshLists : function() {
this.refreshVisualValidCoursesList(this._coursesValidList);
this.refreshVisualFixedCourseStartDates(this._schoolCourses.getValidFixedCourseSession(this));
},
getCourseValidSessions  : function () {
return this._schoolCourses.getValidFixedCourseSession(this);
},
/**
* Refresh the values when the user change a course information
*
* @param Object values The new values
*/
refreshCourseData : function() {
// Set the variables for this course
this._courseStartDate = this._session.courseStartDate;
this._courseEndDate = this._session.courseEndDate;
this._courseDuration = this.getCalculatedDuration(this._courseStartDate, this._courseEndDate);
// 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) == this._courseStartDate.format(this._dateFormat, this._monthsTranslations) &&
item.courseEndDate.format(this._dateFormat, this._monthsTranslations) == this._courseEndDate.format(this._dateFormat, this._monthsTranslations)) {
this._session = item;
}
}.bind(this));
}
this.refreshLists();
this.fireEvent('courseUpdated');
},
/**
* 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 (newCourse.type ==  'fixed') {
if (this.isComplete()) {
this._courseDetails = newCourse;
this._durationValue.addClass(this._classNameBase + 'Section-Item-Info-ValueNotEditable');
this.refreshCourseData(this.getNewFixedCourseDates(this._courseStartDate));
this._title.set("html", this._courseDetails.name);
this._subTitle.set("html", this._courseDetails.subtitle);
this.reGenerateLists();
this._parent.fireEvent('refreshCourses');
} else {
this._schoolSessionsList.getHtml().destroy();
this._coursesValidList.getHtml().destroy();
this._parent.replaceCourse(this, newCourse);
}
} else {
this._schoolSessionsList.getHtml().destroy();
this._coursesValidList.getHtml().destroy();
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;
}
},
/**
* 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);
//todo remove
//        list.getListItems().each(function(item, index) {
//            if (validCourses.indexOf(item.getValue()) != -1) {
//                item.setIsValid(true);
//            } else {
//                item.setIsValid(false);
//            }
//        }.bind(this));
},
/**
* 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(validSessions) {
this._validSessionsIndexList = new Array();
validSessions.each(function(item, index){
this._validSessionsIndexList.push(this._courseDetails.sessions.indexOf(item) + '');
}.bind(this));
},
/**
* Return the valid course sessions index
*
* @return integer[] The valid index
*/
getValidCourseSessions : function () {
if(!this._validSessionsIndexList)
this._validSessionsIndexList = new Array();
return this._validSessionsIndexList;
},
/**
* Return the valid course start dates
*/
getValidCourseStartDates:function () {
var validSessions = this.getValidCourseSessions();
var validStartDates = [];
var startDatesAdded = [];
validSessions.each(function(item, index){
var session = this._courseDetails.sessions[item];
if(!startDatesAdded.contains(session.courseStartDate.getTime())){
validStartDates.push(session.courseStartDate);
startDatesAdded.push(session.courseStartDate.getTime() + '');
}
}.bind(this));
return startDatesAdded;
},
/**
* Return the valid course start dates
*/
getCourseValidDurations:function () {
var validDurations = [];
if (this._courseStartDate) {
this._courseDetails.sessions.each(function (session, index) {
if (session.courseStartDate.getTime() == this._courseStartDate.getTime()) {
validDurations.push(this.getCalculatedDuration(session.courseStartDate, session.courseEndDate) + '');
}
}.bind(this));
}
return validDurations;
},
setCourseStartDate : function (startDate) {
var sessions = [];
// Set the variables for this course
//        this._courseEndDate = endDate;
//        this._courseDuration = this.getCalculatedDuration(this._courseStartDate, this._courseEndDate);
// 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) == startDate.format(this._dateFormat, this._monthsTranslations)) {
sessions.push(item);
}
}.bind(this));
if(sessions.length == 1){
this.setSession(sessions[0]);
}
if(sessions.length > 1){
this._courseStartDate = startDate;
this._courseEndDate = null;
this._courseDuration = null;
this._session = null;
this.fireEvent('courseUpdated');
}
},
setCourseDuration : function (duration) {
var sessions = [];
if(this._courseStartDate){
// 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) == this._courseStartDate.format(this._dateFormat, this._monthsTranslations)) {
if(this.getCalculatedDuration(item.courseStartDate, item.courseEndDate) == parseInt(duration)){
sessions.push(item);
}
}
}.bind(this));
if(sessions.length){
this.setSession(sessions[0]);
}
}
},
getCourseDuration : function (){
if(this._courseDuration){
return this._courseDuration;
}
return null;
},
/**
* 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) {
var numberOfWeeks = 0;
if(startDate && endDate){
var refStartDate = startDate.getTime();
var refEndDate = endDate.getTime() - (86400 * 3 *1000) ;
while (refStartDate <= refEndDate) {
numberOfWeeks++;
refStartDate += (86400 * 7 * 1000);
}
if(numberOfWeeks == 0 && startDate.getTime() < endDate.getTime() ){
numberOfWeeks = 1;
}
}
return numberOfWeeks;
}
/**
* This function remove the course from the list
*
*/
/* removeCourse : function() {
this._schoolSessionsList.getHtml().destroy();
this._coursesValidList.getHtml().destroy();
this._container.destroy();
}*/
});
/**
* 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 = new Class({
Implements: Events,
/**
* This is the initialization function
*/
initialize : function(id, insuranceDTO, parent) {
this._insuranceDTO = insuranceDTO;
this._insuranceName = this._insuranceDTO.name;
this._type = this._insuranceDTO.type;
this._insuranceId = id;
this._parent = parent;
this._isMandatory = false;
this._insuranceStartDate = null;
this._insuranceEndDate = null;
this._insuranceDuration = null;
this._booking = this._parent.getParent();
this._booking.addEvent('descriptionsUpdated', function() {
this.updateDescriptions();
}.bind(this));
},
getInsuranceId : function () {
return this._insuranceId;
},
/**
* Return this insurance informations DTO
*
* @return InsuranceDTO The insurance informations DTO
*/
getInsuranceInformations : function() {
return this._insuranceDTO;
},
updateDescriptions : function() {
if (this._booking.getDescription && this._booking.getDescription('insurance', this._insuranceId) && this._booking.getDescription('insurance', this._insuranceId) != '') {
this._descriptionText = this._booking.getDescription('insurance', this._insuranceId);
} else {
this._descriptionText = null;
}
},
getDescriptionText : function () {
return this._descriptionText;
},
/**
* 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
},
/**
* Set the mandatory information of this insurance
*
* @param Boolean mandatory True if the insurance is mandatory
*/
setMandatory : function(mandatory) {
this._isMandatory = mandatory;
},
/**
* Return true if the insurance is mandatory
*/
getMandatory : function() {
return this._isMandatory;
},
/**
* 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;
},
/**
* Return date the insurance start date
*/
getInsuranceStartDate : function() {
return this._insuranceStartDate;
},
/**
* Return date the insurance end date
*/
getInsuranceEndDate : function() {
return this._insuranceEndDate;
},
/**
* Return date the insurance duration
*/
getInsuranceDuration : function() {
return this._insuranceDuration;
},
/**
* 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);
},
/**
* 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.set("html", 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));
},
/**
* Set the element container of this insurance
*
* @param element
*/
setElement : function(element){
this._element = element;
},
/**
* Set the element container of this insurance
*
* @return  The element containing this insurance
*/
getElement : function(){
return this._element;
},
/**
* Remove the insurance from the list
*
*/
removeInsurance : function() {
this.fireEvent('deleteInsurance');
}
});
/**
* 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 = new Class({
Implements: Events,
/**
* This is the initialization function
*/
initialize : function(schoolInsurancesDTO, parent) {
this._schoolInsurancesDTO = new Hash();
if (schoolInsurancesDTO) {
for (var i = 0; i < schoolInsurancesDTO.length; i++) {
this._schoolInsurancesDTO.set(schoolInsurancesDTO[i].id, schoolInsurancesDTO[i]);
}
}
this._booking = this._parent = parent;
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));
},
/**
* Return the insurances list
*
* @return BiHash The insurances DTO
*/
getInsurances : function() {
return this._schoolInsurancesDTO;
},
/**
* Return the added insurances list
*
* @return InsuranceObject[] The insurances
*/
getAddedInsurances : function() {
return this._insurances;
},
/**
* 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));
}
},
/**
* 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
*/
refreshInsuranceList : function() {
this._validInsurances = new Array();
this._schoolInsurancesDTO.each(function(insurance, key) {
if (this._duration && (insurance.availableFrom <= this._duration) && !this.isAdded(key)) {
this._validInsurances.push(insurance);
}
}.bind(this));
},
/**
* Return the valid insurance list
*/
getValidInsurancesList : function() {
this.refreshInsurances();
return this._validInsurances;
},
/**
* 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._booking.getStartDate(courseOnly);
},
/**
* Return the insurance start date calculated from the course and accommodation
*/
getInsuranceCourseStartDate : function(courseOnly) {
if(!courseOnly)courseOnly = false;
return this._booking.getCourseStartDate(courseOnly);
},
/**
* Return the insurance end date calculated from the course and accommodation
*/
getInsuranceEndDate : function() {
return this._booking.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();
this.refreshInsuranceList();
// 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){
this.deleteInsurance(item);
}
}.bind(this));
// remove all the insurance if there are no more course on the quote
if (this._booking.getCompletedCourses().length == 0) {
this.deleteAllInsurance();
}else {
this._defaultCheckedInsurances.each(function(item, index) {
if (!this.isAdded(item.id)) {
this.addInsurance(item.id);
}
this._defaultCheckedInsurances.erase(item);
}.bind(this))
}
},
/**
* Add a insurance from its ID
*
* @param Number id The insurance id
*/
addInsurance : function(id, noTest) {
if (this._schoolInsurancesDTO.has(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);
this._insurances.push(newInsurance);
newInsurance.addEvent('insuranceUpdated', this.refreshPrice.bind(this));
newInsurance.addEvent('deleteInsurance', function(e) {
this.deleteInsurance(newInsurance);
}.bind(this));
this.fireEvent('insuranceAdded', newInsurance);
this.refreshPrice();
return newInsurance;
}
return null;
},
/**
* Refresh the price
*/
refreshPrice: function() {
this.fireEvent('insurancesUpdated');
},
/**
* 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) {
},
/**
* 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 integer 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.erase(insurance);
this.fireEvent('insurancesUpdated');
},
/**
* Delete the given insurance
*
* @param SchoolInsuranceObject insurance The insurance to delete
*/
deleteAllInsurance : function(insurance) {
if(this._insurances.length){
this._insurances = new Array();
this.fireEvent('insurancesUpdated');
}
}
});/**
* 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 = new Class({
Implements: Events,
/**
* 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.inject(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.inject(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() {
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() {
clearTimeout(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(Browser.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(Browser.ie6){
this.getHtml().setStyle('width', (parseInt(this.getHtml().getStyle('width')) + 15) + 'px');
}else{
this.getHtml().setStyle('min-width', (parseInt(this.getHtml().getStyle('width')) + 30) + 'px');
}
//            new Fx.Style(this.getHtml(), 'height', {transition : Fx.Transitions.Quart.easeOut}).start('0', (listHeight) + 'px');
new Fx.Tween(this.getHtml(),{
duration: 100,
property: 'height'
}).start(0, listHeight);
} else {
new Fx.Tween(this.getHtml(),{
duration: 100,
property: 'height'
}).start(0, this.getListHeight());
//            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().destroy();
},
/**
* 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 = new Class({
Implements: Events,
/**
* 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.set("html", 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.set("html", 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 = new Class({
Extends: SchoolCourseObject,
/**
* This is the initialization function
*
*/
initialize : function(courseDetails, schoolCourses) {
this.parent(courseDetails, schoolCourses, 'optional');
this.type = 'optional';
// the course start dates
this._startDatesObjects = new Array();
this._courseDetails.startDates.each(function(item, index) {
this._startDatesObjects.push({id : item.getTime() , name : item.format(this._dateFormat, this._monthsTranslations)});
// we store the dates values so the list is populated with the right object not the value stored in the dom object
}.bind(this));
// the course durations
this._durations = new Array();
this._courseDetails.duration.each(function(item, index) {
this._durations.push({id : item , name : item });
}.bind(this));
this.refreshCourseData();
},
/**
* Populate the variable course from a dto
*
* @param Object The fixed course informations needed to populate
*/
populateFromDTO : function(toPopulateDTO) {
var startDate = toPopulateDTO.startDate;
var endDate = toPopulateDTO.endDate;
if(!(startDate instanceof Date)){
startDate = (new Date()).fromIso(startDate);
}
if(!(endDate instanceof Date)){
endDate = (new Date()).fromIso(endDate);
}
this._courseStartDate = startDate;
this._courseEndDate = endDate;
this._courseDuration = this.getCalculatedDuration(this._courseStartDate, this._courseEndDate);
// If the start and the duration are set,  the end date is calculated
if (this._courseStartDate && this._courseDuration) {
this._courseEndDate = this.getOptionalCourseEndDate();
}
// 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._courseEndDate = this.getOptionalCourseEndDate();
}
this.refreshCourseData();
},
/**
* 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.refreshCourseStartDatesList(this._schoolCourses.getValidOptionalCourseStartDate(this));
// initialize the duration list and its event
this.refreshCourseDurationList(this._schoolCourses.getValidOptionalCourseDuration(this));
},
/**
* Generate all the lists of this course
*
*/
reGenerateLists : function() {
// remove old list if exists
if (this._coursesValidList._listItems.length) {
this._coursesValidList.getHtml().destroy();
this._coursesValidList.clear();
}
if (this._schoolStartList._listItems.length) {
this._schoolStartList.getHtml().destroy();
this._schoolStartList.clear();
}
if (this._schoolDurationList._listItems.length) {
this._schoolDurationList.getHtml().destroy();
this._schoolDurationList.clear();
}
this.getVisualValidCoursesList(this._coursesValidList);
this._coursesValidList.getHtml().inject(this._listContainer);
this._coursesValidList.initializeEvents();
this.getVisualOptionalCourseStartDates(this._courseDetails.startDates, this._schoolStartList);
this.refreshVisualOptionalCourseStartDates(this._parent.getValidOptionalCourseStartDate(this), this._schoolStartList);
this._schoolStartList.getHtml().inject(this._listContainer);
this._schoolStartList.initializeEvents();
this.getVisualOptionalCourseDurationList(this._courseDetails.duration, this._schoolDurationList);
this.refreshVisualOptionalCourseDurationList(this._parent.getValidOptionalCourseDuration(this), this._schoolDurationList);
this._schoolDurationList.getHtml().inject(this._listContainer);
this._schoolDurationList.initializeEvents();
},
/**
* Refresh the course data
*
*/
refreshCourseData : function() {
// If the start and the duration are set,  the end date is calculated
if (this._courseStartDate && this._courseDuration) {
this._courseEndDate = this.getOptionalCourseEndDate();
}
// when the user selects only the start date
if (this._courseStartDate && !this._courseDuration) {
if (this._courseDuration) {
this._courseEndDate = this.getOptionalCourseEndDate();
} else {
this.refreshCourseDurationList(this._schoolCourses.getValidOptionalCourseDuration(this));
}
}
this.refreshLists();
// refresh the course list
this.fireEvent('courseUpdated');
},
/**
*  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 = 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().destroy();
this._schoolDurationList.getHtml().destroy();
this._coursesValidList.getHtml().destroy();
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.set("html", this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.set("html", this._translateDTO.week.replace("%0", this._courseDuration));
}
}
this._courseStartDate = newDate;
//            this.refreshOptionalCourseData();
}
},
/**
* Refresh a list of course that have possible dates between this courseStartDate and courseEndDate
*
* @param SchoolList list The courses list
*
*/
refreshVisualValidCoursesList : function() {
this._validCourses = this._parent.getValidCourses(this, true);
},
/**
* Return the valid courses that could replace this one
*/
getValidCourses : function () {
if (!this._validCourses)
this._validCourses = new Array();
return this._validCourses;
},
/**
* 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
*/
refreshCourseStartDatesList : function(validStartDates) {
this._validStartDatesList = new Array();
for (var i = 0; i < validStartDates.length; i++) {
this._validStartDatesList.push(validStartDates[i]);
}
},
/**
* Return a list with the valid start dates time stamp
*
* @return string[] The valid start dates
*/
getCourseValidStartDates : function () {
if (!this._validStartDatesList)
this._validStartDatesList = new Array();
return this._validStartDatesList;
},
/**
* Return a list with the valid start dates time stamp
*
* @return string[] The valid start dates
*/
getCourseValidStartDatesTime : function () {
if (!this._validStartDatesList)
this._validStartDatesList = new Array();
var validStartDatesTimeList = new Array();
for (var i = 0; i < this._validStartDatesList.length; i++) {
validStartDatesTimeList.push(this._validStartDatesList[i].getTime());
}
return validStartDatesTimeList;
},
/**
* Return a list with the valid start dates time stamp
*
* @return string[] The valid start dates
*/
getCourseValidDurations : function () {
if (!this._validDurationsList)
this._validDurationsList = new Array();
return this._validDurationsList;
},
/**
* 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
*/
refreshCourseDurationList : function(validDurations) {
this._validDurationsList = validDurations;
},
/**
*  set the course duration
*
* @param integer duration The course duration
*/
setCourseDuration : function(duration) {
this._courseDuration = duration;
this.refreshCourseData();
},
/**
*  set the course start date
*
* @param Date startDate The course start date
*/
setCourseStartDate : function(startDate) {
if(startDate && startDate.isValid && startDate.isValid()){
this._courseStartDate = startDate;
}else {
this._courseStartDate = null;
}
this.refreshCourseData();
}
/**
* Remove the course from the list
*
*/
/*removeCourse : function() {
this._schoolStartList.getHtml().destroy();
this._schoolDurationList.getHtml().destroy();
this._coursesValidList.getHtml().destroy();
this._container.destroy();
}*/
});
/**
* 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 = new Class({
Implements: Events,
/**
* 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 + 'Section Participants-Section'});
this._participantTitle = new Element('div', {'class': this._classNameBase + 'Section-Title'});
this._participantButtons = new Element('div', {'class': this._classNameBase + 'Button' + ' ' + this._classNameBase + 'AddButton'});
this._participantTitle.inject(this._participantContainer);
this._participantTitle.set("html", this._translateDTO.title);
this._participantButtons.set("html", '1');
this._participantButtons.inject(this._participantContainer);
this._participantsList = new SchoolList(this._participantButtons, this._classNameBase);
this.createVisualList(this._participantsList);
this._participantsList.getHtml().inject(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.set("html", 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;
if(this._parent.widgetMode)
this._participantButtons.set("html", participants);
//        this._participantButtons.set("html", 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 = new Class({
Implements: Events,
/**
* 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 = new Class({
Implements: Events,
/**
* 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 = new Class({
Implements: Events,
/**
* This is the initialization function
*/
initialize : function(id, name, sessions, subtitle, accommodationMandatory, transferMandatory, availableAccommodations, position, availableOptionalCourses, courseTypeId, price, minimumAcceptedLevel, maximumAcceptedLevel,prices) {
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.price = price;
this.prices = prices;
this.minimumAcceptedLevel = minimumAcceptedLevel;
this.maximumAcceptedLevel = maximumAcceptedLevel;
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var FixedDatesCourseSessionListItemDTO = new Class({
Implements: Events,
/**
* 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 = new Class({
Implements: Events,
/**
* This is the initialization function
*/
initialize : function(id, name, startDates, duration, courseStartDay, courseEndDay, subtitle,  accommodationMandatory, transferMandatory, availableAccommodations, position, availableOptionalCourses, availabilities, courseTypeId, price, minimumAcceptedLevel, maximumAcceptedLevel,prices) {
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.price = price;
this.prices = prices;
this.minimumAcceptedLevel = minimumAcceptedLevel;
this.maximumAcceptedLevel = maximumAcceptedLevel;
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var OptionalCourseListItemDTO = new Class({
Implements: Events,
/**
* This is the initialization function
*/
initialize : function(id, name, startDates, duration, courseStartDay, courseEndDay, subtitle, position, availabilities, oneDayCourse, courseTypeId, additionalDays, price, minimumAcceptedLevel, maximumAcceptedLevel, prices) {
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.price = price;
this.prices = prices;
this.minimumAcceptedLevel = minimumAcceptedLevel;
this.maximumAcceptedLevel = maximumAcceptedLevel;
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var AccommodationOptionListItemDTO = new Class({
Implements: Events,
/**
* This is the initialization function
*/
initialize : function(id, name, minimumDurationInWeeks, minimumNumberOfPeople, accommodationStartDay, accommodationEndDay, availabilities, noAccommodation, additionalNightsBefore, additionalNightsAfter, additionalNightsOnBounds,price, prices) {
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.price = price;
this.prices = prices;
}
});
/**
* This class is used for the price calculation functionnalities
*
**/
var AccommodationListItemDTO = new Class({
Implements: Events,
/**
* 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 = new Class({
Implements: Events,
/**
* 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 = new Class({
Implements: Events,
/**
* 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 = new Class({
Implements: Events,
/**
* 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 = new Class({
Implements: Events,
/**
* This is the initialization function
*/
initialize : function(schoolItemsDTO, parent) {
this._schoolItemsDTO = schoolItemsDTO;
this._parent = parent;
this._items = new Array();
},
/**
* 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 schoolItemsDTO = Array.from(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().inject(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.erase(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 = new Class({
Extends: SchoolSection,
/**
* This is the initialization function
*/
initialize : function(schoolItemsDTO, parent) {
this.parent(schoolItemsDTO, parent);
this.promotions = new Array();
},
validateCode : function(code){
if (!this._xhrValidate) {
this._xhrValidate = new Request({
url : this._parent.getBookingJsonUrl(),
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.fireEvent('promotionAlreadyAdded');
this.fireEvent('promotionsUpdated');
return 0;
}
}
this.promotions.push(parseInt(e));
this.fireEvent('promotionAdded');
this.fireEvent('promotionsUpdated');
} else {
this.fireEvent('invalidCode');
}
}.bind(this)
});
}
if(code != ''){
this._xhrValidate.send('step=validateCode&code=' + code);
}
},
/**
* Return the DTO
*/
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 = new Class({
Implements: Events,
/**
* 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._booking = this._parent = parent;
this._schoolsList = schoolsList;
this._schoolsHash = new Hash();
this._cityCountryHash = new Hash();
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;
}
this.populateData();
},
populateData : function () {
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.has(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.has(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.has(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.has(cityId)) {
this._cityCountryHash.set(cityId, countryCode)
}
if (!this.programs.get(programId).countries.get(countryCode).cities.get(cityId).schools.has(this._schoolsList[i].schoolId)) {
var school = new Object();
school.name = this._schoolsList[i].schoolName;
school.id = this._schoolsList[i].schoolId;
if (!this._schoolsHash.has(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._data = new Object();
this._data.programs = new Array();
for (var i = 0; i < this.programs.getKeys().length; i++) {
var program = this.programs.get(this.programs.getKeys()[i]);
var programObj = new Object();
programObj.id = program.id;
programObj.name = program.name;
programObj.countries = new Array();
for (var j = 0; j < program.countries.getKeys().length; j++) {
var country = program.countries.get(program.countries.getKeys()[j]);
var countryObj = new Object();
countryObj.id = country.id;
countryObj.name = country.name;
countryObj.cities = new Array();
for (var k = 0; k < country.cities.getKeys().length; k++) {
var city = country.cities.get(country.cities.getKeys()[k]);
var cityObj = new Object();
cityObj.id = city.id;
cityObj.name = city.name;
cityObj.schools = new Array();
for (var l = 0; l < city.schools.getKeys().length; l++) {
var school = city.schools.get(city.schools.getKeys()[l]);
var schoolObj = new Object();
schoolObj.id = school.id;
schoolObj.name = school.name;
cityObj.schools.push(schoolObj);
}
cityObj.schools.sort(this.sortFunction);
countryObj.cities.push(cityObj);
}
countryObj.cities.sort(this.sortFunction);
programObj.countries.push(countryObj);
}
programObj.countries.sort(this.sortFunction);
this._data.programs.push(programObj);
}
this._data.programs.sort(this.sortFunction);
},
render : function () {
var programsTemplate = this._booking.getProgramsListTemplate(this._data);
var countriesTemplate = this._booking.getCountriesListTemplate(null, this._data);
var citiesTemplate = this._booking.getCitiesListTemplate(null, null, this._data);
var schoolsTemplate = this._booking.getSchoolsListTemplate(null, null, null, this._data);
programsTemplate.getElement().render(this._data, programsTemplate.getDirective());
countriesTemplate.getElement().render(false, countriesTemplate.getDirective());
citiesTemplate.getElement().render(false, citiesTemplate.getDirective());
schoolsTemplate.getElement().render(false, schoolsTemplate.getDirective());
this._programSelectorList = this._booking.populateList(document.getElement(programsTemplate.getSelector()));
this._programSelectorList.addEvent('change', function(e) {
this.onProgramChange(this._programSelectorList.getValue());
}.bind(this));
this._countrySelectorList = this._booking.populateList(document.getElement(countriesTemplate.getSelector()));
this._countrySelectorList.addEvent('change', function(e) {
this.onCountryChange(this._countrySelectorList.getValue());
}.bind(this));
this._citySelectorList = this._booking.populateList(document.getElement(citiesTemplate.getSelector()));
this._citySelectorList.addEvent('change', function(e) {
this.onCityChange(this._citySelectorList.getValue());
}.bind(this));
this._schoolSelectorList = this._booking.populateList(document.getElement(schoolsTemplate.getSelector()));
this._schoolSelectorList.addEvent('change', function(e) {
this.onSchoolChange(this._schoolSelectorList.getValue());
}.bind(this));
this.clearListSelection(this._countrySelectorList);
this.clearListSelection(this._citySelectorList);
this.clearListSelection(this._schoolSelectorList);
this.fireEvent('updated');
},
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;
}
},
/**
* Function called when program is changed
*
* @param SchoolListItem item The new item
*/
onProgramChange : function(programId) {
if (this._selectedProgramId != programId) {
this.setListSelection(this._programSelectorList, programId);
this._selectedProgramId = programId;
this._selectedCityId = null;
this._selectedCountryId = null;
this._selectedSchoolId = null;
this._countries = new Array();
this._cities = new Array();
this._schools = new Array();
for (var i = 0; i < this._data.programs.length; i++) {
if (this._data.programs[i].id == programId || !programId) {
this._countries = this._data.programs[i].countries;
break;
}
}
var countriesTemplate = this._booking.getCountriesListTemplate(this._selectedProgramId, this._countries);
var citiesTemplate = this._booking.getCitiesListTemplate(this._selectedProgramId, this._selectedCountryId, this._cities);
var schoolsTemplate = this._booking.getSchoolsListTemplate(this._selectedProgramId, this._selectedCountryId, this._selectedCityId, this._schools);
citiesTemplate.getElement().render(false, citiesTemplate.getDirective());
schoolsTemplate.getElement().render(false, schoolsTemplate.getDirective());
this._citySelectorList.updateListOptions(document.getElement(citiesTemplate.getSelector()));
this._schoolSelectorList.updateListOptions(document.getElement(schoolsTemplate.getSelector()));
this.clearListSelection(this._citySelectorList);
this.clearListSelection(this._schoolSelectorList);
if (programId && programId > 0) {
countriesTemplate.getElement().render(this._countries, countriesTemplate.getDirective());
this._countrySelectorList.updateListOptions(document.getElement(countriesTemplate.getSelector()));
if (this._countries.length == 1) {
this.setListSelection(this._countrySelectorList, this._countries[0].id);
} else {
this.clearListSelection(this._countrySelectorList);
}
} else {
countriesTemplate.getElement().render(false, countriesTemplate.getDirective());
this._countrySelectorList.updateListOptions(document.getElement(countriesTemplate.getSelector()));
this.clearListSelection(this._countrySelectorList);
}
}
this.fireEvent('updated');
this.fireEvent('changeSchool');
},
/**
* Function called when the country change
* @param SchoolListItem item The new item
*/
onCountryChange : function(countryCode) {
if (this._selectedCountryId != countryCode) {
this.setListSelection(this._countrySelectorList, countryCode);
this._selectedCountryId = countryCode;
this._selectedCityId = null;
this._selectedSchoolId = null;
this._cities = new Array();
this._schools = new Array();
for (var i = 0; i < this._countries.length; i++) {
if (this._countries[i].id == countryCode) {
this._cities = this._countries[i].cities;
break;
}
}
var citiesTemplate = this._booking.getCitiesListTemplate(this._selectedProgramId, this._selectedCountryId, this._cities);
var schoolsTemplate = this._booking.getSchoolsListTemplate(this._selectedProgramId, this._selectedCountryId, this._selectedCityId, this._schools);
schoolsTemplate.getElement().render(false, schoolsTemplate.getDirective());
this._schoolSelectorList.updateListOptions(document.getElement(schoolsTemplate.getSelector()));
this.clearListSelection(this._schoolSelectorList);
if (countryCode) {
citiesTemplate.getElement().render(this._cities, citiesTemplate.getDirective());
this._citySelectorList.updateListOptions(document.getElement(citiesTemplate.getSelector()));
if (this._cities.length == 1) {
this.setListSelection(this._citySelectorList, this._cities[0].id);
} else {
this.clearListSelection(this._citySelectorList);
}
} else {
citiesTemplate.getElement().render(false, citiesTemplate.getDirective());
this._citySelectorList.updateListOptions(document.getElement(citiesTemplate.getSelector()));
this.clearListSelection(this._citySelectorList);
}
this.fireEvent('updated');
this.fireEvent('changeSchool');
}
},
/**
* Function called when the city change
* @param SchoolListItem item The new item
*/
onCityChange : function(cityId) {
if (this._selectedCityId != cityId) {
this.setListSelection(this._citySelectorList, cityId);
this._selectedCityId = cityId;
this._selectedSchoolId = null;
this._schools = new Array();
for (var i = 0; i < this._cities.length; i++) {
if (this._cities[i].id == cityId) {
this._schools = this._cities[i].schools;
break;
}
}
var schoolsTemplate = this._booking.getSchoolsListTemplate(this._selectedProgramId, this._selectedCountryId, this._selectedCityId, this._schools);
if (cityId > 0) {
schoolsTemplate.getElement().render(this._schools, schoolsTemplate.getDirective());
this._schoolSelectorList.updateListOptions(document.getElement(schoolsTemplate.getSelector()));
if (this._schools.length == 1) {
this.setListSelection(this._schoolSelectorList, this._schools[0].id);
} else {
this.clearListSelection(this._schoolSelectorList);
}
} else {
schoolsTemplate.getElement().render(false, schoolsTemplate.getDirective());
this._schoolSelectorList.updateListOptions(document.getElement(schoolsTemplate.getSelector()));
this.clearListSelection(this._schoolSelectorList);
}
this.fireEvent('updated');
this.fireEvent('changeSchool');
}
},
/**
* Function called when the school change
* @param SchoolListItem item The new item
*/
onSchoolChange : function(schoolId) {
this.setListSelection(this._schoolSelectorList, schoolId);
if (this._selectedSchoolId != schoolId) {
this._selectedSchoolId = schoolId;
this.fireEvent('updated');
this.fireEvent('changeSchool');
}
},
/**
* 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.has(school)) {
var schoolObject = this._schoolsHash.get(school);
this.onProgramChange(schoolObject.schoolProgramId);
this.onCountryChange(schoolObject.schoolCountryCode);
this.onCityChange(schoolObject.schoolCityId);
this.onSchoolChange(school);
}
} else {
if (program.toInt()) {
this.onProgramChange(program);
if (country) {
this.onCountryChange(country);
}
if (city) {
if (!country) {
this.onCountryChange(this._cityCountryHash.get(city));
}
this.onCityChange(city);
}
}
}
},
setListSelection : function(list, value) {
if (!list) {
return false;
}
var valueFound = list.setValue(value);
var element = this.getListElement(list);
if (!element || !element.options) {
return valueFound;
}
var normalizedValue = value == null ? '' : String(value);
var selectedIndex = -1;
for (var i = 0; i < element.options.length; i++) {
if (String(element.options[i].value) == normalizedValue) {
selectedIndex = i;
break;
}
}
for (var j = 0; j < element.options.length; j++) {
element.options[j].selected = j == selectedIndex;
}
if (selectedIndex >= 0) {
element.selectedIndex = selectedIndex;
if (element.set) {
element.set('value', normalizedValue);
} else {
element.value = normalizedValue;
}
} else {
element.selectedIndex = 0;
if (element.options.length) {
element.options[0].selected = true;
}
if (element.set) {
element.set('value', '');
} else {
element.value = '';
}
}
return valueFound;
},
clearListSelection : function(list) {
if (!list) {
return;
}
list.setValue('');
var element = this.getListElement(list);
if (element && element.options && element.options.length) {
for (var i = 0; i < element.options.length; i++) {
element.options[i].selected = false;
}
element.options[0].selected = true;
element.selectedIndex = 0;
if (element.set) {
element.set('value', '');
} else {
element.value = '';
}
}
},
getListElement : function(list) {
var element = list ? (list._list || list._listElement) : null;
if (element && element.get && element.get('tag') != 'select' && element.getElement('select')) {
element = element.getElement('select');
}
return element;
},
/**
* Returns the number of schoolSelector
*
* @return number The number of schoolSelectors
*/
getSelectedSchoolId : function() {
if(this._schoolsList.length == 1)
return this._schoolsList[0].schoolId;
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 integer type the transfer type    1 : One way only   2 : round trip  3 : all   4 : way back only
* @param SchoolTransfers parent
**/
var SchoolTransferObject = new Class({
Implements: Events,
/**
* This is the initialization function
*/
initialize : function(id, name, type, parent) {
//        this._translateDTO = translateDTO;
this._transferName = name;
this._type = type;
this._transferId = id;
this._parent = parent;
this._isMandatory = false;
var options = this.getOptions();
if(options.length){
this.setTransferType(options[0].id);
}
// transferType 1 for round trip, 2 for one way at arrival , 3 for one way to departure
// the transfer value type
this._value = 1;
},
/**
* 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._transferTypeData;
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;
this.fireEvent('transferUpdated');
},
/**
* 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.setTransferType(parseInt(toPopulateDTO.roundTrip));
},
/**
* Return true if the transfer is complete
*
* @return Boolean Return true if complete
*/
isComplete : function() {
if (this._value != -1) {
return true;
}
},
/**
* Return the transfer type
*/
getTransferType : function () {
return this._transferTypeData;
},
/**
* Return the transfer type
*
* set the transfer type
* @param integer transferType (0 : onef way, 1 : roundtrip, 2 : way back
*
*/
setTransferType : function (transferType) {
this._transferTypeData = transferType;
this.fireEvent('transferUpdated');
},
/**
* Return an array containing the options
*/
getOptions : function() {
var options = new Array();
if (this._type != 2 && this._type != 4) {
options.push({'id': 0 , 'name' : 'oneWay'});
}
if (this._type != 2 && this._type != 1) {
options.push({'id': 2 , 'name' : 'wayBack'});
}
if (this._type != 1 && this._type != 4) {
options.push({'id': 1 , 'name' : 'roundTrip'});
}
return options;
},
/**
* 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.set("html", this._transferName);
if (this._transfersList._listItems.length) {
this._transfersList.getHtml().destroy();
this._transfersList.clear();
}
this.getVisualTransferOptionsList(this._transfersList);
this._transfersList.getHtml().inject(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');
},
/**
* Set the element container of this transfer
*
* @param element
*/
setElement : function(element){
this._element = element;
},
/**
* Set the element container of this transfer
*
* @return  The element containing this transfer
*/
getElement : function(){
return this._element;
},
/**
* Remove the transfer from the list
*
*/
removeTransfer : function() {
this.fireEvent('deleteTransfer');
}
});
/**
* 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 = new Class({
Implements: Events,
/**
* This is the initialization function
*/
initialize : function(schoolTransfersDTO, parent) {
this._schoolTransfersDTO = schoolTransfersDTO;
this._translateDTO = {};
this._school = this._parent = parent;
this._booking = this._school.getBooking();
this._transfers = new Array();
},
/**
* 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.erase(this._transfers[i]);
i--;
}
}
this.addTransfer(item.id);
if(this._transfers.length){
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._school.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) {
this._availableTransfers = this._school.getAvailableTransfers();
},
getValidTransfersList : function () {
if(!this._availableTransfers)
this._availableTransfers = new Array();
return this._availableTransfers;
},
/**
* Return the added transfers
*
* @return TransferObject[] The added transfers
*/
getTransfers : function() {
return this._transfers;
},
/**
* Refresh the transfers lists
*
*/
refreshTransfers : function() {
var transfNb = this._transfers.length;
this.refreshVisualTransferList(this._transfersList);
if (this._school.getCompletedCourses().length == 0) {
for (var i = this._transfers.length - 1; i >= 0; i--) {
this._transfers[i].removeTransfer();
this._transfers.erase(this._transfers[i]);
}
this._school.fireEvent('heightModified');
if (transfNb > 0)this._school.fireEvent('refreshPrice');
} else {
// get the available transfers List
var availableTransfers = this._school.getAvailableTransfers();
// remove the unavailable transfers
this._transfers.each(function(item) {
if (!availableTransfers.contains(item.getTransferId())) {
item.removeTransfer();
this._transfers.erase(item);
}
}.bind(this));
// add transfers if they are mandatory
if (!this._transfers.length && availableTransfers.length && this._school.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._school.getIsTransferMandatory() && this._transfers.length) {
this._transfers[0].setIsMandatoryTransfer(true);
}
}
}
if (!this._school.getIsTransferMandatory()) {
for (var i = 0; i < this._transfers.length; i++) {
this._transfers[i].setIsMandatoryTransfer(false);
}
}
this.fireEvent('transfersUpdated');
/*
if ((this._school.getIsTransferMandatory() == true && this._transfers.length) || this._school.getCompletedAccommodations().length == 0) {
this.displayAddButton(false);
} else {
this.displayAddButton(true);
}*/
},
/**
* Add a transfer from its ID
*
* @param Integer id The transfer id
*/
addTransfer : function(id) {
var schoolTransfersDTO = Array.from(this._schoolTransfersDTO);
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);
this._transfers.push(newTransfer);
newTransfer.addEvent('deleteTransfer', function(e) {
this.deleteTransfer(newTransfer);
}.bind(this));
newTransfer.addEvent('transferUpdated', function(e) {
this.fireEvent('transfersUpdated');
}.bind(this));
this.refreshTransfers();
this.fireEvent('transferAdded', newTransfer);
return newTransfer;
},
replaceTransfer : function(oldTransfer, newTransferId){
var oldTransferIndex = this._transfers.indexOf(oldTransfer);
var dto = oldTransfer.getDTO();
var schoolTransfersDTO = Array.from(this._schoolTransfersDTO);
var schoolTransfer = schoolTransfersDTO.filter(function(item, index) {
return item.id == newTransferId;
}.bind(this));
var newTransfer = new SchoolTransferObject(schoolTransfer[0].id, schoolTransfer[0].name, schoolTransfer[0].type, this);
this._transfers.splice(oldTransferIndex, 1, newTransfer);
newTransfer.addEvent('deleteTransfer', function(e) {
this.deleteTransfer(newTransfer);
}.bind(this));
newTransfer.addEvent('transferUpdated', function(e) {
this.fireEvent('transfersUpdated');
}.bind(this));
newTransfer.populateFromDTO(dto);
this.refreshTransfers();
this.fireEvent('transferAdded', newTransfer);
return newTransfer;
},
/**
* Returns the parent of this object
*
* @return SchoolPriceEstimation The parent
*/
getParent : function() {
return this._school;
},
/**
* 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.erase(transfer);
this.fireEvent('transfersUpdated');
},
/**
* Remove all transfers
*/
removeAllTransfers : function () {
this._transfers = new Array();
this.fireEvent('transfersUpdated');
}
});/**
* 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 = new Class({
Extends: SchoolCourseObject,
/**
* This is the initialization function
*
*/
initialize : function(courseDetails, schoolCourses) {
this.parent(courseDetails, schoolCourses, 'variable');
this.type = 'variable';
// the course start dates
this._startDatesObjects = new Array();
this._courseDetails.startDates.each(function(item, index) {
this._startDatesObjects.push({id : item.getTime() , name : item.format(this._dateFormat, this._monthsTranslations)});
// we store the dates values so the list is populated with the right object not the value stored in the dom object
}.bind(this));
// the course durations
this._durations = new Array();
this._courseDetails.duration.each(function(item, index) {
this._durations.push({id : item , name : item });
}.bind(this));
},
/**
* set the course duration
*
* @param integer duration The duration
*/
setCourseDuration : function(duration){
this._courseDuration = duration;
this.refreshCourseData();
},
/**
* set the course startDate
*
* @param integer duration The duration
*/
setCourseStartDate : function(startDate){
this._courseStartDate = startDate;
this.refreshCourseData();
},
/**
* Refresh the course end date template
*/
refreshCourseEndDateTemplate : function () {
//        var courseEndDateTemplate = this._booking.getSchoolCourseEndDateTemplate(this);
//        if(courseEndDateTemplate && this._element){
//            var endDate = this._courseEndDate ? this._courseEndDate.format(this._dateFormat , this._monthsTranslations) : '';
//            $p(courseEndDateTemplate.getSelector(), this._element).render({date : endDate}, courseEndDateTemplate.getDirective());
//        }
},
/**
* Populate the variable course from a dto
*
* @param Object The fixed course informations needed to populate
*/
populateFromDTO : function(toPopulateDTO) {
this.refreshLists();
var validStartDates = this.getCourseValidStartDatesTime();
if (validStartDates.length) {
var startDate = toPopulateDTO.startDate;
var endDate = toPopulateDTO.endDate;
if(!(startDate instanceof Date)){
startDate = (new Date()).fromIso(startDate);
}
if(!(endDate instanceof Date)){
endDate = (new Date()).fromIso(endDate);
}
var duration = this.getCalculatedDuration(startDate, endDate);
// find the best start date
if (validStartDates.contains(startDate.getTime())) {
this._courseStartDate = startDate;
} else {
var startDateTime = startDate.getTime();
var diff = -1;
for (var i = 0; i < validStartDates.length; i ++) {
if (diff == -1 || diff > Math.abs(parseInt(validStartDates[i]) - startDateTime)) {
this._courseStartDate = new Date(parseInt(validStartDates[i]));
diff = Math.abs(parseInt(validStartDates[i]) - startDateTime);
}
}
}
// find the best duration
this.refreshLists();
if (duration) {
var validDurations = this.getCourseValidDurations();
if (validDurations.contains(duration + '')) {
this._courseDuration = duration;
} else {
var diff = -1;
for (var i = 0; i < validDurations.length; i ++) {
if (diff == -1 || diff > Math.abs(parseInt(validDurations[i]) - duration)) {
this._courseDuration = validDurations[i];
diff = Math.abs(parseInt(validDurations[i]) - duration);
}
}
}
}
}
this.refreshCourseData();
},
/**
* 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.refreshCourseStartDatesList(this._schoolCourses.getValidVariableCourseStartDate(this));
// initialize the duration list and its event
this.refreshCourseDurationList(this._schoolCourses.getValidVariableCourseDuration(this));
// 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();
}*/
},
/**
* Refresh the course data
*
*/
refreshCourseData : function() {
// If the start and the duration are set,  the end date is calculated
if (this._courseStartDate && this._courseDuration) {
this._courseEndDate = this.getVariableCourseEndDate();
}
// when the user selects only the start date
if (this._courseStartDate && !this._courseDuration) {
if(this._courseDuration){
this._courseEndDate = this.getVariableCourseEndDate();
}else {
this.refreshCourseDurationList(this._schoolCourses.getValidVariableCourseDuration(this));
}
}
this.fireEvent('courseUpdated');
},
/**
*  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 (newCourse.type != 'fixed') {
if (this.isComplete()) {
this._courseDetails = newCourse;
this._durationValue.addClass(this._classNameBase + 'Section-Item-Info-Value');
this.replaceVariableCourseDates(this._courseStartDate, this._courseDuration);
this._title.set("html", this._courseDetails.name);
this._subTitle.set("html", this._courseDetails.subtitle);
this.reGenerateLists();
this.fireEvent('courseUpdated');
} else {
this._schoolStartList.getHtml().destroy();
this._schoolDurationList.getHtml().destroy();
this._coursesValidList.getHtml().destroy();
this._schoolCourses.replaceCourse(this, newCourse);
}
} else {
this._schoolStartList.getHtml().destroy();
this._schoolDurationList.getHtml().destroy();
this._coursesValidList.getHtml().destroy();
if (this.isComplete()) {
this._schoolCourses.replaceCourse(this, newCourse, this._courseStartDate);
} else {
this._schoolCourses.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.set("html", this._translateDTO.weeks.replace("%0", this._courseDuration));
} else {
this._durationValue.set("html", this._translateDTO.week.replace("%0", this._courseDuration));
}
}
this._courseStartDate = newDate;
this._startDateValue.set("html", newDate.format(this._dateFormat , this._monthsTranslations));
this.refreshCourseData();
}
},
/**
* Refresh a list of course that have possible dates between this courseStartDate and courseEndDate
*
* @param SchoolList list The courses list
*   todo
*/
refreshVisualValidCoursesList : function(list) {
var validCourses = this._schoolCourses.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 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
*/
refreshCourseStartDatesList : function(validStartDates) {
this._validStartDatesList = new Array();
for(var i = 0; i < validStartDates.length; i++){
this._validStartDatesList.push(validStartDates[i]);
}
},
/**
* Return a list with the valid start dates time stamp
*
* @return string[] The valid start dates
*/
getCourseValidStartDates : function (){
if(!this._validStartDatesList)
this._validStartDatesList = new Array();
return this._validStartDatesList;
},
/**
* Return a list with the valid start dates time stamp
*
* @return string[] The valid start dates
*/
getCourseValidStartDatesTime : function (){
if(!this._validStartDatesList)
this._validStartDatesList = new Array();
var validStartDateTime = new Array();
for(var i = 0; i < this._validStartDatesList.length; i++){
validStartDateTime.push(this._validStartDatesList[i].getTime());
}
return validStartDateTime;
},
/**
* Return a list with the valid start dates time stamp
*
* @return string[] The valid start dates
*/
getCourseValidDurations : function (){
if(!this._validDurationsList)
this._validDurationsList = new Array();
return this._validDurationsList;
},
/**
* 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
*/
refreshCourseDurationList : function(validDurations) {
this._validDurationsList = validDurations;
},
/**
* Returns false is it's not a fixed course
*
* @return Boolean Return false because it's a variable course
*/
getIsFixedCourse : function() {
return false;
}
});
var BookingManager = new Class({
Implements: [Events, Options],
options: {
shoppingCartPage: false, // True if it's a shopping cart page
courseTypeContainer : '',
accommodationTypeContainer : '',
insuranceContainer : '',
promotionIntroductionContainer : '',
promotionContainer : '',
onlyWebsiteSchools : false
},
/**
* This is the initialization function
*/
initialize : function(options) {
this.setOptions(options);
this.createDirectives();
var programDir = this._directives.get('programsListDirective');
var countryDir = this._directives.get('countriesListDirective');
var cityDir = this._directives.get('citiesListDirective');
var schoolDir = this._directives.get('schoolsListDirective');
this.booking = new Booking({
shoppingCartPage: this.options.shoppingCartPage,
input: $('bookingOption'),
output: $('bookingCart'),
schoolsSelectorContainer: $('schoolsSelector'),
header: $('bookingLinks'), // the header block
printOutput: $("schoolPriceEstimationPrint"),
courseTypeContainer : this.options.courseTypeContainer,
accommodationTypeContainer : this.options.accommodationTypeContainer,
insuranceContainer : this.options.insuranceContainer,
promotionIntroductionContainer : this.options.promotionIntroductionContainer,
promotionContainer : this.options.promotionContainer,
onlyWebsiteSchools : this.options.onlyWebsiteSchools,
getProgramsListTemplateCallback : function  (data) {
return new BookingTemplateObject({selector : '.program-selector',
directive : programDir,
element : $p('.program-selector')});
},
getCountriesListTemplateCallback : function  (programId, data) {
switch (parseInt(programId)) {
default :
return new BookingTemplateObject({selector : '.country-selector',
directive : countryDir
, element : $p('.country-selector')});
break;
}
},
getCitiesListTemplateCallback : function  (programId, countryCode, data) {
return new BookingTemplateObject({selector : '.city-selector',
directive : cityDir,
element : $p('.city-selector')});
},
getSchoolsListTemplateCallback : function  (programId, countryCode, cityId, data) {
return new BookingTemplateObject({selector : '.school-selector',
directive : schoolDir,
element : $p('.school-selector')});
}
});
// The school selector options
this.booking.addEvent('schoolsSelectorLoaded', function() {
this.setActive($('schoolsSelector'), true);
try {
$('schoolsSelector').getElements('select').chosen();
} catch(ex) {
}
this.ensureSchoolSelectorChoices();
this.setActive($$('.country-selector')[0], $$('.country-selector select')[0].getElements('option').length);
this.setActive($$('.city-selector')[0], $$('.city-selector select')[0].getElements('option').length);
this.setActive($$('.school-selector')[0], $$('.school-selector select')[0].getElements('option').length);
this.syncSchoolSelectorChoices();
this.booking.getSchoolsSelector().addEvent('changeSchool', function() {
this.updateEmptyState();
}.bind(this));
this.booking.getSchoolsSelector().addEvent('updated', function() {
this.ensureSchoolSelectorChoices();
this.setActive($$('.country-selector')[0], $$('.country-selector select')[0].getElements('option[value]').length);
this.setActive($$('.city-selector')[0], $$('.city-selector select')[0].getElements('option[value]').length);
this.setActive($$('.school-selector')[0], $$('.school-selector select')[0].getElements('option[value]').length);
this.syncSchoolSelectorChoices();
this.updateEmptyState();
}.bind(this));
this.setActive($('schoolsSelector'), false);
this.updateEmptyState();
}.bind(this));
this.booking.addEvent('initialized', function(){
this.fireEvent('initialized');
}.bind(this));
$("bookingOption").store('booking', this.booking);
// override this method if you want a customized list
this.booking.populateList = function (list, values) {
if (!values)
values = null;
return new BookingList(list, values, '.item-option', '.selector-button');
};
this._initializeBookingEvents();
this.booking.launch();
$('promoField').addEvent('focus', function(e) {
if ($('promoField').get('value') == this.booking.getTranslations().promotions.enterYourCode) {
$('promoField').set('value', '');
}
}.bind(this));
$('promoField').addEvent('blur', function(e) {
if ($('promoField').get('value') == '') {
$('promoField').set('value', this.booking.getTranslations().promotions.enterYourCode)
}
}.bind(this));
$('promotionForm').addEvent('submit', function(e) {
e.stop();
var code = $('promoField').get('value');
if (code && code != this.booking.getTranslations().promotions.enterYourCode) {
$('promoField').setAttribute('disabled', 'disabled');
this.booking.getPromotionsManager().validateCode(code);
}
}.bind(this));
},
/**
* Create a list object container
*
* @param list
* @param values
*/
createList : function(list, values) {
if (!values)
values = null;
return new BookingList(list, values, '.item-option', '.selector-button');
},
updateSchoolDescriptions : function(school) {
if(school.elementContainer){
var courses = school.elementContainer.getElements('.item-option-course');
var groupToolTip;
var sameCourseType;
var oldCourseType;
var description;
var currentGroup = new Array();
courses.each(function(item, index) {
if (!item.getParent('.item-category') || groupToolTip != item.getParent('.item-category').getElement('.item-tool-tip')) {
if (groupToolTip && currentGroup.length && sameCourseType) {
groupToolTip.setAttribute('title', description);
groupToolTip.removeClass('hidden');
var tooltip = new SynergeeTips(groupToolTip, {'className':'Booking-Tool-Tip Tool-tip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
} else {
currentGroup.each(function(tip, index) {
tip.removeClass('hidden');
var tooltip = new SynergeeTips(tip, {'className':'Booking-Tool-Tip Tool-tip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
}.bind(this));
}
currentGroup = new Array();
sameCourseType = item.getParent('.item-category');
oldCourseType = -1;
groupToolTip = item.getParent('.item-category') ? item.getParent('.item-category').getElement('.item-tool-tip') : null;
}
var toolTipEl = item.getElement('.item-tool-tip');
if (toolTipEl) {
var courseInfo = school.getCoursesManager().getCourseInformationDTO(parseInt(item.getAttribute('value')));
if (courseInfo) {
if (oldCourseType != -1 && courseInfo.courseTypeId != oldCourseType) {
sameCourseType = false;
}
oldCourseType = courseInfo.courseTypeId;
description = this.booking.getDescription('course', courseInfo.courseTypeId);
if (description) {
currentGroup.push(toolTipEl);
toolTipEl.setAttribute('title', description);
}
} else {
sameCourseType = false;
}
}
}.bind(this));
if (groupToolTip && currentGroup.length && sameCourseType) {
groupToolTip.setAttribute('title', description);
groupToolTip.removeClass('hidden');
var tooltip = new SynergeeTips(groupToolTip, {'className':'Booking-Tool-Tip Tool-tip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
} else {
currentGroup.each(function(tip, index) {
tip.removeClass('hidden');
var tooltip = new SynergeeTips(tip, {'className':'Booking-Tool-Tip Tool-tip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
}.bind(this));
}
var accommodations = school.elementContainer.getElements('.item-option-accommodation');
accommodations.each(function(item, index) {
var toolTipEl = item.getParent('.item-category').getElement('.item-tool-tip');
if (toolTipEl) {
var accommodationInfo = school.getAccommodationsManager().getAccommodationOptionInformations(parseInt(item.getAttribute('value')));
if (accommodationInfo) {
description = this.booking.getDescription('accommodation', accommodationInfo.accommodationDTO.accommodationType);
if (description) {
currentGroup.push(toolTipEl);
toolTipEl.setAttribute('title', description);
toolTipEl.removeClass('hidden');
var tooltip = new SynergeeTips(toolTipEl, {'className':'Booking-Tool-Tip Tool-tip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
}
}
}
}.bind(this));
}
},
_initializeBookingEvents : function () {
this.booking.addEvent('descriptionsUpdated', function() {
this.booking.getSchools().each(function(school, index) {
this.updateSchoolDescriptions.delay(700, this, school);
}.bind(this));
var insurances = $('insurancesContainer').getElements('.item-option-insurance');
insurances.each(function(item, index) {
var toolTipEl = item.getElement('.item-tool-tip');
if (toolTipEl) {
var description = this.booking.getDescription('insurance', parseInt(item.getAttribute('value')));
if (description) {
toolTipEl.setAttribute('title', description);
toolTipEl.removeClass('hidden');
var tooltip = new SynergeeTips(toolTipEl, {'className':'Booking-Tool-Tip Tool-tip', 'hideDelay':1000, 'fixed':true, 'closeButton':true, 'maxHeight':280});
}
}
}.bind(this));
}.bind(this));
// when the booking is initialized we start the rendering of the booking
this.booking.addEvent('initialized', function() {
//
// The main schools rendering
//
var schoolsTemplate = this.getSchoolsTemplate(this.booking.getSchoolsDTO());
schoolsTemplate.getElement().render(this.booking.getSchoolsDTO(), schoolsTemplate.getDirective());
//
// display or not the school selector
//
if (!this.booking.getIsShoppingCartPage() && this.booking._initDTO.schoolsList.length > 1) {
$('schoolsSelector').removeClass('inActive');
}
this.updateEmptyState();
this.booking.getPromotionsManager().addEvent('promotionAlreadyAdded', function() {
this.booking.displayMessage(this.booking.getTranslations().promotions.promotionAlreadyAdded);
$('promoField').set('value', this.booking.getTranslations().promotions.enterYourCode);
$('promoField').removeAttribute('disabled');
}.bind(this));
this.booking.getPromotionsManager().addEvent('promotionAdded', function() {
$('promoField').set('value', this.booking.getTranslations().promotions.enterYourCode);
$('promoField').removeAttribute('disabled');
//            this.booking.displayMessage(this.booking.getTranslations().promotions.promotionAlreadyAdded);
}.bind(this));
this.booking.getPromotionsManager().addEvent('invalidCode', function() {
this.booking.displayMessage(this.booking.getTranslations().promotions.invalidCode);
$('promoField').removeAttribute('disabled');
$('promoField').set('value', this.booking.getTranslations().promotions.enterYourCode);
}.bind(this));
this.bookingCalendar = new BookingCalendar({
days: this.booking._translateDTO.days, // days of the week starting at sunday
months: this.booking._translateDTO.months,
offset: this.booking._translateDTO.firstDayOfWeek
});
this.bookingCalendar.addEvent('dateselected', function(e) {
this.bookingCalendar.hide();
this.bookingCalendar.getCallBackMethod().call(this.bookingCalendar.getBind(), this.bookingCalendar.getSelectedDate());
}.bind(this));
// The currency selector
var currencies = this.booking.currency.getAvailableCurrencies();
var currenciesListTp = this.getCurrenciesListTemplate(this.booking, currencies);
if (currenciesListTp) {
$p(currenciesListTp.getSelector()).render(currencies, currenciesListTp.getDirective());
if (currencies.length > 1) {
$$('.currencies-list select').set('value', this.booking.currency.getCurrency());
$$('.currencies-list select').addEvent('change', function(e) {
var value = $$('.currencies-list select').get('value');
if (value.length && value[0] != this.booking.currency.getCurrency() && value[0] != '') {
this.booking.currency.setCurrency(value[0]);
}
}.bind(this));
$$('.currencies-list select').chosen();
}
}
//
// The insurances List
//
var insurancesListTp = this.getInsurancesListTemplate(this.booking);
if (insurancesListTp) {
var insurances = new Array();
this.booking.getInsurancesManager().getInsurances().each(function(item, index) {
insurances.push(item);
}.bind(this));
insurances.sort(function(a, b){
var nameA = a.name.toLowerCase(), nameB = b.name.toLowerCase()
if (nameA < nameB) //sort string ascending
return -1
if (nameA > nameB)
return 1
return 0 //default return value (no sorting)
});
$p(insurancesListTp.getSelector()).render(insurances, insurancesListTp.getDirective());
if(!insurances.length){
$('insurancesContainer').addClass('hidden');
}else{
$('insurancesContainer').removeClass('hidden');
}
$$('.insurances-list .item-option-radio').addEvent('change', function(e) {
var insuranceId = parseInt(e.target.value);
if (e.target.checked) {
// check if it's already added
var addInsurance = true;
this.booking.getInsurancesManager().getAddedInsurances().each(function(item, index) {
if (parseInt(item.getInsuranceId()) == insuranceId) {
// the course is already in the basket
addInsurance = false;
}
}.bind(this));
if (addInsurance) {
this.booking.getInsurancesManager().addInsurance(insuranceId);
}
} else {
this.booking.getInsurancesManager().getAddedInsurances().each(function(item, index) {
if (parseInt(item.getInsuranceId()) == insuranceId) {
this.booking.getInsurancesManager().deleteInsurance(item);
}
}.bind(this));
}
}.bind(this));
}
//
// when an insurance is added, it adds some listener to
//
this.booking.getInsurancesManager().addEvent('insuranceAdded', function(insurance) {
// the insurance events
insurance.addEvent('refresh', function(e) {
if (insurance.getElement()) {
insurance.getElement().getParent().getElement('input').checked = 'checked';
}
}.bind(this));
insurance.fireEvent('refresh');
}.bind(this));
//
// refresh the rendering of the insurances
//
this.booking.getInsurancesManager().addEvent('insurancesUpdated', function(e) {
$$('.insurance-container').addClass('hidden');
this.booking.getInsurancesManager().getAddedInsurances().each(function(insurance, index) {
insurance.setElement($$('.insurances-list')[0].getElement(('.item-option-insurance[value=' + insurance.getInsuranceId() + '] .insurance-container')));
insurance.fireEvent('refresh');
}.bind(this));
this.updateInsurancesList();
}.bind(this));
//
// Check each school in the booking
//
this.booking.getSchools().each(function(school, index) {
$('bookingOption').removeClass('inActive');
$('bookingCart').removeClass('inActive');
this.updateEmptyState();
school.elementContainer = document.getElement(schoolsTemplate.getSelector()).getElements('.school-container')[index];
//
// the courses list
//
var schoolCoursesListTp = this.getSchoolCoursesListTemplate(school._schoolDTO);
if (schoolCoursesListTp) {
// retrieve the courses list
var coursesTree = new Array();
var courses = school.getCoursesManager().getCourses();
// Retrieve the minimum price to display
courses.each(function(item, index){
var priceFound = false;
item.prices.each(function(price, index){
if(price.currency == bookingManager.booking.currency.getCurrency()){
item.displayPrice = price.price;
priceFound = true;
}
});
if(!priceFound)
item.displayPrice = item.price;
});
$p(schoolCoursesListTp.getSelector(), school.elementContainer).render(courses, schoolCoursesListTp.getDirective());
school.elementContainer.getElements('.item-option-course .item-option-radio').addEvent('change', function(e) {
var courseId = parseInt(e.target.value);
var addCourse = true;
school.getCoursesManager()._courses.each(function(item, index) {
if (parseInt(item.getCourseDetails().id) == courseId) {
// the course is already in the basket
addCourse = false;
}
}.bind(this));
if (addCourse) {
// check if there is an old course
this._lastSchoolDTO = school.getDTO();
school.getCoursesManager().removeAllCourses(false, true);
var course = school.getCoursesManager().addCourseFromId(courseId);
if (this._lastSchoolDTO.fixedDatesCourses.length || this._lastSchoolDTO.variableDatesCourses.length) {
var oldCourse = this._lastSchoolDTO.variableDatesCourses.length ? this._lastSchoolDTO.variableDatesCourses[0] : this._lastSchoolDTO.fixedDatesCourses[0];
course.populateFromDTO(oldCourse);
}
if (this._lastSchoolDTO && this._lastSchoolDTO.accommodations.length) {
school.getAccommodationsManager().removeAllAccommodations(true);
school.getAccommodationsManager().addAccommodation(null, this._lastSchoolDTO.accommodations[0].id);
}
}
}.bind(this));
}
//
// the optional courses list
//
var courses = school.getCoursesManager().getOptionalCourses();
// Retrieve the minimum price to display
courses.each(function(item, index){
var priceFound = false;
item.prices.each(function(price, index){
if(price.currency == bookingManager.booking.currency.getCurrency()){
item.displayPrice = price.price;
priceFound = true;
}
});
if(!priceFound)
item.displayPrice = item.price;
});
var schoolOptionalCoursesListTp = this.getSchoolOptionalCoursesListTemplate(school._schoolDTO);
if (schoolOptionalCoursesListTp) {
$p(schoolOptionalCoursesListTp.getSelector(), school.elementContainer).render(courses, schoolOptionalCoursesListTp.getDirective());
if(!school.getCoursesManager().getOptionalCourses().length){
$$('.options-section').addClass('hidden');
}else {
$$('.options-section').removeClass('hidden');
}
school.elementContainer.getElements('.item-option-optional-course .item-option-radio').addEvent('change', function(e) {
var courseId = parseInt(e.target.value);
if (e.target.checked) {
// check if it's already added
var addCourse = true;
school.getCoursesManager()._optionalCourses.each(function(item, index) {
if (parseInt(item.getCourseDetails().id) == courseId) {
// the course is already in the basket
addCourse = false;
}
}.bind(this));
if (addCourse) {
var optionalCourse = school.getCoursesManager().addCourseFromId(courseId);
if (optionalCourse && optionalCourse.getCourseValidStartDates().length) {
optionalCourse.setCourseStartDate(optionalCourse.getCourseValidStartDates()[0]);
// set the first possible duration by default
if (!optionalCourse.getCourseDuration()) {
if (optionalCourse.getCourseValidDurations().length)
optionalCourse.setCourseDuration(optionalCourse.getCourseValidDurations()[0]);
}
}
}
} else {
school.getCoursesManager()._optionalCourses.each(function(item, index) {
if (parseInt(item.getCourseDetails().id) == parseInt(courseId)) {
school.getCoursesManager().deleteCourse(item);
}
}.bind(this));
}
}.bind(this));
}
//
// The accommodations list
//
var schoolAccommodationsListTp = this.getSchoolAccommodationsListTemplate(school._schoolDTO);
if (schoolAccommodationsListTp) {
var accommodations = school.getAccommodationsManager()._schoolAccommodationsDTO;
// Retrieve the minimum price to display
accommodations.each(function(item, index){
item.option.each(function(opt, index){
var priceFound = false;
opt.prices.each(function(price, index){
if(price.currency == bookingManager.booking.currency.getCurrency()){
opt.displayPrice = price.price;
priceFound = true;
}
});
if(!priceFound)
opt.displayPrice = opt.price;
});
});
$p(schoolAccommodationsListTp.getSelector(), school.elementContainer).render(school.getAccommodationsManager()._schoolAccommodationsDTO, schoolAccommodationsListTp.getDirective());
school.elementContainer.getElements('.school-accommodations-list .item-option-radio').addEvent('change', function(e) {
var accommodationOptionId = parseInt(e.target.value);
if (accommodationOptionId) {
var accommodationInfo = school.getAccommodationsManager()._accommodationsOptions.get(accommodationOptionId);
// check if it's already added
var addAccommodation = true;
school.getAccommodationsManager().getAccommodations().each(function(item, index) {
if (parseInt(item.getAccommodationOptionDetails().id) == accommodationInfo.optionDTO.id) {
// the course is already in the basket
addAccommodation = false;
}
}.bind(this));
if (addAccommodation) {
school.getAccommodationsManager().removeAllAccommodations(true);
school.getAccommodationsManager().addAccommodation(accommodationInfo.accommodationDTO.id, accommodationInfo.optionDTO.id);
}
} else {
school.getAccommodationsManager().removeAllAccommodations();
}
}.bind(this));
}
//
// The Transfers list
//
var schoolTransfersListTp = this.getSchoolTransfersListTemplate(school._schoolDTO);
if (schoolTransfersListTp) {
$p(schoolTransfersListTp.getSelector(), school.elementContainer).render(school.getTransfersManager()._schoolTransfersDTO, schoolTransfersListTp.getDirective());
school.elementContainer.getElements('.school-transfers-list .item-option-radio').addEvent('change', function(e) {
var transferId = parseInt(e.target.value);
if (transferId) {
// check if it's already added
var addTransfer = true;
school.getTransfersManager().getTransfers().each(function(item, index) {
if (parseInt(item.getTransferId()) == transferId) {
// the course is already in the basket
addTransfer = false;
}
}.bind(this));
if (addTransfer) {
school.getTransfersManager().removeAllTransfers(true);
school.getTransfersManager().addTransfer(transferId);
}
} else {
school.getTransfersManager().removeAllTransfers();
}
}.bind(this));
}
//
// when a course is added, it adds some listener to
//
school.getCoursesManager().addEvent('courseAdded', function(course) {
// the courses events
course.addEvent('refresh', function(e) {
if (course.getElement()) {
course.getElement().getParent().getElement('input').checked = 'checked';
course.getElement().removeClass('hidden');
switch (course.getCourseType()) {
case 'optional':
course.refreshLists();
case 'variable':
// start date template
var startDatesTemplate = this.getSchoolCourseStartDatesListTemplate('startDate', course);
if (startDatesTemplate) {
$p(startDatesTemplate.getSelector(), course.getElement()).render({'date' : course.getCourseStartDate() ? course.getCourseStartDate().format(course._dateFormat, course._monthsTranslations) : this.booking._translateDTO.courses.courseObject.dateSelect}, startDatesTemplate.getDirective());
var element = course.getElement().getElement(startDatesTemplate.getSelector());
element.addEvent('click', function() {
this.bookingCalendar.setValidDates(course.getCourseValidStartDates(), 0, 0, 0);
if (course.getCourseStartDate()) {
this.bookingCalendar.setSelectedDate(course.getCourseStartDate(), 0, 0, 0);
}
else {
if (course.getCourseValidStartDates().length)
this.bookingCalendar.displayMonths(course.getCourseValidStartDates()[0].getMonth(), course.getCourseValidStartDates()[0].getFullYear());
}
this.bookingCalendar.show(element, function(date) {
course.setCourseStartDate(date.relativeDate);
// set the first possible duration by default
if (!course.getCourseDuration()) {
if (course.getCourseValidDurations().length)
course.setCourseDuration(course.getCourseValidDurations()[0]);
}
}, this);
}.bind(this));
}
//
// the course duration template
//
var durationsListTemplate = this.getSchoolCourseDurationsListTemplate(course._courseDuration, course);
if (durationsListTemplate) {
var durations = course._durations;
durations.each(function(item, index){
if(item.id == '1'){
item.name =  this.booking.getTranslations().courses.courseObject.week.replace("%0", item.id)
} else {
item.name =  this.booking.getTranslations().courses.courseObject.weeks.replace("%0", item.id)
}
}.bind(this));
$p(durationsListTemplate.getSelector(), course.getElement()).render(durations, durationsListTemplate.getDirective());
// the durations list
if (course.durationsList) {
course.durationsList.removeEvents('change');
course.durationsList.updateListOptions(course.getElement().getElement(durationsListTemplate.getSelector()));
} else {
course.durationsList = this.createList(course.getElement().getElement(durationsListTemplate.getSelector()));
}
course.durationsList.setValidOptions(course.getCourseValidDurations());
course.durationsList.setValue(course.getCourseDuration());
course.durationsList.addEvent('change', function(e) {
course.setCourseDuration(course.durationsList.getValue());
}.bind(this));
}
var courseEndDateTemplate = this.getSchoolCourseEndDateTemplate(course);
if (courseEndDateTemplate && course.getElement()) {
var endDate = course.getCourseEndDate() ? course.getCourseEndDate().format(course._dateFormat, course._monthsTranslations) : '';
$p(courseEndDateTemplate.getSelector(), course.getElement()).render({date : endDate}, courseEndDateTemplate.getDirective());
}
break;
case 'fixed':
course.getElement().removeClass('hidden');
//
// start date template
//
var startDatesListTemplate = this.getSchoolCourseStartDatesListTemplate(course.getCourseStartDate(), course);
if (startDatesListTemplate) {
$p(startDatesListTemplate.getSelector(), course.getElement()).render(course._sessionsObjects, startDatesListTemplate.getDirective());
// the start dates list
if (course.startDatesList)
course.startDatesList.removeEvents('change');
course.startDatesList = this.createList(course.getElement().getElement(startDatesListTemplate.getSelector()));
course.startDatesList.setValidOptions(course.getValidCourseSessions());
if (course.getSession()) {
course.startDatesList.setValue(course.getCourseDetails().sessions.indexOf(course.getSession()));
}
course.startDatesList.addEvent('change', function(e) {
var sessionIndex = parseInt(course.startDatesList.getValue());
course.setSessionIndex(sessionIndex);
}.bind(this));
}
var courseEndDateTemplate = this.getSchoolCourseEndDateTemplate(course);
if (courseEndDateTemplate) {
var endDate = course.getCourseEndDate() ? course.getCourseEndDate().format(course._dateFormat, course._monthsTranslations) : '';
$p(courseEndDateTemplate.getSelector(), course.getElement()).render({date : endDate}, courseEndDateTemplate.getDirective());
}
var courseDurationTemplate = this.getSchoolCourseDurationValueTemplate(course);
if (courseDurationTemplate) {
var duration = course.getCourseDuration() ? course.getCourseDuration() : '';
if(duration == '1'){
duration =  this.booking.getTranslations().courses.courseObject.week.replace("%0", duration)
} else {
duration =  this.booking.getTranslations().courses.courseObject.weeks.replace("%0", duration)
}
$p(courseDurationTemplate.getSelector(), course.getElement()).render({duration : duration}, courseDurationTemplate.getDirective());
}
break;
}
course.getElement().getElements('select.item-selector').chosen();
}
}.bind(this));
}.bind(this));
//
// refresh the rendering of the courses
//
school.getCoursesManager().addEvent('coursesUpdated', function(e) {
$$('.course-container').addClass('hidden');
$$('.optional-course-container').addClass('hidden');
school.getCoursesManager()._courses.each(function(course, index) {
course.setElement(school.elementContainer.getElement('.item-option-course[value=' + course.getCourseDetails().id + '] .course-container'));
course.fireEvent('refresh');
}.bind(this));
school.getCoursesManager()._optionalCourses.each(function(course, index) {
course.setElement(school.elementContainer.getElement('.item-option-optional-course[value=' + course.getCourseDetails().id + '] .optional-course-container'));
course.fireEvent('refresh');
}.bind(this));
this.updateCoursesList(school);
this.updateAccommodationsList(school);
this.updateInsurancesList();
}.bind(this));
//
// when an accommodation is added, it adds some listener to
//
school.getAccommodationsManager().addEvent('accommodationAdded', function(accommodation) {
// the accommodation events
accommodation.addEvent('refresh', function(e) {
if (accommodation.getElement()) {
accommodation.getElement().getParent().getElement('input').checked = 'checked';
accommodation.getElement().removeClass('hidden');
accommodation.refreshValidStartDates();
// start date template
var startDatesTemplate = this.getSchoolAccommodationsDateValueTemplate('startDate', accommodation);
if (startDatesTemplate) {
$p(startDatesTemplate.getSelector(), accommodation.getElement()).render({'date' : accommodation.getAccommodationStartDate() ? accommodation._calculatedStartDate.format(accommodation._dateFormat, accommodation._monthsTranslations) : this.booking._translateDTO.accommodations.accommodationObject.dateSelect}, startDatesTemplate.getDirective());
var element = accommodation.getElement().getElement(startDatesTemplate.getSelector());
element.addEvent('click', function() {
this.bookingCalendar.setValidDates(accommodation.getValidStartDates(), accommodation.getAvailableDaysBefore(), 0, accommodation._accommodationOptionDetails.additionalNightsOnBounds);
if (accommodation._accommodationStartDate) {
this.bookingCalendar.setSelectedDate(accommodation._accommodationStartDate, accommodation._additionalNightsBefore, 0);
}
else {
if (accommodation.getValidStartDates().length)
this.bookingCalendar.displayMonths(accommodation.getValidStartDates()[0].getMonth(), accommodation.getValidStartDates()[0].getFullYear());
}
this.bookingCalendar.show(element, function(date) {
accommodation.setStartDate(date.relativeDate, date.additionalNightsBefore);
}, this);
}.bind(this));
}
// end date template
var endDatesTemplate = this.getSchoolAccommodationsDateValueTemplate('endDate', accommodation);
if (endDatesTemplate) {
$p(endDatesTemplate.getSelector(), accommodation.getElement()).render({'date' : accommodation._accommodationEndDate ? accommodation._calculatedEndDate.format(accommodation._dateFormat, accommodation._monthsTranslations) : 'select an end date'}, endDatesTemplate.getDirective());
var endDateElement = accommodation.getElement().getElement(endDatesTemplate.getSelector());
endDateElement.addEvent('click', function() {
this.bookingCalendar.setValidDates(accommodation.getValidEndDates(), 0, accommodation.getAvailableDaysAfter(), accommodation._accommodationOptionDetails.additionalNightsOnBounds);
if (accommodation._accommodationEndDate) {
this.bookingCalendar.setSelectedDate(accommodation._accommodationEndDate, 0, accommodation._additionalNightsAfter);
}
else {
if (accommodation.getValidEndDates().length)
this.bookingCalendar.displayMonths(accommodation.getValidStartDates()[0].getMonth(), accommodation.getValidStartDates()[0].getFullYear());
}
this.bookingCalendar.show(endDateElement, function(date) {
accommodation.setEndDate(date.relativeDate, date.additionalNightsAfter);
}, this);
}.bind(this));
}
// to ensure the value is a string
var validDurations = new Array();
accommodation.getValidDurations().each(function(item, index) {
validDurations.push(item + '');
}.bind(this));
// the accommodation duration list template and functionality
var durationsListTemplate = this.getSchoolAccommodationDurationsListTemplate(accommodation._accommodationDuration, validDurations);
if (durationsListTemplate) {
var durations = new Array();
var durations = new Array();
accommodation.getDurations().each(function(item, index) {
if (parseInt(item) == 1) {
var name = this.booking.getTranslations().accommodations.accommodationObject.week.replace("%0", item)
} else {
var name = this.booking.getTranslations().accommodations.accommodationObject.weeks.replace("%0", item)
}
durations.push({id : item, name : name});
}.bind(this));
if(validDurations.length > 1){
$p(durationsListTemplate.getSelector(), accommodation.getElement()).render(durations, durationsListTemplate.getDirective());
// the durations list
if (accommodation.durationsList) {
accommodation.durationsList.removeEvents('change');
accommodation.durationsList.updateListOptions(accommodation.getElement().getElement(durationsListTemplate.getSelector()));
} else {
accommodation.durationsList = this.createList(accommodation.getElement().getElement(durationsListTemplate.getSelector()));
}
accommodation.durationsList.setValidOptions(validDurations);
accommodation.durationsList.setValue(accommodation._accommodationDuration);
accommodation.durationsList.addEvent('change', function(e) {
accommodation.setDuration(accommodation.durationsList.getValue());
}.bind(this));
} else {
var dur = accommodation.getAccommodationDuration();
if (parseInt(dur) == 1) {
dur = this.booking.getTranslations().accommodations.accommodationObject.week.replace("%0", dur)
} else {
dur = this.booking.getTranslations().accommodations.accommodationObject.weeks.replace("%0", dur)
}
$p(durationsListTemplate.getSelector(), accommodation.getElement()).render({'duration' : dur}, durationsListTemplate.getDirective());
}
}
accommodation.getElement().getElements('select.item-selector').chosen();
}
}.bind(this));
accommodation.fireEvent('refresh');
}.bind(this));
// refresh the rendering of the accommodations
school.getAccommodationsManager().addEvent('accommodationsUpdated', function(e) {
$$('.accommodation-container').addClass('hidden');
var addedAccommodations = new Array();
school.getAccommodationsManager().getAccommodations().each(function(accommodation, index) {
addedAccommodations.push(parseInt(accommodation.getAccommodationOptionDetails().id));
accommodation.setElement(school.elementContainer.getElement('.item-option-accommodation[value=' + accommodation.getAccommodationOptionDetails().id + '] .accommodation-container'));
accommodation.fireEvent('refresh');
}.bind(this));
// check the accommodations list
$$('.item-option-accommodation input').each(function(item, index) {
if (!addedAccommodations.contains(parseInt(item.value)))
item.checked = null;
}.bind(this));
if (!addedAccommodations.length) {
$('noAccommodationOption').checked = 'checked';
}
this.updateTransfersList(school);
this.updateInsurancesList();
}.bind(this));
//
// when an transfer is added, it adds some listener to
//
school.getTransfersManager().addEvent('transferAdded', function(transfer) {
// the transfer events
transfer.addEvent('refresh', function(e) {
if (transfer.getElement()) {
transfer.getElement().getParent().getElement('input').checked = 'checked';
transfer.getElement().removeClass('hidden');
var options = transfer.getOptions();
options.each(function(item, index) {
switch (item.name) {
case 'oneWay':
item.name = this.booking.getTranslations().transfers.transferObject.oneWay;
break;
case 'wayBack':
item.name = this.booking.getTranslations().transfers.transferObject.wayBack;
break;
case 'roundTrip':
item.name = this.booking.getTranslations().transfers.transferObject.roundTrip;
break;
}
}.bind(this));
// the transfer type template
var optionsListTemplate = this.getSchoolTransferOptionsListTemplate(options, transfer);
if (optionsListTemplate) {
$p(optionsListTemplate.getSelector(), transfer.getElement()).render(options, optionsListTemplate.getDirective());
// the options list
if (transfer.optionsList) {
transfer.optionsList.removeEvents('change');
transfer.optionsList.updateListOptions(transfer.getElement().getElement(optionsListTemplate.getSelector()));
} else {
transfer.optionsList = this.createList(transfer.getElement().getElement(optionsListTemplate.getSelector()));
}
transfer.optionsList.setValue(transfer.getTransferType());
transfer.optionsList.addEvent('change', function(e) {
transfer.setTransferType(transfer.optionsList.getValue());
}.bind(this));
}
transfer.getElement().getElements('select.item-selector').chosen();
}
}.bind(this));
transfer.fireEvent('refresh');
}.bind(this));
// refresh the rendering of the transfers
school.getTransfersManager().addEvent('transfersUpdated', function(e) {
$$('.transfer-container').addClass('hidden');
var addedTransfers = new Array();
school.getTransfersManager().getTransfers().each(function(transfer, index) {
addedTransfers.push(transfer.getTransferId());
transfer.setElement(school.elementContainer.getElement('.item-option-transfer[value=' + transfer.getTransferId() + '] .transfer-container'));
transfer.fireEvent('refresh');
}.bind(this));
// check the transfers list
$$('.item-option-transfer input').each(function(item, index) {
if (!addedTransfers.contains(parseInt(item.value)))
item.checked = null;
}.bind(this));
if (!addedTransfers.length) {
$('noTransferOption').checked = 'checked';
}
}.bind(this));
school.getCoursesManager().fireEvent('coursesUpdated');
school.getAccommodationsManager().fireEvent('AccommodationsUpdated');
$$('.Component-ItemAdded').addClass('hidden');
}.bind(this));
this.fireEvent('schoolsCreated');
}.bind(this));
},
/**
* Update the optional courses list
*
* @param SchoolObject school The school
*/
updateCoursesList : function(school) {
if (!school) {
this.booking.getSchools().each(function(school, index) {
this.updateCoursesList(school);
}.bind(this));
} else {
var courses = school.getCoursesManager().getCourses();
//            school.elementContainer.getElements('.school-courses-list .item-category').addClass('invalid');
school.elementContainer.getElements('.school-courses-list .item-option-radio').each(function(item, index) {
//                item.removeAttribute('disabled');
//                item.getParent('.item-option').removeClass('invalid');
}.bind(this));
var validOptionalCourses = school.getCoursesManager().getValidOptionalCourses();
school.elementContainer.getElements('.school-optional-courses-list .item-option-radio').each(function(item, index) {
if (validOptionalCourses.contains(parseInt(item.getAttribute('value')))) {
item.removeAttribute('disabled');
item.getParent('.item-option').removeClass('invalid');
} else {
item.setAttribute('disabled', 'disabled');
item.getParent('.item-option').addClass('invalid');
}
}.bind(this));
}
},
/**
* Update the accommodations list
*
* @param SchoolObject school The school
*/
updateAccommodationsList : function(school) {
var validAccommodations = school.getAccommodationsManager().getValidAccommodationsList();
var getParentWithClass = function(element, className) {
var parent = element.parentNode;
while (parent && parent != school.elementContainer) {
if ($(parent).hasClass(className)) {
return $(parent);
}
parent = parent.parentNode;
}
return null;
};
school.elementContainer.getElements('.school-accommodations-list .item-category').addClass('invalid');
school.elementContainer.getElements('.school-accommodations-list .item-option-radio').each(function(item, index) {
var itemOption = getParentWithClass(item, 'item-option');
var itemCategory = getParentWithClass(item, 'item-category');
if ((!school.getMandatoryAccommodations().length && item.getAttribute('id') == 'noAccommodationOption') || validAccommodations.contains(parseInt(item.getAttribute('value')))) {
item.removeAttribute('disabled');
if (itemOption) itemOption.removeClass('invalid');
if (itemCategory) itemCategory.removeClass('invalid');
} else {
item.setAttribute('disabled', 'disabled');
if (itemOption) itemOption.addClass('invalid');
}
}.bind(this));
},
/**
* Update the transfers list
*
* @param SchoolObject school The school
*/
updateTransfersList : function(school) {
var validTransfers = school.getTransfersManager().getValidTransfersList();
school.elementContainer.getElements('.school-transfers-list .item-option-radio').each(function(item, index) {
if (item.getAttribute('id') == 'noTransferOption' || validTransfers.contains(parseInt(item.getAttribute('value')))) {
item.removeAttribute('disabled');
item.getParent('.item-option').removeClass('invalid');
} else {
item.setAttribute('disabled', 'disabled');
item.getParent('.item-option').addClass('invalid');
}
}.bind(this));
},
/**
* Update the insurances list
*/
updateInsurancesList : function() {
var validInsurances = this.booking.getInsurancesManager().getValidInsurancesList();
var validInsurancesIds = new Array();
validInsurances.each(function(item, index) {
validInsurancesIds.push(item.id);
}.bind(this));
this.booking.getInsurancesManager().getCompletedInsurances().each(function(item, index) {
if (!item.getMandatory())
validInsurancesIds.push(parseInt(item.getInsuranceId()));
}.bind(this));
$$('.insurances-list')[0].getElements('.item-option-radio').each(function(item, index) {
if (validInsurancesIds.contains(parseInt(item.getAttribute('value')))) {
item.removeAttribute('disabled');
item.getParent('.item-option').removeClass('invalid');
} else {
item.setAttribute('disabled', 'disabled');
item.getParent('.item-option').addClass('invalid');
}
}.bind(this));
},
/**
* Create the directives for this template
*
*/
createDirectives : function() {
this._directives = new Hash();
// The templates directives
// More informations on : http://beebole.com/pure/
var schoolsListDirectiveProgram = {
'.item-option' : {
"program<-programs" : {
'.' : "program.name",
'.@value' : "program.id"
}
}
};
var schoolsListDirectiveObject = {
".item-option": {
'listItem <-': {
'.': "listItem.name",
'.@value' : "listItem.id"}
}};
var schoolCoursesListDirectiveObject = {
".item-category": {
'category <-': {
'.item-category-name': "category.name",
".item-option-course": {
'listItem <- category.courses': {
'.item-option-radio@id': "listItem.id",
'.item-option-radio@value': "listItem.id",
'.item-option-name@for': "listItem.id",
'.item-option-name': "listItem.name",
'.item-course-info@title': "listItem.subtitle",
'.item-course-info@data-course-info': "listItem.subtitle",
'.item-course-info@aria-label': "listItem.subtitle",
'.item-option-price': "listItem.price",
'.@value' : "listItem.id"}
}
}
}};
var schoolCoursesListDirectiveObject = {
".item-option-course": {
'listItem <- ': {
'.item-option-radio@id': "listItem.id",
'.item-option-radio@value': "listItem.id",
'.item-option-name@for': "listItem.id",
'.item-option-name': "listItem.name",
'.item-course-info@title': "listItem.subtitle",
'.item-course-info@data-course-info': "listItem.subtitle",
'.item-course-info@aria-label': "listItem.subtitle",
'.item-option-price': "listItem.displayPrice",
'.@value' : "listItem.id"
}
}
};
var schoolOptionalCoursesListDirectiveObject = {
".item-option-course": {
'listItem <- ': {
'.item-option-radio@id': "listItem.id",
'.item-option-radio@value': "listItem.id",
'.item-option-name@for': "listItem.id",
'.item-option-name': "listItem.name",
'.item-course-info@title': "listItem.subtitle",
'.item-course-info@data-course-info': "listItem.subtitle",
'.item-course-info@aria-label': "listItem.subtitle",
'.item-option-price': "listItem.displayPrice",
'.@value' : "listItem.id"}
}
};
var schoolAccommodationsListDirectiveObject = {
".item-category": {
'category <-': {
'.item-category-name': "category.name",
".item-option-accommodation" : {
'listItem <- category.option': {
'.item-option-radio@id': "listItem.id",
'.item-option-radio@value': "listItem.id",
'.item-option-name@for': "listItem.id",
'.item-option-name': "listItem.name",
'.item-option-price': "listItem.displayPrice",
'.@value' : "listItem.id"
}
}
}
}};
var schoolTransfersListDirectiveObject = {
".item-option-transfer": {
'listItem <-': {
'.item-option-radio@id': "listItem.id",
'.item-option-radio@value': "listItem.id",
'.item-option-name@for': "listItem.id",
'.item-option-name': "listItem.name",
'.@value' : "listItem.id"}
}
};
var insurancesListDirectiveObject = {
".item-option-insurance": {
'listItem <-': {
'.item-option-radio@id': "listItem.id",
'.item-option-radio@value': "listItem.id",
'.item-option-name@for': "listItem.id",
'.item-option-name': "listItem.name",
'.@value' : "listItem.id"}
}};
var currenciesListDirectiveObject = {
".item-option": {
'listItem <-': {
'.': "listItem.currencyName",
'.@value' : "listItem.currencyCode"
}
}
};
var currencyDirectiveObject = {
".currencyItem": {
'listItem <-': {
'.': "listItem.currencyName"
}
}
};
var schoolAccommodationDateDirectiveObject = {
".accommodation-date-value": "date"
};
var accommodationValueDirectiveObject = {
".accommodation-duration-value": "duration"
};
var schoolCourseDateDirectiveObject = {
".course-date-value": "date"
};
this._directives.set('programsListDirective', $p(".program-selector").compile(schoolsListDirectiveProgram));
this._directives.set('countriesListDirective', $p(".country-selector-template1").compile(schoolsListDirectiveObject));
this._directives.set('citiesListDirective', $p(".city-selector").compile(schoolsListDirectiveObject));
this._directives.set('schoolsListDirective', $p(".school-selector").compile(schoolsListDirectiveObject));
var schoolsDirective = {
".school-container" :{
"school <-" : {
'.school-title' :  "school.schoolName",
'.school-description-city' :  "school.schoolCityName",
'.school-description-country' :  "school.schoolCountryCode"
}
}
};
this._directives.set('schoolsDirective', $p(".schools-container").compile(schoolsDirective));
this._directives.set('schoolCoursesListDirective', $p(".school-courses-list").compile(schoolCoursesListDirectiveObject));
this._directives.set('schoolOptionalCoursesListDirective', $p(".school-optional-courses-list").compile(schoolOptionalCoursesListDirectiveObject));
this._directives.set('schoolAccommodationsListDirective', $p(".school-accommodations-list").compile(schoolAccommodationsListDirectiveObject));
this._directives.set('schoolAccommodationsStartDateDirective', $p(".accommodation-startdate").compile(schoolAccommodationDateDirectiveObject));
this._directives.set('schoolAccommodationsEndDateDirective', $p(".accommodation-enddate").compile(schoolAccommodationDateDirectiveObject));
this._directives.set('schoolAccommodationsDurationDirective', $p(".accommodation-duration-template1").compile(schoolsListDirectiveObject));
this._directives.set('schoolAccommodationsDurationDirective2', $p(".accommodation-duration-template2").compile(accommodationValueDirectiveObject));
this._directives.set('schoolTransfersListDirective', $p(".school-transfers-list").compile(schoolTransfersListDirectiveObject));
this._directives.set('insurancesListDirective', $p(".insurances-list").compile(insurancesListDirectiveObject));
this._directives.set('currenciesListDirective', $p(".currencies-list-a").compile(currenciesListDirectiveObject));
this._directives.set('currencyDirective', $p(".currencies-list-b").compile(currencyDirectiveObject));
var coursesDirective = {};
var optionalCoursesDirective = {};
var courseEndDateDirective = {
'.course-enddate-value' : "date"
};
var courseDurationDirective = {
'.course-duration-value' : "duration"
};
var accommodationsDirective = {};
var transfersDirective = {
".transfer-container" :{
"transfer <-" : {
'.transfer-title' :  "transfer._transferName"
}
}
};
transfersDirective = {};
var transferFixedOptionDirectiveObject = {
".transfer-value" :{
"listItem <-" : {
'.' :  "listItem.name"
}
}
};
this._directives.set('schoolCoursesDirective', $p(".item-option-course").compile(coursesDirective));
this._directives.set('schoolOptionalCoursesDirective', $p(".item-option-optional-course").compile(optionalCoursesDirective));
this._directives.set('fixedCourseStartDatesListDirective', $p(".course-startdates-list").compile(schoolsListDirectiveObject));
this._directives.set('courseStartDatesListDirective', $p(".course-startdate").compile(schoolCourseDateDirectiveObject));
this._directives.set('courseDurationsListDirective', $p(".course-durations-list").compile(schoolsListDirectiveObject));
this._directives.set('courseDurationValueDirective', $p(".course-duration-item").compile(courseDurationDirective));
this._directives.set('schoolCourseEndDateDirective', $p(".course-enddate").compile(courseEndDateDirective));
this._directives.set('schoolAccommodationsDirective', $p(".accommodation-container").compile(accommodationsDirective));
this._directives.set('schoolTransfersDirective', $p(".transfer-container").compile(transfersDirective));
this._directives.set('schoolTransferOptionDirective', $p(".transfer-type-list-a").compile(schoolsListDirectiveObject));
this._directives.set('schoolTransferFixedOptionDirective', $p(".transfer-type-value-b").compile(transferFixedOptionDirectiveObject));
},
getSchoolsTemplate : function  (data) {
return new BookingTemplateObject({selector : '.schools-container',
directive : this._directives.get('schoolsDirective'),
element : $p('.schools-container')});
},
getSchoolCoursesListTemplate : function  (data) {
return new BookingTemplateObject({selector : '.school-courses-list',
directive : this._directives.get('schoolCoursesListDirective'),
element : $p('.school-courses-list')});
},
getSchoolOptionalCoursesListTemplate : function  (data) {
return new BookingTemplateObject({selector : '.school-optional-courses-list',
directive : this._directives.get('schoolOptionalCoursesListDirective'),
element : $p('.school-optional-courses-list')});
},
getSchoolCoursesTemplate : function  (data) {
return new BookingTemplateObject({
selector : '.courses-container',
directive : this._directives.get('schoolCoursesDirective'),
element : $p('.courses-container')});
},
getSchoolAccommodationsTemplate : function  (data) {
return new BookingTemplateObject({
selector : '.accommodations-container',
directive : this._directives.get('schoolAccommodationsDirective'),
element : $p('.accommodations-container')});
},
getSchoolOptionalCoursesTemplate : function  (data) {
return new BookingTemplateObject({selector : '.optional-courses-container',
directive : this._directives.get('schoolOptionalCoursesDirective'),
element : $p('.optional-courses-container')});
},
getSchoolCourseStartDatesListTemplate : function  (startDate, course) {
if (course.getCourseType() == 'fixed') {
return new BookingTemplateObject({selector : '.course-startdate-selector-container',
directive : this._directives.get('fixedCourseStartDatesListDirective'),
element : $p('.course-startdate-selector-container')});
}
return new BookingTemplateObject({selector : '.course-startdate-selector-container',
directive : this._directives.get('courseStartDatesListDirective'),
element : $p('.course-startdate-selector-container')});
},
getSchoolCourseDurationsListTemplate : function  (duration, data) {
return new BookingTemplateObject({selector : '.course-duration',
directive : this._directives.get('courseDurationsListDirective'),
element : $p('.course-duration')});
},
getSchoolCourseDurationValueTemplate : function  (duration, data) {
return new BookingTemplateObject({selector : '.course-duration',
directive : this._directives.get('courseDurationValueDirective'),
element : $p('.course-duration')});
},
getSchoolCourseEndDateTemplate : function  (endDate, data) {
return new BookingTemplateObject({selector : '.course-enddate',
directive : this._directives.get('schoolCourseEndDateDirective'),
element : $p('.course-enddate')});
},
getSchoolAccommodationsListTemplate : function  (data) {
return new BookingTemplateObject({selector : '.school-accommodations-list',
directive : this._directives.get('schoolAccommodationsListDirective'),
element : $p('.school-accommodations-list')});
},
getSchoolAccommodationsDateValueTemplate : function  (type, data) {
switch (type) {
case 'startDate' :
return new BookingTemplateObject({selector : '.accommodation-startdate',
directive : this._directives.get('schoolAccommodationsStartDateDirective'),
element : $p('.accommodation-startdate')});
break;
case 'endDate' :
return new BookingTemplateObject({selector : '.accommodation-enddate',
directive : this._directives.get('schoolAccommodationsEndDateDirective'),
element : $p('.accommodation-enddate')});
break;
}
},
getSchoolAccommodationDurationsListTemplate : function  (duration, validDurations) {
return new BookingTemplateObject({selector : '.accommodation-duration',
directive :validDurations.length > 1 ? this._directives.get('schoolAccommodationsDurationDirective') : this._directives.get('schoolAccommodationsDurationDirective2'),
element : $p('.accommodation-duration')});
},
getSchoolTransfersListTemplate : function  (data) {
return new BookingTemplateObject({selector : '.school-transfers-list',
directive : this._directives.get('schoolTransfersListDirective'),
element : $p('.school-transfers-list')});
},
getSchoolTransfersTemplate : function  (data) {
return new BookingTemplateObject({
selector : '.transfers-container',
directive : this._directives.get('schoolTransfersDirective'),
element : $p('.transfers-container')});
},
getSchoolTransferOptionsListTemplate : function  (options, transfer) {
return new BookingTemplateObject({selector : '.transfer-type-list',
directive : options.length > 1 ?  this._directives.get('schoolTransferOptionDirective') : this._directives.get('schoolTransferFixedOptionDirective') ,
element : $p('.transfer-type-list')});
},
getInsurancesListTemplate : function  (data) {
return  new BookingTemplateObject({selector : '.insurances-list',
directive : this._directives.get('insurancesListDirective'),
element : $p('.insurances-list')});
},
getCurrenciesListTemplate : function  (data, currencies) {
return  new BookingTemplateObject({selector : '.currencies-list',
directive : currencies.length > 1 ? this._directives.get('currenciesListDirective') : this._directives.get('currencyDirective'),
element : $p('.currencies-list')});
},
setActive : function(element, active){
if(active){
element.removeClass('inActive');
}else {
element.addClass('inActive');
}
},
updateEmptyState : function(){
var emptyState = $('bookingEmptyState');
if (!emptyState || !this.booking || this.booking.getIsShoppingCartPage()) {
return;
}
var loadedSchools = this.booking.getSchools ? this.booking.getSchools() : null;
var hasLoadedSchool = loadedSchools && loadedSchools.length;
var selectedSchoolId = null;
if (this.booking.getSchoolsSelector && this.booking.getSchoolsSelector()) {
selectedSchoolId = this.booking.getSchoolsSelector().getSelectedSchoolId();
}
if (hasLoadedSchool || selectedSchoolId) {
emptyState.addClass('hidden');
} else {
emptyState.removeClass('hidden');
}
},
syncSchoolSelectorChoices : function(){
['.program-selector', '.country-selector', '.city-selector', '.school-selector'].each(function(selector){
this.syncSchoolSelectorChoice(selector);
}.bind(this));
},
ensureSchoolSelectorChoices : function(){
['.program-selector', '.country-selector', '.city-selector', '.school-selector'].each(function(selector){
this.ensureSchoolSelectorChoice(selector);
}.bind(this));
},
ensureSchoolSelectorChoice : function(selector){
var section = $$(selector)[0];
if (!section) {
return;
}
var select = section.getElement('select.item-selector');
if (!select) {
return;
}
this.bindSchoolSelectorChoiceSync(selector, select);
var chosen = this.getChosenContainerForSelect(select, section);
if (chosen && select.hasClass('chzn-done')) {
return;
}
section.getElements('.chzn-container').each(function(container){
container = document.id(container);
if (container && container.dispose) {
container.dispose();
} else if (container && container.parentNode) {
container.parentNode.removeChild(container);
}
});
select.removeClass('chzn-done');
try {
new Elements([select]).chosen();
} catch(ex) {
}
},
bindSchoolSelectorChoiceSync : function(selector, select){
if (!select) {
return;
}
var previousHandler = select.retrieve ? select.retrieve('masBookingChoiceSyncHandler') : null;
if (previousHandler) {
select.removeEvent('change', previousHandler);
}
var handler = function(){
this.syncSchoolSelectorChoice(selector);
}.bind(this);
if (select.store) {
select.store('masBookingChoiceSyncHandler', handler);
}
select.addEvent('change', handler);
},
syncSchoolSelectorChoice : function(selector){
var section = $$(selector)[0];
if (!section) {
return;
}
var select = section.getElement('select.item-selector');
if (!select) {
return;
}
var selectedOption = select.options && select.selectedIndex >= 0 ? select.options[select.selectedIndex] : null;
var selectedValue = selectedOption ? selectedOption.get('value') : select.get('value');
var selectedText = '';
if (selectedOption) {
selectedText = selectedOption.text || selectedOption.textContent || selectedOption.innerHTML || '';
}
var placeholder = select.get('data-placeholder') || '';
if (!selectedValue) {
select.set('value', '');
if (select.options && select.options.length) {
for (var i = 0; i < select.options.length; i++) {
select.options[i].selected = false;
}
select.options[0].selected = true;
select.selectedIndex = 0;
}
selectedText = placeholder;
}
var signatureParts = [];
if (select.options) {
for (var j = 0; j < select.options.length; j++) {
var option = select.options[j];
signatureParts.push([option.value, option.text || option.textContent || option.innerHTML || '', option.selected ? 1 : 0, option.disabled ? 1 : 0].join('|'));
}
}
var signature = signatureParts.join('||');
var previousSignature = select.retrieve ? select.retrieve('masBookingChosenSignature') : select.getAttribute('data-mas-booking-chosen-signature');
if (signature != previousSignature) {
select.fireEvent('liszt:updated');
if (select.store) {
select.store('masBookingChosenSignature', signature);
} else {
select.setAttribute('data-mas-booking-chosen-signature', signature);
}
}
var chosen = this.getChosenContainerForSelect(select, section);
if (chosen) {
var label = chosen.getElement('.chzn-single span');
if (label) {
label.set('text', selectedText || placeholder);
}
}
},
getChosenContainerForSelect : function(select, section){
if (select && select.id) {
var container = $(select.id.replace(/(:|\.)/g, '_') + '_chzn');
if (container) {
return container;
}
}
return section ? section.getElement('.chzn-container') : null;
},
/**
* Display the waiting panel
*
* @param Element panel
*/
displayWaitingPanel : function(panel) {
if(panel)
panel.removeClass('waiting-panel-hidden');
},
/**
* Hide the waiting panel
*
* @param panel
*/
hideWaitingPanel : function(panel) {
if(panel)
panel.addClass('waiting-panel-hidden');
}
});
function printPriceEstimation() {
window.print();
/**
if ($("bookingOption") && $("bookingOption").retrieve('booking')) {
$("bookingOption").retrieve('booking').print();
}    **/
return false;
}
function addToMyQuotes() {
if ($("bookingOption") && $("bookingOption").retrieve('booking')) {
$("bookingOption").retrieve('booking').addToMyQuotes();
}
return false;
}
function addToCart() {
if ($("bookingOption") && $("bookingOption").retrieve('booking')) {
$("bookingOption").retrieve('booking').addToCart();
}
return false;
}
function mailQuote() {
if ($("bookingOption") && $("bookingOption").retrieve('booking')) {
$("bookingOption").retrieve('booking').mailQuote();
}
return false;
}
function checkout() {
if (bookingManager.booking) {
bookingManager.booking.checkout();
}
return false;
}
