	function showAvail(i_day, i_month, i_year, key) {
		var url = getIncPath('livesearch.php');
		var pars = 'action=AvailByDay&day=' + i_day + '&month=' + i_month + '&year=' + i_year + '&appkey=' + key + '&lang=' + appLang + '&from_code=' + from_code;
    var myAjax = new Ajax.Updater('disponibilities', url, { method: 'get', parameters: pars });
	}

  /**
   * Simply calls a javascript alert message with the string passed in parameters.
   *
   * @param info The Message to display.
   */
	function displayAlert(info) {
		alert(info);
	}

  /**
   * Takes the authentication parameters then callback call authResponse function to authenticate 
   * a user and validate or not his access.
   * 
   * @param userid The username of the person
   * @param userpwd The password of the person
	 *
	 * @deprecated
   */   
	function authenticate(userid, userpwd) {
		var url = getIncPath('livequery.php');
		var pars = 'action=auth&userid=' + userid + '&userpwd=' + userpwd;
		var myAjax = new Ajax.Request( url, { method: 'get', parameters: pars, onComplete: authResponse });
	}

  /**
   * Treats the XML response of the autheticate method and updates agenda display
   * following the aswer received.
   *
   * @param resp Callback response containing the XML document
   *
   * @deprecated
   */	
	function authResponse(resp) {
	  var doc = resp.responseXML.documentElement;
	  if (doc) {
	    if (!isError(doc)) {
	    	formHide('divLogin');
        formShow('divBooking'); 
				formShow('divNewbooking');
	    } else {
	    	var url = getIncPath('livesearch.php');
	    	var pars = 'action=error&msg=' + escape(nodeValue(doc, 'errordesc')); 
	    	var myAjax = new Ajax.Updater('divLoginMsg', url, {method: 'get', parameters: pars});
	    }	
	  } else 
	  	  alert("Warning : No XML response sent!");
	}

  
  /**
   * Stores booking informations into hidden fields for further use and display.
   *
   * @param bstamp (Integer) Timestamp of the reservation
   * @param disdaymonth (String) Date of the reservation
   * @param dishourmin (String) Time of the reservation
   * @param disfree (Integer) Seats remaining
   */
  function prepareBooking(bstamp, disdaymonth, dishourmin, disfree) { 	
  	$('nmbookedfor').innerHTML = disdaymonth;
  	$('nmbookedat').innerHTML = dishourmin;
  	$('nmconfirmnmbookedfor').innerHTML = disdaymonth;
  	$('nmconfirmnmbookedat').innerHTML = dishourmin;  
  	$('bookingstamp').value = bstamp;	
  	$('nmfreespaces').value = disfree;
  	formHide('divAvail'); 
  	formShow('divLogin');
  }

	/**
	 * Checks the reservation fields.
	 * - Are they filled ?
	 * - Are the contents correctly formatted ?
	 * If so proceed to the validation process, if not, display the missing or incorrect reason.
	 *
	 */	 
	function validateNMBookingBid() {		
		var pplnbr = $F('nmbooknbr');
		if (!pplnbr) {  // the number of guest(s) hasn't been set
    	dispatchError('JS_PplNbrVoid', '');;			
		} else if (!isNumeric(pplnbr)) { // number of guest(s) contains non-numeric chars
				dispatchError('JS_PplChrChk', '');
		} else if (!$F('nmlastname') || !$F('nmfirstname') || !$F('nmphone') || !$F('nmemail')) { //required zones not filled  
			if (!$F('nmlastname'))
			  dispatchError('JS_NameReq', ''); else
			if (!$F('nmfirstname'))
			  dispatchError('JS_FnameReq', ''); else
			if (!$F('nmphone'))
			  dispatchError('JS_PhoneReq', ''); else
			if (!$F('nmemail'))
			  dispatchError('JS_MailReq', '');			    			  			  			
/*		} else if (formatForSms($F('nmphone'))=='') {
				dispatchError('JS_ValidPhone', ''); */
		} else if (!checkInternationalPhone($F('nmphoneintl')+$F('nmphone'))) {
				dispatchError('JS_ValidPhone', '');				
		} else if (!emailvalid($F('nmemail'))) {
				dispatchError('JS_ValidMail', '');
		} else if (($F('nmfreespaces') - pplnbr) < 0) { // not enough free places to valid the booking.   		
    	  $('nmbooknbr').value = $F('nmfreespaces');
    	  dispatchError('JS_NoRoom', pplnbr + ';' + $F('nmfreespaces'));
 		} else { // all is ok, go to confirmation div.
		  nmciv = '';
		  $('nmguestnbr').innerHTML = pplnbr;
		  if ($F('nmciv1'))
		    nmciv = $F('nmciv1'); 
		  else if ($F('nmciv2')) 
		  	nmciv = $F('nmciv2'); 
		  else if ($F('nmciv3')) 
		  	nmciv = $F('nmciv3'); 		  			  	
		  $('nmcciv').innerHTML = nmciv;
		  $('nmclastname').innerHTML = $F('nmlastname');		 
		  $('nmcfirstname').innerHTML = $F('nmfirstname');		  
		  $('nmcphone').innerHTML = formatPhone();		
		  $('nmcemail').innerHTML = $F('nmemail');	
		  $('divBookingBid').innerHTML = '';
		  
	  	if (eval($F('groupaction')) == 3) {
		  	if (eval($F('nmbooknbr')) > eval($F('grouplimit'))) {
		  		//NMProcessOgone();
 				  $('nmpayby').innerHTML = 'A partir de ' + $F('grouplimit') + ' personnes, le restaurant requiert un acompte de '+ $F('depositamount') + '&euro; pour valider votre réservation<br /><br />';
 				  $('nmpayby').innerHTML += 'Vous allez maintenant être redirigé vers le site de paiement sécurisé.'; 
 				  new Rico.Effect.Round( 'div', 'divpayby', {corners:'tl tr bl br',border:'#000000', compact:false} );
 				  formShow('divpayby');
		  	}
		  }		  
		  		  //NMCheckFee(pplnbr > 4);
		  //$('nmCheckFee').onClick = NMCheckFee(pplnbr > 4);		  
			formHide('divAuth');	  		  		  
		  formHide('divBookingBid');
      formHide('divNMBookingBid');
      formShow('divNMConfirmation');
    } 	    
	}

  /**
   * Check admin's group action settings and call the real reservation process or
   * switch to the Ogone screen for online payment.
   *
   */
  function performConfirmation() {
	  	if (eval($F('groupaction')) == 3) {
		  	if (eval($F('nmbooknbr')) > eval($F('grouplimit'))) {          
          formHide('divNMConfirmation');
          formShow('divNMPayment');
          NMPreprocessOgone();
        } else {
        	  NMDoBooking();
        	}
      } else  
      NMDoBooking();      
  }

  /**
   * Takes the translation alias code and language then callback call the db to
   * get the translations. 
   * 
   * @param codeid Text alias of the translation
   * @param params (Optional) Array for passing multiple parameters if required by the alias translation.
	 *
   */ 
  function dispatchError(codeid, params) {
		//let's translate first
		var url = getIncPath('livequery.php');
		var pars = 'action=translate&s_code=' + codeid + '&s_lang=' + appLang + '&a_params=' + params;
		var myAjax = new Ajax.Request( url, { method: 'get', parameters: pars, onSuccess: updateErrorDiv});  	
  }

  /**
   * Updates the error's DIV from the client with right translated message following the XML response received.
   *
   * @param resp Callback response containing the XML document
   */
  function updateErrorDiv(resp) {
	  var doc = resp.responseXML.documentElement;
   	var url = getIncPath('livesearch.php');   
	  if (doc) 
    	var pars = 'action=err&msg=' + nodeValue(doc, 'translation'); 	  	
	  else
	  	var pars = 'action=err&msg=[Translation not found]'; 
    var myAjax = new Ajax.Updater('divBookingBid', url, {method: 'get', parameters: pars});; 				    	
    formShow('divBookingBid');    		  	 	
  }

  /**
   * Check group action following admin settings.
   * - If group limit is over or gets an error, display it to client.
   * - If group limit is reached then take appropriate actions (call or else).
   */
  function NMCheckGroupAction() {	
  	switch ($F('groupaction')) {
  		case '2':
  		  if (!isNumeric($F('nmbooknbr'))) { // number of guest(s) contains non-numeric chars
				  dispatchError('JS_PplChrChk', '');
				  break;
			  }
			  if ((eval($F('grouplimit') > 0)) && (eval($F('nmbooknbr')) > eval($F('grouplimit')))) {
					var url = getIncPath('livequery.php');
					var params = $F('grouplimit') + ';' + $F('restotel') ;
					var pars = 'action=translate&s_lang=' + appLang + '&s_code=TXT_GroupOver&a_params=' + params;
					var myAjax = new Ajax.Request( url, { method: 'get', parameters: pars, onSuccess: updateMessageDiv});
			  } else {
			  	formHide('divNMInfo');
			  	formShow('divNMData');
			  }
  		  break;
    }
  }
  
  /**
   * Updates the HTML DIV "message" to furnish information to client while being in the registration process.
   *
   * @param resp Callback response containing the XML document
   */
  function updateMessageDiv(resp) {
	  var doc = resp.responseXML.documentElement;
   	var url = getIncPath('livesearch.php');   
	  if (doc) 
    	var pars = 'action=err&msg=' + nodeValue(doc, 'translation'); 	  	
	  else
	  	var pars = 'action=err&msg=[Translation not found]'; 
    var myAjax = new Ajax.Updater('divNMInfo', url, {method: 'get', parameters: pars});; 				    	   	
    formShow('divNMInfo');  
    formHide('divNMData');   
  }

	/**
	 * Displays the credit DIV if group option == pay a deposit.
	 *
	 * @params withFee True ou False, is there a deposit to ask to the client.
	 */
  function NMCheckFee(withFee) {
  	if (withFee) {
  		new Rico.Effect.Round( 'div', 'infoOgone' );
  		formShow('divNMBookingOgone');
  	} else {
  	  formHide('divNMBookingOgone');  	    	  
  	}  	
  }

  /**
   * Performs the confirmation.
   */
  function NMDoBooking() {
    formHide('divNMConfirmation');
  	var nmciv = ''; 
  	var dbciv = 0;
	  if ($F('nmciv1'))
	    nmciv = $F('nmciv1'); 
	  else if ($F('nmciv2')) { 
	  	nmciv = $F('nmciv2');
	  	dbciv = 1; 
	  }
	  else if ($F('nmciv3')) { 
	  	nmciv = $F('nmciv3'); 
	  	dbciv = 2;
	  }
    $('nmcciv2').innerHTML = nmciv;
    $('nmclastname2').innerHTML = $F('nmlastname');
    $('nmguestnbr2').innerHTML = $('nmguestnbr').innerHTML;
    $('nmconfirmnmbookedfor2').innerHTML = $('nmconfirmnmbookedfor').innerHTML;
    $('nmconfirmnmbookedat2').innerHTML = $('nmconfirmnmbookedat').innerHTML;  
 		var url = getIncPath('livequery.php');
 		var nmCredit = 0;
 		//if ($F('nmbooknbr') > 4) nmCredit = 15;
	  	if (eval($F('groupaction')) == 3) {
		  	if (eval($F('nmbooknbr')) > eval($F('grouplimit'))) {
		  		nmCredit = $F('depositamount');
		  	}
		  } 		
		var pars = 'action=nmsave&s_bStamp='     + $F('bookingstamp') + 
		                        '&s_places='    + $('nmguestnbr2').innerHTML  +
		                        '&s_credit='    + nmCredit + 
		                        '&s_title='			+ dbciv + 
		                        '&s_placeid='		+ appKey + 
		                        '&s_lastname='  + $F('nmlastname') +
		                        '&s_firstname=' + $F('nmfirstname') +
		                        '&s_email='		  + $F('nmemail') +
		                        '&s_phone='		  + formatPhone() + 
		                        '&s_comment='		+ checkPrefillComment() +
                            '&s_from_code=' + $F('from_code') +
                            '&s_duration='	+ $F('mealduration') +
                            '&s_lang='      + appLang +
                            '&s_ref='			  + $F('bookingREF');
		var myAjax = new Ajax.Request( url, { method: 'get', parameters: pars, onComplete: NMBookingCompleted });		       
  }

	/**
	 * Analyse the reservation's confirmation XML response and updates display following the response received.
	 * Call the sendsms() function if it matches the admin settings.
	 *
   * @param resp Callback response containing the XML document
   */   
  function NMBookingCompleted(resp) {
  	//alert(resp.responseText);	
	  var doc = resp.responseXML.documentElement;
	  if (doc) {
	    if (!isError(doc)) {
	    	$('bookingID').value = nodeValue(doc, 'id');	    	
	    	$('bookingREF').value = nodeValue(doc, 'reference');
	    	$('bookedat').value = nodeValue(doc, 'booked_dt');	    	
	    } else {
	    	alert('SQL error when storing booking');
	    }
	  }
    new Rico.Effect.Round( 'div', 'infoOgone');
    formShow('divNMBooked');  
    formShow('divNMBookedOgone');
    if ($F('nmcomment').length > 0) 
      var cmt = 'true';
    else
    	var cmt = 'false';
 		var url = getIncPath('livesearch.php');
 		var pars = 'action=sms' + 
                '&s_places='    + $F('nmbooknbr')  +
                '&iDateFrom='   + $('nmconfirmnmbookedfor').innerHTML +
								'&iHourFrom='   + $('nmconfirmnmbookedat').innerHTML +		                         
                '&s_lastname='  + $F('nmlastname') +
                '&s_firstname=' + $F('nmfirstname') +
      					'&s_title='     + nmciv +                   
                '&s_email='     + $F('nmemail') +
                '&s_phone='			+ formatPhone() +
                '&s_comment='   + cmt +
                '&s_reference=' + $F('bookingREF') + 
                '&s_placeid='		+ appKey + 
                '&s_stamp='		  + $F('bookingstamp') + 
                '&s_bookedat='	+ $F('bookedat') +
                '&i_bookingid=' + $F('bookingID') +
                '&s_lang='			+ appLang;   
                //alert(pars);            
		var myAjax = new Ajax.Updater( 'nmsms', url, { method: 'get', parameters: pars, onComplete: getSmsStatus });		      	
  }
  
  /**
   * Get NetSize's sms xml report status (used only for debug and de-activated).
   */
  function getSmsStatus(resp) {
    //alert(resp.responseText);  	
  }
  
  /** 
   * Calls the ogone processing service if place requires a credit to be paid and check values and settings.
   */
  function NMPreprocessOgone() {  	
  	var url = getIncPath('livequery.php');  	
    var pars = 'action=payByOgone' + 
      '&place_id=' + appKey +
      '&lang=' + appLang;
		var myAjax = new Ajax.Updater( 'nmsms', url, { method: 'get', parameters: pars, onComplete: NMProcessOgone });
  }
  
  /**
   * Creates and displays a new window with ogone console for the customer.
   *
   * @param resp Callback response containing the XML document
   */
  function NMProcessOgone(resp) {
	  var doc = resp.responseXML.documentElement;
 	  if (doc) {
	    if (!isError(doc)) {
		  	$('bookingREF').value = nodeValue(doc, 'reference');		  	
		  	var w = 760;
		  	var h = 560; 
		  	var url= nodeValue(doc, 'url')		 	
		  	var pars = 'place_id=' + appKey +
		  	           '&lang=' + appLang + 
		  	           '&ref=' + $F('bookingREF') + 
		  	           '&tmpl=default' +
		  	           '&cowner=' + escape($F('nmlastname') + ' ' + $F('nmfirstname'));
		  	var win = window.open(url+pars, '', 'menubar=no,resizable=yes,locationbar=yes,scrollbars=yes,width='+w+',height='+h+',top=20');
		  	win.moveTo(screen.availWidth/3-(w/3),screen.availHeight/3-(h/3));
		  }
		}				
  }
  
  /**
   * Calls the database to check if the payment has been done and callback calls infoPayment() for an xml response.
   *
   */ 
  function checkPayment() {
  	var url = getIncPath('livequery.php');
 		var pars = 'action=checkpayment' +
 		           '&s_lang=' + appLang +
 		           '&s_placeid=' + appKey + 
 		           '&s_reference=' + $F('bookingREF');
		var myAjax = new Ajax.Request( url, { method: 'get', parameters: pars, onComplete: infoPayment });	
  }
   
  /**
   * Analyze if payment has been processed throughout the XML response and process the booking if so.
   *
   * @param resp Callback response containing the XML document
   */
  function infoPayment(resp) {  	
	  var doc = resp.responseXML.documentElement;
	  if (doc) {
	    if (!isError(doc)) {
	    	formHide('divNMPayment');
    	  NMDoBooking();
	    } else {
	    	if (appLang == 'fr') {
	    	  alert("The payment has not yet been processed or is not authorized.");
	    	} else 
	    	if (appLang == 'nl') {
	    		alert("De betaling is nog niet verwerkt of niet is toegestaan.");
	    	} else {
	    		alert("Le payement n'a pas encore été effectué ou n'est pas autorisé.");
	    	}	    		
	    }
	  }  	
  }   
  
  /**
   * Calls an ajax DIV display of the promotion or advertising.
   *
   * @param resp Callback response containing the XML document  
   */
  function displayPromo(resp) {
 		var url = getIncPath('livesearch.php');
 		var pars = 'action=promo';		                                              
		var myAjax = new Ajax.Updater( 'promo', url, { method: 'get', parameters: pars, onComplete: displayPromo });		      	
  } 

  /**
   * Creates a new window with the proof of confirmation (same as customer will get by mail).
   * 
   * @param docName Filename of the template to use.
   */
   
  function NMPrintBooking(docName) {
  	var w = 760;
  	var h = 560; //window.screen.Height -20;
    var pars = '?booking_id=' + $F('bookingID') +
               '&language=' + appLang;      
  	var win = window.open(getIncPath(docName)+pars, '', 'menubar=yes,resizable=yes,scrollbars=yes,width='+w+',height='+h+',top=20');
  	win.moveTo(screen.availWidth/3-(w/3),screen.availHeight/3-(h/3));
  	return true;  	
  }
     
  function oldNMPrintBooking(docName) {
  	
  	var w = 760;
  	var h = 560; //window.screen.Height -20;
    var pars =
      '?s_places='    + $F('nmbooknbr')  +
      '&iDateFrom='   + $('nmconfirmnmbookedfor').innerHTML +
			'&iHourFrom='   + $('nmconfirmnmbookedat').innerHTML +		                         
      '&s_lastname='  + $F('nmlastname') +
      '&s_firstname=' + $F('nmfirstname') +
      '&s_title='     + nmciv +      
      '&s_mail=' 		  + $F('nmemail') +
      '&s_reference='	+ $F('bookingREF') + 
      '&s_placeid='		+ appKey + 
      '&s_bookedat='	+ $F('bookedat') +
      '&s_stamp='		  + $F('bookingstamp') +
      '&s_lang='			+ appLang;

  	var win = window.open(getIncPath(docName)+pars, '', 'menubar=yes,resizable=yes,scrollbars=yes,width='+w+',height='+h+',top=20');
  	win.moveTo(screen.availWidth/3-(w/3),screen.availHeight/3-(h/3));
  	return true;
  }
  
  /**
   * Check if a reservation based on the parameters passed can be unbooked.
   * 
   * @param id The reference number of the reservation
   * @param check The hashed check code to validate the unbooking
   * @param lang Language in which to display the unbooking page
   * @param plid The id of the place where the unbooking is for
   */
  function unbookcheck(id, check, lng, plid) {
 		var url = getIncPath('livequery.php');
 		var pars = 'action=checkUnbookRef' + 
                '&i_ref='  + id  +
                '&s_chk='	 + check + 
                '&s_lng='  + lng + 
                '&s_plid=' + plid;
    new Ajax.Request( url, { method: 'get', parameters: pars, onComplete: unbookCheckCompleted });                		 	
  }

  /**
   * Analyze XML response and displays the confirmation of the reservation being cancelled.
   *
   * @param resp Callback response containing the XML document  
   */   
  function unbookCheckCompleted(resp) {
	  var doc = resp.responseXML.documentElement;
 		var pars = 'action=unbookDisplay';
	  if (doc) {
	    if (isError(doc)) {
	    	pars += '&status=-1&s_msg=' + nodeValue(doc, 'errordesc');
	    } else {
	    	pars += '&status=0&s_lastname=' + nodeValue(doc, 'name') +
	    	        '&i_title=' + nodeValue(doc, 'title') +
	    	        '&i_places=' + nodeValue(doc, 'places') +
	    	        '&i_date=' + nodeValue(doc, 'date') + 
	    	        '&i_id=' + nodeValue(doc, 'id') +
	    	        '&s_chk=' + nodeValue(doc, 'check') + 
	    	        '&s_lng=' + nodeValue(doc, 'language') + 
                '&i_placeid=' + nodeValue(doc, 'placeid') + 
	    	        '&s_placename=' + nodeValue(doc, 'placename');
	    }
	  } 		
 		var url = getIncPath('livesearch.php');
    new Ajax.Updater( 'unbookmsg', url, { method: 'get', parameters: pars});                		 	
  }  

	/**
	 * Following admin comments settings prefilled, do no store any comments if nothings was added by the customer.
	 *
	 * @return Void string or prefilled comments completed.
	 */
	function checkPrefillComment() {
		$('comparecomment').value = $F('nmcomment');
		if ($F('placecomment').replace(/\r\n/g,"", "") == $F('comparecomment').replace(/\n/g,"", "")) { 
		  return '';
		} else {
		  return escape($F('nmcomment'));
		}		
	}
  
  /**
   * Calls the ajaxed unbooking check with required parameters.
   *
   * @param id The reference number of the reservation
   * @param check The hashed check code to validate the unbooking
   * @param lng Language in which to display the unbooking page
   * @param placeid The id of the place where the unbooking is for
   */   
  function unbook(id, check, lng, placeid) {
 		var url = getIncPath('livesearch.php');
 		var pars = 'action=unbook' + 
                '&i_id=' + id  +
                '&s_chk='	+ check + 
                '&s_lng=' + lng +
                '&i_placeid=' + placeid;
		var myAjax = new Ajax.Updater( 'unbookmsg', url, { method: 'get', parameters: pars });  	  	
  }
  
	/* Utils functions */

	/**
	 * Get the node's value of an XML response.
	 *
	 * @param node XML Node
	 * @param name Node's name
	 */
	function nodeValue(node, name) {
	    var childs = node.getElementsByTagName(name);
	    if (childs.length > 0 && childs.item(0).childNodes.length > 0)
	        return childs.item(0).childNodes.item(0).nodeValue;
	    return "";
	}
	
	/**
	 * Takes a XML document element and checks its error code status then return false if error(s) occured.
	 */
	function isError(docElement) {
		return eval(nodeValue(docElement, 'errorcode')) > 0;
	}
	
	/**
	 * Check if the int passed as parameters is valid.
	 *
	 * @param sText Numeric value to check
	 */
	function isNumeric(sText){
	   var ValidChars = "0123456789";
	   var isNumber=true;
	   var Char;
	 
	   for (i = 0; i < sText.length && isNumber; i++) { 
	      Char = sText.charAt(i); 
	      if (ValidChars.indexOf(Char) == -1) {
	         isNumber = false;
	      }
	   }
	   return isNumber;
	}	
	
  /**
   * Javascript function to automatically handle "enter" as a submit action.
   *
   * @param e Event
   *
   * @deprecated
   */
  function enterSubmitAuth(e) {
    if (window.event && (window.event.keyCode == 13) || (e.which == 13))
      authenticate($F('authid'), $F('authpwd'));
   else
      return true;
  } 
  
  /**
   * Handles javascript files location based on relative paths.
   *
   * @param str Relative path
   */   
  function getIncPath(str) {
  	return ''+incPath.toString()+str.toString();    
  }   

	/**
	 * Checks the validity of an email address syntaxycally.
	 *
	 * @param (String) Email address to validate
	 */
	function emailvalid (email) {               
     return email.match(/^[\w\.\-]+@([\w\-]+\.)+[a-zA-Z]+$/);
	}

	/** Declaring required variables */
	var digits = "0123456789";
	/** non-digit characters which are allowed in phone numbers */
	var phoneNumberDelimiters = "()-/. ";
	/**
	 * characters which are allowed in international phone numbers
	 * (a leading + is OK)
	 */
	var validWorldPhoneChars = phoneNumberDelimiters + "+";
	/** Minimum no of digits in an international phone no. */
	var minDigitsInIPhoneNumber = 10;
	
	/**
	 * Check if the int passed as parameters is valid.
	 *
	 * @param s Numeric value to check
	 */
	function isInteger(s)
	{   var i;
	    for (i = 0; i < s.length; i++)
	    {   
	        // Check that current character is number.
	        var c = s.charAt(i);
	        if (((c < "0") || (c > "9"))) return false;
	    }
	    // All characters are numbers.
	    return true;
	}

	/**
	 * Check chars of a chain and appends them to the result, avoiding white spaces
	 *
	 * @param s Start value
	 * @param bag Bag to check
	 * @return Everything in bag trimmed
	 */	
	function stripCharsInBag(s, bag)
	{   var i;
	    var returnString = "";
	    // Search through string's characters one by one.
	    // If character is not in bag, append to returnString.
	    for (i = 0; i < s.length; i++)
	    {   
	        // Check that current character isn't whitespace.
	        var c = s.charAt(i);
	        if (bag.indexOf(c) == -1) returnString += c;
	    }
	    return returnString;
	}

  /**
   * Checks the validity of an internation formatted phone number
   *
   * @param strPhone Phone # to check
   */
	function checkInternationalPhone(strPhone){
	s=stripCharsInBag(strPhone,validWorldPhoneChars);
	return (isInteger(s) && s.length >= minDigitsInIPhoneNumber);
	}
	
	/**
	 * Formats phone number if correct to be stored in the serveonline database
	 */
	function formatPhone() {
		var nbr = ""; 
		if ($F('nmphoneintl').length > 0)
		  nbr = $F('nmphoneintl');
		else
			nbr = "0032"; // define to belgium if not set
    if ($F('nmphone').charAt(0) == "0")	{
      nbr += $F('nmphone').substring(1);
    }	else {
    	nbr += $F('nmphone');
    }
    return stripCharsInBag(nbr, validWorldPhoneChars);
	}
	
	/**
	 * Show or Hide DIVS following their ID
	 */
	function showHideForm(id) {
		if($(id).style.visibility == 'visible') {
      $(id).style.visibility= 'hidden';
      $(id).style.display= 'none';
    } else {
      $(id).style.visibility= 'visible';
      $(id).style.display= 'block';     	
    } 		
	}

