var avaibility_daily = null; /** Formate une date, soit au format europeen jj/mm/aaaa, soit au format sql aaaa-mm-jj Format a date the the european format dd/mm/yyyy or sql format yyyy-mm-dd */ function formatFixedDate(dateObject, format) { if(!dateObject) return ""; var nDay = dateObject.getDate(); var sDay; if( nDay < 10 ) sDay = "0"+nDay; else sDay = nDay; var nMonth = dateObject.getMonth()+1; var sMonth; if( nMonth < 10 ) sMonth = "0"+nMonth; else sMonth = nMonth; if(format != null && format == "fr") return ""+sDay+'/'+sMonth+'/'+dateObject.getFullYear(); else return ""+dateObject.getFullYear()+"-"+sMonth+"-"+sDay; } /** Cree l'id d'une cellule du calendrier a partir de la date Create a calendar cell id from the date */ function getDateKey( theDate ) { return 'D'+formatFixedDate(theDate, 'iso'); } /** Construit la grille d'affichage vide Build the empty calendar grid */ function getGrid(dFromDate, dToDate) { var aMonthLabel = new Array('janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'); var sRet = "\n\t\n"; sRet += "\t\n"; var currentFirstDayNbr = dFromDate.getDay() == 0 ? 7 : dFromDate.getDay(); var previousDate = new Date(dFromDate.getFullYear(), dFromDate.getMonth(), (dFromDate.getDate()-1), '0', '0', '0', '0'); var previousMonthDateCell = ''; for(i=(currentFirstDayNbr-1);i>0;i--) { var thisDate = new Date(dFromDate.getFullYear(), dFromDate.getMonth(), dFromDate.getDate() - i, '0', '0', '0', '0'); previousMonthDateCell += "\t\t\n"; previousDate = new Date(thisDate); } for(currentDate=new Date(dFromDate);currentDate<=dToDate;currentDate.setDate(currentDate.getDate()+1)) { var currentDayNbr = currentDate.getDay(); var previousDayNbr = previousDate.getDay(); if(currentDate.getDate() < previousDate.getDate()) { sRet += "\t\n"; sRet += "\t\n\t\t\n\t\n"; sRet += "\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\n" sRet += "\t\n"; if(previousDayNbr != 0) sRet += previousMonthDateCell; } if(currentDayNbr== 1) sRet += "\t\n"; sRet += "\t\t\n"; if(currentDayNbr== 0) sRet += "\n"; previousDate = new Date(currentDate); } var currentLastDayNbr = dToDate.getDay() == 0 ? 7 : dToDate.getDay(); for(i=1;i<=(7-currentLastDayNbr);i++) { var thisDate = new Date(dToDate.getFullYear(), dToDate.getMonth(), dToDate.getDate() + i, '0', '0', '0', '0'); sRet += "\t\t\n"; } sRet += "\t\n"; sRet += "
"+thisDate.getDate()+" 
"+aMonthLabel[ currentDate.getMonth() ]+"
LunMarMerJeuVenSamDim
"+currentDate.getDate()+" 
"+thisDate.getDate()+" 
\n"; return sRet; } /** Recupere toutes les disponibilites du mois passe en parametre pour le produit de base choisi. Au passage met a jour les selecteurs du formulaire (les donnees proviennent de Resalys). /!\ ATTENTION la grille est construite a partir des types de periode AUTO qui doivent etre accessibles. Modifier ce script si d'autre type de periode doivent etre utilisees Get all the availability from the given month and base product. Also update the form select fields. /!\ WARNING this grid is build from the period type AUTO. These period type should be accessible in the setting. Update the script if you use other period type. */ function getAvaibilities(monthCode, productCode, preferedRoomTypeAndCapacity, etabId) { $('#gridContner').css( 'cursor', 'progress' ); // On recupere les disponibilites // Get the availability var avaibilityUrl="/rsl/clickbooking?template=search_avaibility_daily.json.rsl&tokens=ignore_token&display=default&actions=updateAvaibilityFormPerPaxCriterias%3BgetProposalsPerPax&search_form_semainier_mode=3&search_form_day_constraints=1&search_form_period_type=AUTO&search_form_max_rooms=1&search_form_nb_adults=1&etab_id="+etabId+"&search_form_lookup_month="+monthCode+"&search_form_product_code="+productCode; $.getJSON( avaibilityUrl, function( data ) { try { // On met a jour les selecteurs // Update the select field $('#search_form_lookup_month').empty(); $.each(data.monthSelectOptions, function(i, val){$('#search_form_lookup_month').append('')}); $('#search_form_lookup_month').val(data.monthSelected); $('#search_form_product_code').empty(); $.each(data.formuleSelectOptions, function(i, val){$('#search_form_product_code').append('')}); $('#search_form_product_code').val(data.formuleSelected); $('#preferedRoomTypeAndCapacity').empty(); $.each(data.roomTypeSelectOptions, function(i, val){$('#preferedRoomTypeAndCapacity').append('')}); preferedRoomTypeAndCapacity = preferedRoomTypeAndCapacity != '' ? preferedRoomTypeAndCapacity : data.roomTypeSelectFirstValue; $('#preferedRoomTypeAndCapacity').val(preferedRoomTypeAndCapacity); avaibility_daily = data.avaibility; // et maintenant on les copie dans le tableau en tenant compte du choix de type d'hebergement // and now, update the grid according to the room type selected var aCurrentMonth = monthCode.split('_'); var dFromDate = new Date(aCurrentMonth[ 1 ], (aCurrentMonth[ 0 ]-1), '01', '0', '0', '0', '0'); var dToDate = new Date(dFromDate.getFullYear(), dFromDate.getMonth()+1, '0', '0', '0', '0', '0'); var aRoomTypeAndCapacitySelected = preferedRoomTypeAndCapacity.split('_'); updateGrid( aRoomTypeAndCapacitySelected[ 0 ], aRoomTypeAndCapacitySelected[ 1 ], dFromDate, dToDate ); } catch(ex) { var fctClose = function(){ } dialogAlert('box_dialog_error',"Erreur lors de la lecture des disponibilites:"+ex,fctClose); /*$( "#box_dialog_error" ).dialog({ open: function( event, ui ) { $( "#box_dialog_error_text" ).html("Erreur lors de la lecture des disponibilites:"+ex); }, close: function(ev, ui){ } });*/ } $('#gridContner').css( 'cursor', 'auto' ); }); } /** Verifie si une cellule de la grille est disponible par rapport au contraintes (fermeture, arrive ou depart) Check if a grid cell is available according to the constrains (close, arrival, departure) */ function isAvailableAccordingToLineitemDiscount( aLineitemDiscounts, checkFor ) { bIsAvailable = true; for( d=0; d < aLineitemDiscounts.length; d++ ) { var bIsClosed = (aLineitemDiscounts[d].isClosed != null && aLineitemDiscounts[d].isClosed == 1 ); var bIsClosedOnArrival = (aLineitemDiscounts[d].isClosedOnArrival != null && aLineitemDiscounts[d].isClosedOnArrival == 1); var bIsClosedOnDeparture = (aLineitemDiscounts[d].isClosedOnDeparture != null && aLineitemDiscounts[d].isClosedOnDeparture == 1); if( checkFor == 'arrival' && (bIsClosed || bIsClosedOnArrival) ) bIsAvailable = false; else if( checkFor == 'departure' && (bIsClosed || bIsClosedOnDeparture) ) bIsAvailable = false; else if( bIsClosed ) bIsAvailable = false; } return bIsAvailable; } /** A partir des donnees de disponibilite recuperees, met a jour l'affichage de la grille. Update the grid display according to the availability */ function updateGrid( sPreferedRoomType, nPreferedCapacity, dFromDate, dToDate) { var sToday = getDateKey(new Date()); for(currentDate=new Date(dFromDate);currentDate<=dToDate;currentDate.setDate(currentDate.getDate()+1)) { var dateKey = getDateKey(currentDate); var dateNbr = currentDate.getDate(); var isGoodRoomType = true; if( typeof(avaibility_daily[ dateKey ]) != 'undefined' && avaibility_daily[ dateKey ].length > 0 ) { var currentProposal = null; var cellStyle = "available"; // On regarde si l'on a le type demande dispo // Is the room type available for(c=0;c= nPreferedCapacity && parseFloat(avaibility_daily[ dateKey ][ c ][ 'adultsPriceWithoutDiscounts' ]) > 0.0 ) { currentProposal = avaibility_daily[ dateKey ][ c ]; if( currentProposal != null && isAvailableAccordingToLineitemDiscount( currentProposal[ 'lineitemDiscounts' ], '' ) ) { if( isAvailableAccordingToLineitemDiscount( currentProposal[ 'lineitemDiscounts' ], 'arrival' ) ) cellStyle = "availablePartialy"; else cellStyle = "availablePartialy notClickable"; isGoodRoomType = false; } else currentProposal = null; } } if( currentProposal == null ) { // Tjs pas trouve de dispo // not found $('#'+dateKey).removeClass().addClass('notAvailable'); $('#'+dateKey).empty().append(''+dateNbr+'Non disponible!'); } else { var priceStyle = ''; var sDiscountPrice = ''; if(currentProposal[ 'adultsPrice' ] != currentProposal[ 'adultsPriceWithoutDiscounts' ]) { priceStyle = ' promo'; sDiscountPrice = currentProposal[ 'adultsPriceWithoutDiscounts' ]; } var sDiscounts = ''; for(d=0; d'+sDiscountPrice+''+dateNbr+''+currentProposal[ 'adultsPrice' ]+''); } else { cellStyle = (isGoodRoomType ? "available" : "availablePartialy"); $('#'+dateKey).empty().append(''+sDiscountPrice+''+dateNbr+''+currentProposal[ 'adultsPrice' ]+''); } $('#'+dateKey).removeClass().addClass(cellStyle); } } else { if( dateKey < sToday ) { $('#'+dateKey).removeClass().addClass('inThePast'); $('#'+dateKey).empty().append(''+dateNbr+' '); } else { $('#'+dateKey).removeClass().addClass('notAvailable'); $('#'+dateKey).empty().append(''+dateNbr+'Non disponible!'); } } } } /** Lorsque l'on change de mois ou de produit de base, la grille est reconstruite et les disponibilites redemandees au serveur. When we change the displayed month or the base product, the grid is rebuild and the availability asked again to Resalys. */ function changeMonthDisplayed() { var selectedMonth = $('#search_form_lookup_month').val(); var aMonth = selectedMonth.split('_'); var dFromDate = new Date(aMonth[ 1 ], (aMonth[ 0 ]-1), '01', '0', '0', '0', '0'); var dToDate = new Date(dFromDate.getFullYear(), dFromDate.getMonth()+1, '0', '0', '0', '0', '0'); // Dessine le calendrier vide // Draw an empty calendar $('#gridContner').empty().append(getGrid(dFromDate, dToDate)); // On recupere les disponibilites // Get the availability var productCode = $('#search_form_product_code').val(); var preferedRoomTypeAndCapacity = $('#preferedRoomTypeAndCapacity').val(); var etabId = $('#etab_id').val(); getAvaibilities(selectedMonth, productCode, preferedRoomTypeAndCapacity, etabId); } /** Lorsque l'on change de type de chambre preferee, la grille n'est pas rechargee car on a deja toutes les donnees, on met juste a jour l'affichage. When we change the room type, the grid is not reloaded because we already have all the data */ function changeRoomTypeDisplayed() { var aRoomTypeAndCapacitySelected = $('#preferedRoomTypeAndCapacity').val().split('_'); var aMonth = $('#search_form_lookup_month').val().split('_'); var dFromDate = new Date(aMonth[ 1 ], (aMonth[ 0 ]-1), '01', '0', '0', '0', '0'); var dToDate = new Date(dFromDate.getFullYear(), dFromDate.getMonth()+1, '0', '0', '0', '0', '0'); updateGrid( aRoomTypeAndCapacitySelected[ 0 ], aRoomTypeAndCapacitySelected[ 1 ], dFromDate, dToDate); } bDateToSetIsEndDate = false; function setDateFromGrid( dateToSet ) { if( bDateToSetIsEndDate ) { $('#end_date').val(dateToSet); changeRoomTypeDisplayed(); // Pour remmettre l'affichage complet / To reset the display bDateToSetIsEndDate = false; getPrices(); } else { resetDates(); $('#start_date').val(dateToSet); disableDates(dateToSet); // invalide toutes les dates non clikable / invalidate all the non clickable dates bDateToSetIsEndDate = true; } } function resetDates() { $('#start_date').val(''); $('#end_date').val(''); bDateToSetIsEndDate = false; $("#searchResult").empty(); changeRoomTypeDisplayed(); // Pour remmettre l'affichage complet / To reset the display } function disableDates(sDateToSet) { var aRoomTypeAndCapacitySelected = $('#preferedRoomTypeAndCapacity').val().split('_'); var sPreferedRoomType = aRoomTypeAndCapacitySelected[ 0 ]; var aMonth = $('#search_form_lookup_month').val().split('_'); var dFromDate = new Date(aMonth[ 1 ], (aMonth[ 0 ]-1), '01', '0', '0', '0', '0'); var dToDate = new Date(dFromDate.getFullYear(), dFromDate.getMonth()+1, '0', '0', '0', '0', '0'); var aDateToSet = sDateToSet.split('/'); var dDateToSet = new Date(aDateToSet[ 2 ], (aDateToSet[ 1 ]-1), aDateToSet[ 0 ], '0', '0', '0', '0'); // On commence par griser tout ce qui est dans le passe // We start by disable all the dates in the past for(currentDate=new Date(dFromDate);currentDate'+sdiscountPrice+''+dateNbr+''+sAmount+''); } // On selectionne le jour choisi en le rendant non clickable // We select the choosen date and define as not clickable var dateKey = getDateKey(dDateToSet); var dateNbr = currentDate.getDate(); var cssAvaibleClass = $('#'+dateKey).hasClass('availablePartialy') ? 'availablePartialy' : 'available'; $('#'+dateKey).removeClass().addClass(cssAvaibleClass + ' choosedCellFirst'); var sAmount = $('#'+dateKey+' span.aPrice').text(); var sdiscountPrice = $('#'+dateKey+' span.aDiscountPrice').text(); $('#'+dateKey).empty().append(''+sdiscountPrice+''+dateNbr+''+sAmount+''); // Ensuite on grise tout ce qui est dans le futur apres une date impossible et rend disponible la 1ere date non reservable comme depart. Ceci part du principe // qu'il n'y a pas d'autres regles de blocage que les contraintes du tarif journalier. // Then, we disable everything in the future after the first unavailable date, and define as clickable this first unavailable date. The assumption is that there // is no other blocking rule than the ones define in the daily price setting. var dFirstInvalideDate = dToDate;// on cherche la 1ere date non reservable, par defaut le dernier jour du mois / Serach the first unavailable date, by default the last day of the month. for(currentDate=new Date(dDateToSet);currentDate<=dToDate;currentDate.setDate(currentDate.getDate()+1)) { var dateKey = getDateKey(currentDate); if( $('#'+dateKey).hasClass('notAvailable') ) { dFirstInvalideDate = currentDate; break; } } // Ce jour invalide en arrivee est clickable en depart (mais on a pas de prix) / This day is unavailable on arrival, but clickable on departure (but we don't have the price) var dateKey = getDateKey(dFirstInvalideDate); var sFirstInvalideDate = formatFixedDate(dFirstInvalideDate, 'fr'); $('#'+dateKey).removeClass().addClass('available'); $('#'+dateKey).empty().append(''+dFirstInvalideDate.getDate()+' '); // Tous les jours suivants ne sont pas clickables / All the next days are unavailable var dNextDayAfterFirstInvalideDate = new Date(dFirstInvalideDate.getFullYear(), dFirstInvalideDate.getMonth(), dFirstInvalideDate.getDate()+1, '0', '0', '0', '0'); for(currentDate=new Date(dNextDayAfterFirstInvalideDate);currentDate<=dToDate;currentDate.setDate(currentDate.getDate()+1)) { var dateKey = getDateKey(currentDate); var dateNbr = currentDate.getDate(); var bIsNotAvailable = $('#'+dateKey).hasClass('notAvailable'); $('#'+dateKey).removeClass().addClass('notClickable'+(bIsNotAvailable ? ' notAvailable' : '')); var sAmount = $('#'+dateKey+' span.aPrice').text(); var sdiscountPrice = $('#'+dateKey+' span.aDiscountPrice').text(); $('#'+dateKey).empty().append(''+sdiscountPrice+''+dateNbr+''+sAmount+''); } // On regarde les contraintes "departure" sur toutes les dates futures valides. La contrainte est enregistre sur la veille, donc on test le jour precedent // We look for the departure constrain on the future valid date. The constrain is recorded on the previous day. for(currentDate=new Date(dFirstInvalideDate);currentDate>dDateToSet;currentDate.setDate(currentDate.getDate()-1)) { var dPreviousDate = new Date(currentDate); dPreviousDate.setDate(dPreviousDate.getDate()-1); var previousDateKey = getDateKey(dPreviousDate); var dateKey = getDateKey(currentDate); var dateNbr = currentDate.getDate(); var currentProposal = null; var bIsClickable = false; if( avaibility_daily[ previousDateKey ] != null ) // Les dates sans dispo ne peuvent pas avoir de contrainte / Date without availability can't have constrain { for(c=0;c 0.0 && isAvailableAccordingToLineitemDiscount( currentProposal[ 'lineitemDiscounts' ], 'departure' ) ) bIsClickable = true; } var sAmount = $('#'+dateKey+' span.aPrice').text(); var sdiscountPrice = $('#'+dateKey+' span.aDiscountPrice').text(); if(bIsClickable) { var cssAvaibleClass = $('#'+dateKey).hasClass('availablePartialy') ? 'availablePartialy' : 'available'; $('#'+dateKey).removeClass().addClass(cssAvaibleClass); var sDate = formatFixedDate(currentDate, 'fr'); $('#'+dateKey).empty().append(''+sdiscountPrice+''+dateNbr+''+sAmount+''); } else { $('#'+dateKey).removeClass().addClass('notClickable'); $('#'+dateKey).empty().append(''+sdiscountPrice+''+dateNbr+''+sAmount+''); } } } // Enfin, on applique d'eventuelles contraintes de minimum stay // /!\ Si on a une contrainte pour le type d'UH choisi mais pas pour les autres, il faut afficher les cases en orange ! // Then we apply "minimum stay" constrains. If there is a constrain on the selected room type, but not for the larger one, the cell is displayed as orange. var dateKey = getDateKey(dDateToSet); var dateNbr = dDateToSet.getDate(); if( typeof(avaibility_daily[ dateKey ]) != 'undefined' && avaibility_daily[ dateKey ].length > 0 ) { var currentProposal = null; // On regarde sur toutes les typologies s'il y a un minimum stay et on prend le plus court pour griser jusqu'a cette date // We chack on all the room types if there is a minimum stay, and we get the shorter to disable to this date. var minimumStay = 99; var nPreferedRoomTypeMinimumStay = 99; for(c=0;c minimumStay ) { // Certaines dispo ne sont pas pour le bon type d'UH, donc on les met en orange // Some availability are not for the good room type, so displayed in orange for( m=nPreferedRoomTypeMinimumStay;m>=minimumStay;m--) { dBadRoomTypeClickableDate = new Date(dDateToSet.getFullYear(), dDateToSet.getMonth(), (dDateToSet.getDate() + m), '0', '0', '0', '0'); var badRoomTypeClickableDateKey = getDateKey(dBadRoomTypeClickableDate); $('#'+badRoomTypeClickableDateKey).removeClass('available').addClass('availablePartialy'); } } for( m=minimumStay;m>0;m--) { dNotClickableDate = new Date(dDateToSet.getFullYear(), dDateToSet.getMonth(), (dDateToSet.getDate() + m), '0', '0', '0', '0'); var notClickableDateKey = getDateKey(dNotClickableDate); var notClickableDateNbr = dNotClickableDate.getDate(); var sAmount = $('#'+notClickableDateKey+' span.aPrice').text(); var sdiscountPrice = $('#'+notClickableDateKey+' span.aDiscountPrice').text(); $('#'+notClickableDateKey).removeClass().addClass('notClickable'); $('#'+notClickableDateKey).empty().append(''+sdiscountPrice+''+notClickableDateNbr+''+sAmount+''); } } } } /** Recupere la liste des propositions correspondantes aux dates et a la prestation de base choisie (utilise le modele search_result_for_grid.htm). Get the proposal list for the given dates and base product (use search_result_for_grid.htm template) */ function getPrices() { $("#searchResult").empty().append('

Recherche des meilleurs offres en cours...

'); var aSelectedStarDate = $('#start_date').val().split('/'); var dSelectedStarDate = new Date(aSelectedStarDate[ 2 ], (aSelectedStarDate[ 1 ] - 1), aSelectedStarDate[ 0 ], 0, 0, 0, 0); var aSelectedEndDate = $('#end_date').val().split('/'); var dSelectedEndDate = new Date(aSelectedEndDate[ 2 ], (aSelectedEndDate[ 1 ] - 1), aSelectedEndDate[ 0 ], 0, 0, 0, 0); var duration = Math.ceil( (dSelectedEndDate.getTime() - dSelectedStarDate.getTime())/86400000 ); showSelectDates(dSelectedStarDate,dSelectedEndDate); var searchUrl="/rsl/clickbooking?iframe=1&actions=updateCriterias%3BgetProposals&tokens=ignore_token&display=search_results&criterias_object_name=search_form&search_form_sort_string=Price&search_form_nb_adults=2&search_result_sub_page=search_result_for_grid.htm&search_form_max_rooms=1&search_form_no_counter_proposals=1&search_form_etab="+$('#etab_id').val()+"&search_form_start_date="+$('#start_date').val()+"&search_form_nb_days="+duration+"&search_form_product_code="+$('#search_form_product_code').val(); $("#searchResult").load(searchUrl+" .rechercheItems"); } /** Ajoute la classe choosedCell aux cellules entre les 2 dates choisies Add the css style choosedCell on the cells between the 2 choosen dates */ function showSelectDates(dSelectedStarDate,dSelectedEndDate) { for(currentDate=new Date(dSelectedStarDate);currentDate<=dSelectedEndDate;currentDate.setDate(currentDate.getDate()+1)) { var dateKey = getDateKey(currentDate); $('#'+dateKey).addClass('choosedCell'); } $('#'+getDateKey(dSelectedStarDate)).addClass('choosedCellFirst'); $('#'+getDateKey(dSelectedEndDate)).addClass('choosedCellLast'); } //