// Calendar vars and DOM creation of the agenda.
// Sanitanized for security reasons.

var ab=new Array("D","L","M","M","J","V","S");
var R=new Array("Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Decembre");
var O=new Array(31,28,31,30,31,30,31,31,30,31,30,31);
var appKey = null;
var incPath = null;
var appLang = null;
var nmciv = null;
var from_code = null;


function z(n,v){var c=n+"="+encodeURIComponent(v);c+="; path=/";document.cookie=c;};
function j(p){return p.appendChild(document.createElement("div"));};
function o(month,year){if(month==1&&year%4==0)return 29;else return O[month];};
function t(){var aa=navigator.userAgent.toLowerCase();if(aa.indexOf('opera')!=-1)return true;else return false;};
function r(T){return(T.U)?T:r(T.parentNode);};
function l(e){e=e?e:window.event;return r(e.currentTarget?e.currentTarget:e.srcElement);};
function contains(parent,B){if(!B||B.tagName=="BODY")return false;if(parent==B)return true;return contains(parent,B.parentNode);};
function k(e){e.currentTarget.M=true;e.currentTarget.onmouseenter(e);};
function w(e){if(!contains(e.currentTarget,e.relatedTarget)){e.currentTarget.M=false;e.currentTarget.onmouseleave(e);}};
function f(T,K){if(t()){T.onmouseenter=K;T.attachEvent("mouseover",k,false);}else if(T.attachEvent)T.attachEvent("onmouseenter",K);else{T.onmouseenter=K;T.addEventListener("mouseover",k,false);}};
function g(T,K){if(t()){T.onmouseleave=K;T.attachEvent("mouseout",w,false);}else if(T.attachEvent)T.attachEvent("onmouseleave",K);else{T.onmouseleave=K;T.addEventListener("mouseout",w,false);}};
/**
 * Constructor
 * 
 * Creates a new instance of the agenda.
 *
 * @param id Identifier of the agenda
 * @param lang Language the agenda will display
 * @param key Id of the place in the places table
 * @param incpath Relative url to base on for scripts
 */
function ServeOnlineEbooking(id, lang, key, incpath) { 
	if (lang=="fr") {
		ab = new Array("D","L","M","M","J","V","S");
		R = new Array("Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Decembre");
	} else 
	if (lang=="nl") {
		ab = new Array("Z","M","D","W","D","V","Z");
		R = new Array("Januari","Februari","Maart","April","Mei","Juni","Juli","Augustus","September","Oktober","November","December");		
	} else 
	if (lang=="en") {
		ab = new Array("S","M","T","W","T","F","S");
		R = new Array("January","February","March","April","May","June","July","August","September","October","November","December");		
	}
	appKey = key;
	incPath = incpath;
	appLang = lang;
	
	
	with(document){

    this.onDateChanged =
      function(formattedDate, currentDay, currentMonth, currentYear) {
        showAvail(currentDay, currentMonth, currentYear, appKey);
        return true;
      };

		this.setDate=
		  function(d,m,y){
		  	this.X=new Date(y,m-1,d);
		  	this.setMonth(m,y);
		  	z("cldr"+this.id,m+"/"+d+"/"+y);
		  	if(this.onDateChanged) {
		  		this.onDateChanged(this.X, d, m, y);
		  		//showAvail(d, m, y);
		  	}
		  };
		
        
    this.setFromCode=
        function(s){
            from_code = s;
        };
            
		this.getDate=
		  function(){
			  return this.X;
		  };
		
		this.setMonth=
		  function(m,y){
		  	this.month=m-1;
		  	this.year=y;
		  	this.refresh();
		  };		  	  
		  
		this.V=
		  function(T){
		  	if(!T.I)return;
		  	T.U.C();
		  	T.U.N=T;
		  	T.className="selected";		  	
		  	T.X=true;
		  	T.U.X=new Date(T.U.year,T.U.month,parseInt(T.texte.innerHTML,10));
		  	T.U.curDay = parseInt(T.texte.innerHTML,10);
		  	T.U.curMonth = T.U.month + 1;
		  	T.U.curYear = T.U.year;
		  	//alert(T.texte.tagName);
		  	//alert("cldr"+T.U.id + ' ' + T.U.month+"/"+T.U.curDay+"/"+T.U.year);
		  	z("cldr"+T.U.id,T.U.month+"/"+T.texte.innerHTML+"/"+T.U.year);
		  };
		
		this.W=
		  function(e){
		  	var T=l(e);
		  	T.U.V(T);
		  	if(T.U.onDateChanged)
		  	  //T.style.background="#ff0000";
		  	  T.U.onDateChanged(T.U.X, T.U.curDay, T.U.curMonth, T.U.curYear);
		  };
		
		this.C=
		  function(){
		  	if(this.N&&this.N.I){
		  		this.N.className="normal";
		  		//this.N.style.background="#ffffff";
		  		this.N.X=false;
		  	}
		  };
		  
		this.setSkin=
		  function(s){
		  	if(!document.CalendarSkin){
		  		document.CalendarSkin=this.A.appendChild(createElement("link"));
		  		document.CalendarSkin.type="text/css";
		  		document.CalendarSkin.rel="stylesheet";
		    }
		    //document.CalendarSkin.href=this.resources+s+"/skin.css";
		    document.CalendarSkin.href="/agenda.css.php?place_domain="+s+"&skin=yes";
		  };		  

		this.setPath=
		  function(s){
		    test2=s;
		  };	
		
	  this.refresh=
	    function(){
	    	var Z;
	    	var F=false;
	    	var Y=new Date(this.year,this.month,1);
	    	var P=Y.getDay();
	    	var Q=o(this.month,this.year);
	    	this.C();
	    	if(this.X&&this.month==this.X.getMonth()&&this.year==this.X.getFullYear())
	    	  F=true;
	    	Y=1;
	    	for(var i=0;i<41;i++){
	    		var item=this.G[i];
	    		if(i<P||Y>Q){
	    			item.texte.innerHTML="&nbsp;";
	    			item.I=false;
	    			item.className="cell";
	    		} else {
	    			item.className="normal";
	    			item.I=true;
	    			Z=new Date(this.year,this.month,Y);
	    			item.texte.innerHTML=$(Y).toString();
	    			//alert(item.text);
	    			//item.insertAdjacentHTML($(Y).toString());
	    			//item.textinnerHTML=$(Y).toString();
	    			// add the day
	    			//item.style.color="#ff00ff";
	    			if(F&&Y==this.X.getDate())
	    			  this.V(item);
	    			  Y++;
	    		}
	    	}
	    	this.D.innerHTML=R[this.month]+" "+this.year;};
	    	this.id=id;
	    	this.A=getElementById(id);
	    	this.A.U=this;
	    	this.inner=j(this.A);
	    	this.inner.style.position="relative";
	    	this.A.onmousedown=function(e){
	    		return false;
	    	};
	    	this.A.onmouseup=function(e){
	    		return true;
	    	};
	    	this.A.onselectstart=function(e){
	    		return false;
	    	};
	    	this.ac=new Array(7);
	    	this.G=new Array(40);
	    	this.inner.appendChild(this.A.removeChild(getElementById("l"+this.id)));
	    	var L=j(this.inner);	    
	    	L.className="header";
	    	this.D=j(L);
	    	this.D.className="date";
	    	var S=j(L);
	    	S.className="prev";
	    	S.onclick=function(e){
	    		var T=l(e);
	    		if(T.U.month-1<0){T.U.month=11;T.U.year--}else T.U.month--;T.U.refresh();};
	    		S=j(L);
	    		S.className="next";
	    		S.onclick=function(e){
	    			var T=l(e);
	    			if(T.U.month+1>11){T.U.month=0;T.U.year++}else T.U.month++;T.U.refresh();
	    		};
	    	var ac=j(this.inner);
	    	ac.className="weekdays";
	    	for(var i=0;i<7;i++){
	    		this.ac[i]=j(ac);
	    		this.ac[i].innerHTML=ab[i];
	    		this.ac[i].style.position="absolute";
	    		this.ac[i].style.left=Math.round(i*20)+"px";
	    	}
	    	var H=j(this.inner);
	    	H.className="days";
	    	for(var i=0;i<41;i++){
	    		var J=createElement("div");
	    		J.className="grid";
	    		H.appendChild(J);
	    		J.style.position="absolute";
	    		J.style.top=(Math.floor(i/7)*19).toString()+"px";
	    		J.style.left=((i%7)*20+2).toString()+"px";
	    		this.G[i]=j(J);
	    		this.G[i].U=this;
	    		this.G[i].className="cell";
	    		this.G[i].I=false;
	    		var ZZZ = createElement("span");
	    		ZZZ.className="text",
	    		this.G[i].texte=this.G[i].appendChild(ZZZ);
	    		//this.G[i].text.className="text";
	    		//this.G[i].text.name="span"+i;
	    		f(this.G[i],function(e){var T=l(e);if(!T.X&&T.I)T.className="hover";});
	    		g(this.G[i],function(e){var T=l(e);if(!T.X&&T.I)T.className="normal";});
	    		this.G[i].onmouseup=this.W;
	    	}
	    }
	   } 

