
if (document.layers) 
{ // Netscape
    document.captureEvents(Event.MOUSEMOVE);
    document.onmousemove = captureMousePosition;
} 
else if (document.all) 
{ // Internet Explorer
    document.onmousemove = captureMousePosition;
} 
else if (document.getElementById) 
{ // Netcsape 6
    document.onmousemove = captureMousePosition;
}

var CALENDAR_LANGUAGE_MAP = { 
		'en_US': 'en',
		'th_TH': 'th',
		'id_ID': 'id',
		'zh_CN': 'zh-CN',
		'ja_JP': 'ja',
		'ko_KR': 'ko',
		'ru_RU': 'ru',
		'ms_MY': 'ms'
};


/*
function addLoadEvent(func) {   		
	var oldonload = window.onload;   		
	if (typeof window.onload != "function"){window.onload = func;}		
	else {window.onload = function(){if(oldonload){oldonload();}func();}}   	
}

addLoadEvent( function(){ Event.observe(document, "mouseover", captureMousePosition, false); });
*/
var languageCode = "en_US";
function setLanguageCode(lang)
{
    languageCode = lang; // global variable
}
// Global variables
xMousePos = 0; 
yMousePos = 0; 
xMousePosMax = 0; // Width of the page
yMousePosMax = 0; // Height of the page
function captureMousePosition(e) 
{	
	if (!e) var e = window.event;

	if (e.pageX || e.pageY) 	{
		xMousePos = e.pageX;
		yMousePos = e.pageY;
	}
	else if (e.clientX || e.clientY) 	{
		xMousePos = e.clientX + f_scrollLeft();
		yMousePos = e.clientY + f_scrollTop();
	}
    xMousePosMax = f_clientWidth()+f_scrollLeft();
    yMousePosMax = f_clientHeight()+f_scrollTop();

}

function f_clientWidth() {
	return f_filterResults (
		window.innerWidth ? window.innerWidth : 0,
		document.documentElement ? document.documentElement.clientWidth : 0,
		document.body ? document.body.clientWidth : 0
	);
}
function f_clientHeight() {
	return f_filterResults (
		window.innerHeight ? window.innerHeight : 0,
		document.documentElement ? document.documentElement.clientHeight : 0,
		document.body ? document.body.clientHeight : 0
	);
}
function f_scrollLeft() {
	return f_filterResults (
		window.pageXOffset ? window.pageXOffset : 0,
		document.documentElement ? document.documentElement.scrollLeft : 0,
		document.body ? document.body.scrollLeft : 0
	);
}
function f_scrollTop() {
	return f_filterResults (
		window.pageYOffset ? window.pageYOffset : 0,
		document.documentElement ? document.documentElement.scrollTop : 0,
		document.body ? document.body.scrollTop : 0
	);
}
function f_filterResults(n_win, n_docel, n_body) {
	var n_result = n_win ? n_win : 0;
	if (n_docel && (!n_result || (n_result > n_docel)))
		n_result = n_docel;
	return n_body && (!n_result || (n_result > n_body)) ? n_body : n_result;
}

function highlight(rowid)
{
    var ele = document.getElementById(rowid);
    if (ele) {
    	Element.addClassName(ele, 'rowHilight');
    }
}
function lowlight(rowid)
{
    var ele = document.getElementById(rowid);
    if (ele)
    	Element.removeClassName(ele, 'rowHilight');
}
function showbox(boxname, hpos)
{	
	if (xMousePos < 30 || yMousePos < 30) return;
	if (!$(boxname)) return;
	if (!$('bubblebox')) return; 
	
	hotcount = new Number(6);
    if (document.dat)
    {
        hotcount = new Number(document.dat.hotcount.value);
    }
    //leftpos = new Number(xMousePos-0); // was -12
    //toppos = new Number(yMousePos-0); // was -150
    leftpos = hpos.pageX;
    toppos = hpos.pageY;
    
    if (!leftpos) leftpos = window.event.clientX + f_scrollLeft();
    if (!toppos) toppos = window.event.clientY + f_scrollTop();
	
	$('bubblebox').innerHTML = document.getElementById(boxname).innerHTML;
    elebox = $('bubblebox');
	
    if (elebox)
    {
        if (elebox.innerHTML != "")
        {
            if (leftpos > (document.viewport.getWidth() - 380))
                leftpos = leftpos-350;
            if (hotcount>0)
            {
                if (hotcount>3)
                {
                    midscr = hotcount/2;
                    if (hpos>midscr)
                        toppos=toppos-100;
                }
                else
                {
                    toppos = toppos-50;
                }
            }
            /*
            $('bubblebox').innerHTML += 'MouseLeft:'+ leftpos +'<br>';
            $('bubblebox').innerHTML += 'MouseTop:'+ toppos +'<br>';
            */
						
			var main = $('main-content');
			var offset = Position.cumulativeOffset(main);
			
			leftpos -= offset[0];
			toppos -= offset[1];
						
            elebox.style.left=leftpos + 'px';
            elebox.style.top=toppos + 'px';
            elebox.style.display='block'
            elebox.style.position='absolute'
        }
    }
}
function hidebox(boxname)
{
    elebox = $('bubblebox');
    if (elebox)
        elebox.style.display = 'none';
}

function notifyComplete(doit)
{
    if (doit==0)    { return;   }
    if (window.parent.location!=self.location)
    {
        docheight = new Number(110)
        //docheight = document.layers?document.height:document.body.offsetHeight;
        hotcount = new Number(document.dat.hotcount.value);
        stdcount = new Number(document.dat.stdcount.value);
        tabcount = new Number(document.dat.tabcount.value);
        tabsplit = new Number(document.dat.tabsplit.value);
        docheight += hotcount*18;
        if (tabsplit>0)
        {
            if (hotcount<=10)
            {
                docheight += stdcount*49;
            }
            else
            {
                docheight += tabcount*70;
            }
        }
        else
        {
            docheight += tabcount*60;
        }
        window.parent.handleResponse(docheight, hotcount);
    }
    
}

function refreshit()
{

}

function UpdateCurrency(oSelect) {
    if (oSelect.value == "0") {
        // return;
    }
    var currencies = new Array();
    for (var isoCode in CurrencyArray) {
        var cData = CurrencyArray[isoCode];
        currencies[isoCode] = new Currency(
            isoCode, '', cData['Name'], '', cData['Value']
        );
    }
    currencyConverter.convert(currencies, oSelect.value);
}

//--------------------------------------------------------------------------------------------------
    function setCurrency()
    {
        var curr = readCookie("currency");
        if (curr)
        {
            var oSelect = document.getElementById("SelectCurrency");
            oSelect.selectedIndex = curr;
            UpdateCurrency(oSelect);
        }
    }
//--------------------------------------------------------------------------------------------------
	function readCurrency()
	{
		/* 
		 * this is obsoleted, same function (and in action) is in hotel_avail_chart.js
		 */
		var currency = readCookie("lt_currency");
		if (currency == null) return;
		
		var oSelect = document.getElementById("SelectCurrency");
		if (oSelect) {
			oSelect.selectedIndex = currency;
			changeCurrency(oSelect);
		}
		
		// multiple select in ccPromotion page
		var currencyDropDowns = document.getElementsByName("currencySelect");
		if (currencyDropDowns.length > 0) {
			// call to update first select, it will then, update the rest
			var m_select = document.getElementById("SelectCurrency[0]");
			if (!m_select) return;
			m_select.selectedIndex = currency;
			changeMultipleCurrency(0);
		}
	}

//--------------------------------------------------------------------------------------------------
// cookie
//--------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------
    function createCookie(name, value, days)
    {
        if (days)
        {
            var date = new Date();
            date.setTime(date.getTime()+(days*24*60*60*1000));
            var expires = "; expires="+date.toGMTString();
        }
        else var expires = "";

		var domain = window.location.hostname;
		var re = /(.*?)\.?latestays\.(.*)/;
		var d = domain.replace(re, ".latestays.$2");

		var expiry = new Date().toGMTString();
		document.cookie = name+"=" + value + ";" + ";expires=" + expiry + ";path=" + "/;" ;
		
        document.cookie = name+"="+value+expires+"; path=/;domain="+d;
    }
//--------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------
    function readCookie(name)
    {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for(var i=0;i < ca.length;i++)
        {
            var c = ca[i];
            while (c.charAt(0)==' ') c = c.substring(1,c.length);
            if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
        }
        return null;
    }
//--------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------
    function eraseCookie(name)
    {
        createCookie(name,"",-1);
    }
//--------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------
    function addCommas(nStr) {
        nStr += '';
        x = nStr.split('.');
        x1 = x[0];
        x2 = x.length > 1 ? '.' + x[1] : '';
        var rgx = /(\d+)(\d{3})/;
        while (rgx.test(x1)) {
            x1 = x1.replace(rgx, '$1' + ',' + '$2');
        }
        return x1 + x2;
    }
//--------------------------------------------------------------------------------------------------

//*************************************************
// below are script use to move availability chart
//*************************************************

var first_col = 3;
var first_show_col = 3;
var last_show_col = 16;
var last_col = 30;

//--------------------------------------------------------------------------------------------------
function setDisplayDate()
{
    resetMatrix();
    return;
    var oTable = document.getElementById("tblAvailability");
    var oMultiPage = document.getElementById("multiPage");
    
    var startRow = 1;
    var endRow = oTable.rows.length-1;
    
    if (oMultiPage != null)
    {
        if (oMultiPage.value == 1)
        {
            startRow++;
            endRow--;
        }
    }
    
    for (var r=startRow; r<endRow; r++)
    {
        var oRow = oTable.rows[r];
        
        for (var c=first_col; c<first_show_col; c++)
        {
            // hide left most column
            oRow.cells[c].style.display = "none";
        
            // show right most column
            var cl = c+14;
            oRow.cells[cl].style.display = "";
        }
    }
    
    // set show or hide move button
    setMoveButton();
}
//--------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------
function getParameter(name) 
{
    var currentUrl = window.location.search;
    currentUrl = currentUrl.replace('%26','&');
    currentUrl = currentUrl.replace(/%20/g,' ');
    var passed = true;
    if (currentUrl.indexOf('?')==-1)
    {
        passed=false;
    }

    if (passed)
    {
        
        // ake, modified to prevent to get value from similar parameter name
        var begin_str_to_find = '?'+name+'=';
        var strBegin = currentUrl.indexOf(begin_str_to_find)
        if (strBegin == -1)
        {
            begin_str_to_find = '&'+name+'=';
            strBegin = currentUrl.indexOf(begin_str_to_find)
            if (strBegin == -1)
            {
                return "";
            }
        }
        
        strBegin += name.length+2;
        var strEnd = currentUrl.indexOf("&", strBegin);

        if (strEnd==-1)
        {
            strEnd = currentUrl.indexOf("%26", strBegin);
            if (strEnd==-1)
            {
                strEnd = currentUrl.length;
            }
        }

        return currentUrl.substring(strBegin, strEnd);
    }
    else
    {
        return "";
    }
}
//--------------------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------------------
function setDisplayPeriod(sStartDate)
{
    var aStartDate = sStartDate.split("-");
    var dStartDate = new Date();
    
    // month value have to decrease by 1 (0-11)
    aStartDate[1] -= 1;
    
    // set to url parameter
    dStartDate.setFullYear(aStartDate[0], aStartDate[1], aStartDate[2]);
    
    // assume that the first day we show in availability chart is 1 day lead time
    var dTomorrow = new Date();
    var seconds = dTomorrow.getTime();
    
    seconds += 86400000;
    
    dTomorrow.setTime(seconds);
    
    
    // if supplied date before tomorrow do nothing
    if ( dStartDate < dTomorrow )
    {
        return false;
    }
    
    // check period
    var dDiff = Math.abs(Math.round((dStartDate-dTomorrow)/86400000));
    
    // if supplied date greater than 28 days from tomorrow, do nothing
    if ( dDiff > 28 )
    {
        return false;
    }
    
    // if date diff more than 14 days, set it to 14 days (last period)
    if ( dDiff > 14 )
    {
        dDiff = 14;
    }
    
    // now value ok, set the first column to show parameter
    // and call function to set the display period
    first_show_col = dDiff+first_col;
    last_show_col = first_show_col+13;
    setDisplayDate();
    return true;    
}
//--------------------------------------------------

// create cookie to log agent booking
var agentId = getParameter("s");
if (agentId != "")
{
    // agent id supplied, create cookie
    createCookie("source", agentId, 30)
}

//--------------------------------------------------
// GTA
var _DestinationID = "";

/***************** BEGIN : LS Display Goback ****************************/
function displayGoback(objTarget) {
	var referrer = document.referrer;
	var latestaysPos = strpos(referrer, 'latestays.');
	// stristr(referrer ,"latestays");
	if (trim(referrer) != '' && latestaysPos < 20) {
		$('gobackBox').style.display = "";
		$('gobackLink').href = referrer;
	}
}
/***************** END : LS Display Goback ****************************/

/***************** BEGIN LS AVAILCHART BY CALENDAR JS ****************************/
function correctmatrixState() {
	if (!supportStartDate || !supportEndDate) {
		var sDate = new Date();
		supportStartDate = sDate.getFullYear() + padZero(sDate.getMonth()+1) + padZero(sDate.getDate());
		sDate.setDate(sDate.getDate()+90);
		supportEndDate = sDate.getFullYear() + padZero(sDate.getMonth()+1) + padZero(sDate.getDate());
	}
	
	var CheckIn = $('mtx_check_in').value;
	var CheckOut = $('mtx_check_out').value;
	
	var chartDisplay = 14;
	var chartMove = chartDisplay / 2;
	
	var d = getCookieDomain();
	var CheckNights = dateDiff(CheckIn, CheckOut);
	
	if (CheckNights > chartDisplay) {
		var setState = dateDiff(supportStartDate, CheckIn);
		
	} else {
		var startDay = dateDiff(supportStartDate, CheckIn);
		var endDay = dateDiff(supportStartDate, CheckOut);
		var setState = Math.floor(startDay / chartMove) * 7;
		
		if ((endDay) > (setState+chartDisplay)) {
			setState = startDay;
		}
	}
	
	document.cookie = "matrixState=" + setState + ";" + ";path=/;domain="+ d;
	document.cookie = "mtx_check_in=" + dateReformat(mkDateObj(CheckIn), 'Ymd') + ";" + ";path=/;domain="+ d;
	document.cookie = "mtx_check_out=" + dateReformat(mkDateObj(CheckOut), 'Ymd') + ";" + ";path=/;domain="+ d;
}

// ---------------------------------------------------------------------------
// Date Function
// ---------------------------------------------------------------------------
function mkDateObj(val) {
	
	if (stristr(val, '/')) {
		// Transform from "d/m/Y" to date obj.
		// 31/12/2011
		var tmp = explode('/', val);
		var date1D = tmp[0];
		var date1M = (tmp[1] * 1) - 1;
		var date1Y = tmp[2];
	} else if (stristr(val, '-')) {
		// Transform from "Y-m-d" to date obj.
		// 2011-12-31
		var tmp = explode('-', val);
		var date1Y = tmp[0];
		var date1M = (tmp[1] * 1) - 1;
		var date1D = tmp[2];
	} else {
		// Transform from "Ymd" to date obj.
		// 20111231
		var date1Y = val.substring(0,4);
		var date1M = (val.substring(4,6) * 1) - 1;
		var date1D = val.substring(6,8);
	}
	
	/*********************
	var alertTXT = 'Source:'+ val +'\r\n';
	alertTXT += 'Day:'+ date1D +'\r\n';
	alertTXT += 'Month:'+ date1M +'\r\n';
	alertTXT += 'Year:'+ date1Y +'\r\n';
	alert(alertTXT);
	/*********************/
	
	// return as date object
	return new Date(date1Y, date1M, date1D);
}

function calcDay(sDate, tDay) {
	// Calculate date from number of days. 
	// Ex : "d/m/Y" + 2 Days
	// return as date object.
	var one_day = 1000 * 60 * 60 * 24;
	var uDate = mkDateObj(sDate);
	var returnVal = uDate.getTime() + (one_day * tDay);
	return new Date(returnVal);
}

function dateReformat(objDate, format) {
	var uDate = objDate.getDate();
	var uMonth = (objDate.getMonth() * 1) + 1;
	var uYear = objDate.getFullYear();
	var returnVal = "";
	
	if (format == 'Ymd') {
		// Transform date object to date format "Ymd"
		returnVal += uYear;
		
		if (uMonth < 10) { 
			returnVal += "0"+ uMonth; 
		} else {
			returnVal += uMonth;
		}
		
		if (uDate < 10) { 
			returnVal += "0"+ uDate; 
		} else {
			returnVal += uDate;
		}
		
	} else if (format == 'd/m/Y') {
		// Transform date object to date format "d/m/Y"
		if (uDate < 10) { 
			returnVal += "0"+ uDate; 
		} else {
			returnVal += uDate;
		}
		
		if (uMonth < 10) { 
			returnVal += "/0"+ uMonth; 
		} else {
			returnVal += "/"+ uMonth;
		}
		
		returnVal += "/"+ uYear;
		
	} else if (format == 'Y-m-d' || format == 'PHP') {
		// Transform date object to date format "Y-m-d"
		returnVal += uYear;
		
		if (uMonth < 10) { 
			returnVal += "-0"+ uMonth; 
		} else {
			returnVal += "-"+ uMonth;
		}
		
		if (uDate < 10) { 
			returnVal += "-0"+ uDate; 
		} else {
			returnVal += "-"+ uDate;
		}
	}
	
	return returnVal;
}

function dateDiff(date1,date2) {  
	// Calculate number of different day. Source of date is "d/m/Y".
	var d1 = mkDateObj(date1);
	var d2 = mkDateObj(date2);
	var one_day = 1000 * 60 * 60 * 24;
	return Math.ceil((d2.getTime() - d1.getTime()) / (one_day));
}

/***************** END LS AVAILCHART BY CALENDAR JS ****************************/

/***************** BEGIN CURRENCY JS ****************************/


function Currency(isoCode, symbol, name, shortName, relativeRate) {
    this.isoCode      = isoCode;
    this.symbol       = symbol;
    this.name         = name;
    this.shortName    = shortName;
    this.relativeRate = relativeRate;
};

/**
 * A 'class' representing generic currency conversion functionality for deal matrices.
 *
 * Follows a convention based approach for identifying cells that require conversion.
 * Rather than a single synchronous conversion, the approach taken is to split the work required up into
 * logical sections (known henceforth as 'deal blocks') and returning control to the browser momentarily between
 * deal block conversions.
 *
 * The convention is as follows:
 *
 *           _________________________________________________________
 *       ___|______________________________________________________   |
 *   ___|_______________________________________________________   |  |
 *  |                                                           |  |  |
 *  | div: id=currencyGroup                                     |  |  |
 *  |      name=currencyGroup                                   |  |  |
 *  |      isoCode=CODE                                         |  |  |
 *  |      index=indexNumber                                    |  |  |
 *  |                                                           |  |  |
 *  |    ____________________________                           |  |  |
 *  |   | div: name=dealBlock        |                          |  |  |
 *  |   |                            |                          |  |  |
 *  |   | span, name=drc             |                          |  |  |
 *  |   | span, name=drc             |                          |  |  |
 *  |   | span, name=drc             |                          |  |  |
 *  |   |                            |                          |  |  |
 *  |   |____________________________|                          |  |  |
 *  |    ____________________________                           |  |  |
 *  |   | div: name=dealBlock        |                          |  |  |
 *  |   |                            |                          |  |  |
 *  |   | span, name=drc             |                          |  |  |
 *  |   | span, name=drc             |                          |  |  |
 *  |   | span, name=drc             |                          |  |  |
 *  |   |                            |                          |  |__|
 *  |   |____________________________|                          |__|
 *  |___________________________________________________________|
 *
 *
 * Blocks that relate to the same currency are encapsulated in DIV elements with an ID of 'currencyGroup'
 * and a name of 'currencyGroup'. Cells within a 'currencyGroup' are further subdivided into logical units known
 * as 'deal blocks'. These are denoted by DIV elements with a name of 'dealBlock'. Each 'deal block' is processed
 * synchronously. After processing a deal block, the next block is scheduled for processing at a later stage
 * (denoted by the TIME_BETWEEN_DEAL_BLOCKS parameter defined below). This approach is taken so that control can be
 * returned to the browser between conversions, allowing continual response to the user for large pages.
 *
 * Each rate cell within a deal block is expected to contain semi-structured data:
 *
 *   ---> <span name="drc">[currencySymbol]RATE</span>
 *  (the currencySymbol is optional, but cannot contain digits).
 *
 * To provide further flexibility, users of this class can schedule callbacks for various phases in the lifecycle:
 *
 * before each currency group: addPreCurrencyGroupCallback(function(...) { ... } );
 *
 * after each currency group: addPostCurrencyGroupCallback(function(...) { ... } );
 *
 * before performing cell conversions on each deal block: addPreDealBlockCallback(function(...) { ... } );
 *
 * after performing cell conversions on each deal block: addPostDealBlockCallback(function(...) { ... } );
 *
 * after entire conversion: addPostConversionCallback(function() { ... } );
 *
 * These callbacks can be useful in performing various random tasks (i.e. updating messages pertaining to currency
 * codes).
 *
 */
function CurrencyConverter() {
    this.postConversionCallbacks    = new Array();
    this.preCurrencyGroupCallbacks  = new Array();
    this.postCurrencyGroupCallbacks = new Array();
    this.preDealBlockCallbacks      = new Array();
    this.postDealBlockCallbacks     = new Array();
    
    this.currentTimeout = null;
};

// DEFINE 'CLASS' level constants.
CurrencyConverter.prototype.DEAL_RATE_REGEX           = /name="?drc?"?>([^\d]*?)([\d,]+)(:?.|\n)*?<\/[Ss]/g;
CurrencyConverter.prototype.TIME_BETWEEN_DEAL_BLOCKS  = 20;
CurrencyConverter.prototype.CONVERSION_TYPE_SINGLE    = 1;
CurrencyConverter.prototype.CONVERSION_TYPE_MULTI     = 2;
CurrencyConverter.prototype.CURRENCY_CODE_ATTR        = 'isoCode';
CurrencyConverter.prototype.CURRENCY_GROUP_NAME       = 'currencyGroup';
CurrencyConverter.prototype.DEAL_BLOCK_NAME           = 'dealBlock';

/**
 * Specify that the given function should be called when all conversions are complete.
 */
CurrencyConverter.prototype.addPostConversionCallback = function(cb) {
    this.postConversionCallbacks.push(cb);
};

/**
 * Specify that the given function should be called before applying conversions to a currencyGroup DIV.
 *    --> callBack(divElement, fromCurrency, toCurrency, conversionType);
 *
 * divElement     --> the 'currencyGroup' element
 * fromCurrency   --> a Currency object representing the default currency for the group
 * toCurrency     --> a Currency object representing the indicative currency for the group
 * conversionType --> The convserion type
 *                ------> CONVERSION_TYPE_SINGLE (only displaying one currency, i.e. turning off display, or default == indicative)
 *                ------> CONVERSION_TYPE_MULTI  (displaying two currencies in the cell, implies default != indicative)
 */
CurrencyConverter.prototype.addPreCurrencyGroupCallback = function(cb) {
    this.preCurrencyGroupCallbacks.push(cb);
};

/**
 * Specify that the given function should be called after applying conversions to a currencyGroup DIV.
 *    --> callBack(divElement, fromCurrency, toCurrency, conversionType);
 *
 * divElement     --> the 'currencyGroup' element
 * fromCurrency   --> a Currency object representing the default currency for the group
 * toCurrency     --> a Currency object representing the indicative currency for the group
 * conversionType --> The convserion type
 *                ------> CONVERSION_TYPE_SINGLE (only displaying one currency, i.e. turning off display, or default == indicative)
 *                ------> CONVERSION_TYPE_MULTI  (displaying two currencies in the cell, implies default != indicative)
 */
CurrencyConverter.prototype.addPostCurrencyGroupCallback = function(cb) {
    this.preCurrencyGroupCallbacks.push(cb);
};


/**
 * Specify that the given function should be called before applying conversions to a deal block DIV.
 *    --> callBack(divElement, fromCurrency, toCurrency, conversionType);
 *
 * divElement     --> the 'dealBlock' element
 * fromCurrency   --> a Currency object representing the default currency for the current currency group
 * toCurrency     --> a Currency object representing the indicative currency
 * conversionType --> The convserion type
 *                ------> CONVERSION_TYPE_SINGLE (only displaying one currency, i.e. turning off display, or default == indicative)
 *                ------> CONVERSION_TYPE_MULTI  (displaying two currencies in the cell, implies default != indicative)
 */
CurrencyConverter.prototype.addPreDealBlockCallback = function(cb) {
    this.preDealBlockCallbacks.push(cb);
};

/**
 * Specify that the given function should be called after applying conversions to a deal block DIV.
 *    --> callBack(divElement, fromCurrency, toCurrency, conversionType);
 *
 * divElement     --> the 'dealBlock' element
 * fromCurrency   --> a Currency object representing the default currency for the current currency group
 * toCurrency     --> a Currency object representing the indicative currency
 * conversionType --> The convserion type
 *                ------> CONVERSION_TYPE_SINGLE (only displaying one currency, i.e. turning off display, or default == indicative)
 *                ------> CONVERSION_TYPE_MULTI  (displaying two currencies in the cell, implies default != indicative)
 */
CurrencyConverter.prototype.addPostDealBlockCallback = function(cb) {
    this.postDealBlockCallbacks.push(cb);
};

/**
 * Perform a currency conversion:
 *
 * currencies is a mapping of isoCode --> Currency objects.
 *
 * indicativeCurrency is the ISO code of the currency to convert to.
 */
CurrencyConverter.prototype.convert = function(currencies, indicativeCurrency) {
    //console.log("Converting...");
    if (this.currentTimeout != null) {
        window.clearTimeout(this.currentTimeout);
    }
    var scopedThis          = this;
    this.turningOff         = false;
    this.longRatePresent    = false;
    this.currencies         = new CloneCurrencyList(currencies);
    //console.log(this.currencies);
    this.indicativeCurrency = this.currencies[new String(indicativeCurrency)];
    //console.log(this.indicativeCurrency);
    this.currencyGroups     = this.findCurrencyGroups();
    this.currencyGroupNum   = 0;
    this.currentTimeout = window.setTimeout(function () { scopedThis.convertCurrencyGroup(); }, 1);
};

/**
 * Turn off any conversions that are currently applied.
 */
CurrencyConverter.prototype.turnOff = function() {
    if (this.currentTimeout != null) {
        window.clearTimeout(this.currentTimeout);
    }
    var scopedThis          = this;
    this.longRatePresent    = false;
    this.turningOff         = true;
    this.indicativeCurrency = null;
    this.currencyGroups     = this.findCurrencyGroups();
    this.currencyGroupNum   = 0;
    if(this.currencies) {
        /* Dont need to turn off in this case as nothing was turned on */
        this.currentTimeout = window.setTimeout(function () { scopedThis.convertCurrencyGroup(); }, 1);
    }
};

/**
 * Internal function for converting a currency group.
 */
CurrencyConverter.prototype.convertCurrencyGroup = function() {
    //console.log("Converting currency group...");
    if (this.currencyGroupNum < this.currencyGroups.length) {
        //console.log("Need to convert more groups...");
        var scopedThis       = this;
        var currencyGroup    = this.currencyGroups.item(this.currencyGroupNum++);
        this.currencyGroup   = currencyGroup;
        this.defaultCurrency = this.currencies[currencyGroup.getAttribute(this.CURRENCY_CODE_ATTR)];
        this.conversionType  = this.determineConversionType();
        this.conversionFunc  = this.determineConversionFunc();
        this.dealBlocks      = this.findDealBlocks(currencyGroup);
        this.dealBlockNum    = 0;
        this.fireCallbacks(currencyGroup, this.preCurrencyGroupCallbacks);
        this.currentTimeout = window.setTimeout(function() { scopedThis.convertDealBlock(); }, 1);
        //console.log("Waiting for deal block timeout...");
    } else {
        for (var callbackIndex = 0; callbackIndex < this.postConversionCallbacks.length; callbackIndex++) {
            this.postConversionCallbacks[callbackIndex]();
        }
    }
};

/**
 * Internal function for converting a deal block.
 */
CurrencyConverter.prototype.convertDealBlock = function() {
    //console.log("Converting deal block...");
    var scopedThis = this;
    if (this.dealBlockNum < this.dealBlocks.length) {
        // change this deal block and schedule the next one
        var dealBlock = this.dealBlocks[this.dealBlockNum++];
        this.fireCallbacks(dealBlock, this.preDealBlockCallbacks);
        dealBlock.innerHTML = dealBlock.innerHTML.replace(this.DEAL_RATE_REGEX, function (match, symbol, rate) {
            return scopedThis.conversionFunc(match, symbol, rate);
        });
        this.fireCallbacks(dealBlock, this.postDealBlockCallbacks);

        this.currentTimeout = window.setTimeout(function() { scopedThis.convertDealBlock(); }, this.TIME_BETWEEN_DEAL_BLOCKS);
    } else {
        // next currency block
        this.fireCallbacks(this.currencyGroup, this.postCurrencyGroupCallbacks);
        this.currentTimeout = window.setTimeout(function() { scopedThis.convertCurrencyGroup(); }, 1);
    }
};

/**
 * Rate cell conversion function for displaying a single rate.
 */
CurrencyConverter.prototype.showOneCurrency = function(match, symbol, rate) {
    //console.log("Show one called!");
    if (rate.length + symbol.length >= 5) {
        this.longRatePresent = true;
    }
    return 'name="drc">' + symbol + rate + '</s';
};

/**
 * Rate cell conversion function for displaying the indicative rate as well as the default rate
 */
CurrencyConverter.prototype.showBothCurrencies = function(match, symbol, rate) {
    //console.log("Show both called!");
    var indicativeSymbol = symbol == '' ? '' : this.indicativeCurrency.shortName;
    var amountInt = convertCurrency(rate, this.defaultCurrency.relativeRate, this.indicativeCurrency.relativeRate);
    if (rate.length + symbol.length >= 5 || amountInt.length + indicativeSymbol.length >=5) {
        this.longRatePresent = true;
    }
    var klass = "cc";
    if (amountInt.length >= 7) {
      klass = "ccs1";
    }
    if (amountInt.length >= 10) {
      klass = "ccs2";
    }
    return 'name="drc">' + symbol + rate + '<br/><font class="' + klass + '">' + indicativeSymbol + amountInt + '</font></s';
};

/**
 * Internal function for determining what type of conversion is being performed currently:
 * - single, or
 * - multi
 */
CurrencyConverter.prototype.determineConversionType = function() {
	if (!this.indicativeCurrency) {
		return this.CONVERSION_TYPE_SINGLE;
	}
    if (this.turningOff || (this.indicativeCurrency.isoCode == this.defaultCurrency.isoCode)) {
        return this.CONVERSION_TYPE_SINGLE;
    }
    return this.CONVERSION_TYPE_MULTI;
};

/**
 * Internal function for determining which function to use for converting deal cells.
 */
CurrencyConverter.prototype.determineConversionFunc = function() {
    if (this.conversionType == this.CONVERSION_TYPE_SINGLE) {
        return this.showOneCurrency;
    } else {
        return this.showBothCurrencies;
    }
};

/**
 * Internal function for finding all currency groups.
 */
CurrencyConverter.prototype.findCurrencyGroups = function() {
    return document.getElementsByName(this.CURRENCY_GROUP_NAME);
};

/**
 * Internal function for finding all deal blocks inside a currency group.
 */
CurrencyConverter.prototype.findDealBlocks = function(currencyGroup) {
    return document.getElementsByName("dealBlock");
    /*var divs = currencyGroup.getElementsByTagName("div");
    var dealBlocks = new Array();
    for (var divNum = 0; divNum < divs.length; divNum++) {
        var div = divs.item(divNum);
        if (div.getAttribute('name') == this.DEAL_BLOCK_NAME) {
            dealBlocks.push(div);
        }
    }
    return dealBlocks;*/
};

/**
 * Internal function for calling all callbacks for a div based on the given callback array.
 */
CurrencyConverter.prototype.fireCallbacks = function(divElement, callbackArray) {
    for (var callbackIndex = 0; callbackIndex < callbackArray.length; callbackIndex++) {
        callbackArray[callbackIndex](divElement, this.defaultCurrency, this.indicativeCurrency, this.conversionType);
    }
};

/**
 * Switch the css classes for all 'elementName' elements under 'rootElement' that have a
 * className of 'fromClass' to 'toClass'.
 */
function switchClasses(rootElement, elementName, fromClass, toClass) {
    var childNodes = rootElement.getElementsByTagName(elementName);
    for (var childIndex = 0; childIndex < childNodes.length; childIndex++) {
        var childNode = childNodes.item(childIndex);
        if (childNode.className == fromClass) {
            childNode.className = toClass;
        }
    }
}

function CloneCurrencyList(source) {
    for (var field in source) {
        var c = source[field];
        this[new String(field)] = new Currency(
                new String(c.isoCode), new String(c.symbol), new String(c.name), new String(c.shortName), parseFloat(c.relativeRate));
    }
}

function convertCurrency(amount, fromRate, toRate) {
    if (amount == "n/a") { amount; }
    return addCommas(new String(parseInt((parseInt(amount.replace(',', '')) / toRate) * fromRate)));
}

var currencyConverter = new CurrencyConverter();

currencyConverter.addPreCurrencyGroupCallback(function(divElement, fromCurrency, toCurrency, conversionType) {
    document.getElementById("currencyGroup").className = (conversionType == CurrencyConverter.prototype.CONVERSION_TYPE_MULTI) ? "twoCurrency" : "";    
});

currencyConverter.addPostDealBlockCallback(function (dealBlock, from, to, conversionType) {
    var dropDowns = dealBlock.getElementsByTagName("select");
    if (dropDowns.length == 1 && to) {
        var dropDown = dropDowns[0];

        for (var i = 0; i < dropDown.length; i++) {
            if (dropDown.options[i].value == to.isoCode) {
                dropDown.selectedIndex = i;
                return;
            }
        }
    }
});

/***************** END CURRENCY JS ******************************/

function gotoDate() {
	jQuery(function($) {
		var inDate = $("#check_in_date").datepicker("getDate");
		var outDate = $("#check_out_date").datepicker("getDate");
		
		if (inDate==null || outDate==null) {
			// no date selected
			return;
		}
		
		dest_a_class.checkIn = inDate.getFullYear() + "" + padZero(inDate.getMonth()+1) + "" + padZero(inDate.getDate()) ;
		dest_a_class.checkOut = outDate.getFullYear() + "" + padZero(outDate.getMonth()+1) + "" + padZero(outDate.getDate()) ;
		
		var toDay = new Date();
		var period = Math.floor((outDate-inDate)/(24*3600*1000));
		
		var diff_in = Math.ceil((inDate-toDay)/(24*3600*1000));
		var move = Math.floor(diff_in/dest_a_class.matrixMoveBy);
		
		// display window
		var start = dest_a_class.matrixMoveBy*move;
		var end = start+dest_a_class.matrixDisplay;
		
		if (end>90) {
			start -= end-90;
			end -= end-90;
		}
		
		var padding_left = diff_in-start;
		var pading_right = end-(diff_in+period);
		if (start>0 && diff_in==start && end-dest_a_class.matrixMoveBy-(diff_in+period)>0) {
			start -= dest_a_class.matrixMoveBy;
		}
		dest_a_class.matrixState = start;
		
		dest_a_class.setCookie(dest_a_class.CHECK_IN_COOKIE, dest_a_class.checkIn, dest_a_class.COOKIE_EXPIRY);
		dest_a_class.setCookie(dest_a_class.CHECK_OUT_COOKIE, dest_a_class.checkOut, dest_a_class.COOKIE_EXPIRY);
		
		dest_a_class.load_avail_chart(0);
	});
}

//------------------------------------------------------------------------------
//calendar script
//------------------------------------------------------------------------------
function padZero(num) {
	return (num< 10) ? '0' + num : num ;
}

function updateNightsSelected(nights) {
	var n = $('num_nights');
	var max_val = parseInt(n.options[n.options.length-1].value,10);
	if (max_val >= nights) {
		n.value = nights;
	} else {
		// we don't have this number yet
		for (var i=max_val+1; i<=nights; i++) {
			var o = new Option(i, i);
			if (i == nights) {
				o.selected = "selected";
			}
			n.options[n.options.length] = o;
		}
	}
}

function synchronizeCalendar(languageCode) {
	
	if ($('calendarStartDate')) {
		var tday = new Date();
		var destinationDate = $('calendarStartDate').value;
		var machineDate = tday.getFullYear() +"-"+ (tday.getMonth() + 1) +"-"+ tday.getDate();
		var calendarStartDate = dateDiff(machineDate,destinationDate);
		// alert(machineDate +' VS '+ destinationDate);
		// alert(calendarStartDate);
	} else {
		var calendarStartDate = 0;
	}
	
	jQuery(function($) {
		$.datepicker.setDefaults( $.datepicker.regional[ languageCode ]);
		var period = $("#check_in_date, #check_out_date").datepicker({
		   //dateFormat: "D d M yy",
		   minDate: calendarStartDate,
		   maxDate: "+90d",
		   onSelect: function(selectedDate) {
			   var option = this.id == "check_in_date" ? "minDate" : "maxDate",
					instance = $( this ).data( "datepicker" ),
					date = $.datepicker.parseDate(
						instance.settings.dateFormat ||
						$.datepicker._defaults.dateFormat,
						selectedDate, instance.settings );
			   
			   // not allow same date
			   if (this.id=="check_in_date") {
				   date.setDate(date.getDate()+1);
			   } else {
				   date.setDate(date.getDate()-1);
			   }
			   period.not( this ).datepicker( "option", option, date );
			   calDateChanges(this);
		   }
	   });
		
		$("#check_in_date").datepicker( "option", "altField", '#mtx_check_in' );
		$("#check_in_date").datepicker( "option", "altFormat", 'dd/mm/yy' );
		$("#check_out_date").datepicker( "option", "altField", '#mtx_check_out' );
		$("#check_out_date").datepicker( "option", "altFormat", 'dd/mm/yy' );
		
		var s_in = readCookie("mtx_check_in");
		var s_out = readCookie("mtx_check_out");
		if (s_in && s_in.length==8 && s_out && s_out.length==8) {
			var inDate = new Date(parseInt(s_in.substr(0, 4),10), parseInt(s_in.substr(4, 2),10)-1, parseInt(s_in.substr(6, 2),10));
			var outDate = new Date(parseInt(s_out.substr(0, 4),10), parseInt(s_out.substr(4, 2),10)-1, parseInt(s_out.substr(6, 2),10));
			
			$("#check_in_date").datepicker("setDate", inDate);
			$("#check_out_date").datepicker("setDate", outDate);
			var days = (outDate.getTime()-inDate.getTime())/(24*3600*1000);
			updateNightsSelected(days);
		}
	});
}

function calDateChanges(dp) {
	jQuery(function($) {
		var nd = new Date();
		var today = new Date(nd.getFullYear(), nd.getMonth(), nd.getDate());
		if (dp.id=="check_in_date" || dp.id=="num_nights") {
			var selectedDate = $("#check_in_date").datepicker("getDate");
			
			if (!selectedDate) return;
			
			// not allow more than 90 days
			if ((selectedDate.getTime()-today.getTime())/(24*3600*1000)>=89) {
				var new_date = new Date(today.getTime());
				new_date.setDate(new_date.getDate()+89);
				$("#check_in_date").datepicker("setDate", new_date);
				updateNightsSelected(1);
			}
			
			var new_date = new Date(selectedDate.getTime());
			new_date.setDate(new_date.getDate()+parseInt($("#num_nights").val(),10));
			
			if ((new_date.getTime()-today.getTime())/(24*3600*1000)>90) {
				var max_date = new Date(today.getTime());
				max_date.setDate(max_date.getDate()+90);
				var nights = (max_date.getTime()-selectedDate.getTime())/(24*3600*1000);
				updateNightsSelected(nights);
			} else {
				$("#check_out_date").datepicker("setDate", new_date);
			}
		} else if (dp.id == "check_out_date") {
			var outDate = $("#check_out_date").datepicker("getDate");
			var inDate = $("#check_in_date").datepicker("getDate");
			if (inDate) {
				var days = (outDate.getTime()-inDate.getTime())/(24*3600*1000);
				updateNightsSelected(days);
			} else {
				var new_date = new Date(outDate.getTime());
				new_date.setDate(new_date.getDate()-parseInt($("#num_nights").val(),10));
				var today = new Date();
				var check_date = new Date(today.getFullYear(), today.getMonth(), today.getDate());
				if (new_date<check_date) {
					new_date = check_date;
					$("#check_in_date").datepicker("setDate", new_date);
					var nights = (outDate.getTime()-new_date.getTime())/(24*3600*1000);
					updateNightsSelected(nights);
				} else {
					$("#check_in_date").datepicker("setDate", new_date);
				}
			}
		}
	});
}

//-------------------------------------------------------------------------------------------------------------------
//FROM php.JS
//-------------------------------------------------------------------------------------------------------------------

function substr( f_string, f_start, f_length ) {
	// Returns part of a string  
	// 
	// version: 810.1317
	// discuss at: http://phpjs.org/functions/substr
	// +     original by: Martijn Wieringa
	// +     bugfixed by: T.Wild
	// +      tweaked by: Onno Marsman
	// *       example 1: substr('abcdef', 0, -1);
	// *       returns 1: 'abcde'
	// *       example 2: substr(2, 0, -6);
	// *       returns 2: ''
	f_string += '';

	if(f_start < 0) {
		f_start += f_string.length;
	}

	if(f_length == undefined) {
		f_length = f_string.length;
	} else if(f_length < 0){
		f_length += f_string.length;
	} else {
		f_length += f_start;
	}

	if(f_length < f_start) {
		f_length = f_start;
	}

	return f_string.substring(f_start, f_length);
}

function stristr( haystack, needle, bool ) {
 // Finds first occurrence of a string within another, case insensitive  
 // 
 // version: 810.1317
 // discuss at: http://phpjs.org/functions/stristr
 // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // +   bugfxied by: Onno Marsman
 // *     example 1: stristr('Kevin van Zonneveld', 'Van');
 // *     returns 1: 'van Zonneveld'
 // *     example 2: stristr('Kevin van Zonneveld', 'VAN', true);
 // *     returns 2: 'Kevin '
 var pos = 0;

 haystack += '';
 pos = haystack.toLowerCase().indexOf( (needle+'').toLowerCase() );
 if( pos == -1 ){
     return false;
 } else{
     if( bool ){
         return haystack.substr( 0, pos );
     } else{
         return haystack.slice( pos );
     }
 }
}

function explode( delimiter, string, limit ) {
 // Splits a string on string separator and return array of components. If limit is positive only limit number of components is returned. If limit is negative all components except the last abs(limit) are returned.  
 // 
 // version: 810.114
 // discuss at: http://phpjs.org/functions/explode
 // +     original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // +     improved by: kenneth
 // +     improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // +     improved by: d3x
 // +     bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // *     example 1: explode(' ', 'Kevin van Zonneveld');
 // *     returns 1: {0: 'Kevin', 1: 'van', 2: 'Zonneveld'}
 // *     example 2: explode('=', 'a=bc=d', 2);
 // *     returns 2: ['a', 'bc=d']

 var emptyArray = { 0: '' };
 
 // third argument is not required
 if ( arguments.length < 2
     || typeof arguments[0] == 'undefined'
     || typeof arguments[1] == 'undefined' )
 {
     return null;
 }

 if ( delimiter === ''
     || delimiter === false
     || delimiter === null )
 {
     return false;
 }

 if ( typeof delimiter == 'function'
     || typeof delimiter == 'object'
     || typeof string == 'function'
     || typeof string == 'object' )
 {
     return emptyArray;
 }

 if ( delimiter === true ) {
     delimiter = '1';
 }
 
 if (!limit) {
     return string.toString().split(delimiter.toString());
 } else {
     // support for limit argument
     var splitted = string.toString().split(delimiter.toString());
     var partA = splitted.splice(0, limit - 1);
     var partB = splitted.join(delimiter.toString());
     partA.push(partB);
     return partA;
 }
}

function strpos (haystack, needle, offset) {
 // Finds position of first occurrence of a string within another  
 // 
 // version: 1103.1210
 // discuss at: http://phpjs.org/functions/strpos
 // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // +   improved by: Onno Marsman    
 // +   bugfixed by: Daniel Esteban
 // +   improved by: Brett Zamir (http://brett-zamir.me)
 // *     example 1: strpos('Kevin van Zonneveld', 'e', 5);
 // *     returns 1: 14
 var i = (haystack + '').indexOf(needle, (offset || 0));
 return i === -1 ? false : i;
}

function strlen (string) {
 // Get string length  
 // 
 // version: 901.1520
 // discuss at: http://phpjs.org/functions/strlen
 // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // +   improved by: Sakimori
 // +      input by: Kirk Strobeck
 // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // +   bugfixed by: Onno Marsman
 // +    revised by: Brett Zamir
 // %        note 1: May look like overkill, but in order to be truly faithful to handling all Unicode
 // %        note 1: characters and to this function in PHP which does not count the number of bytes
 // %        note 1: but counts the number of characters, something like this is really necessary.
 // *     example 1: strlen('Kevin van Zonneveld');
 // *     returns 1: 19
 // *     example 2: strlen('A\ud87e\udc04Z');
 // *     returns 2: 3
 var str = string+'';
 var i = 0, chr = '', lgth = 0;

 var getWholeChar = function (str, i) {
     var code = str.charCodeAt(i);
     var next = '', prev = '';
     if (0xD800 <= code && code <= 0xDBFF) { // High surrogate(could change last hex to 0xDB7F to treat high private surrogates as single characters)
         if (str.length <= (i+1))  {
             throw 'High surrogate without following low surrogate';
         }
         next = str.charCodeAt(i+1);
         if (0xDC00 > next || next > 0xDFFF) {
             throw 'High surrogate without following low surrogate';
         }
         return str[i]+str[i+1];
     } else if (0xDC00 <= code && code <= 0xDFFF) { // Low surrogate
         if (i === 0) {
             throw 'Low surrogate without preceding high surrogate';
         }
         prev = str.charCodeAt(i-1);
         if (0xD800 > prev || prev > 0xDBFF) { //(could change last hex to 0xDB7F to treat high private surrogates as single characters)
             throw 'Low surrogate without preceding high surrogate';
         }
         return false; // We can pass over low surrogates now as the second component in a pair which we have already processed
     }
     return str[i];
 };

 for (i=0, lgth=0; i < str.length; i++) {
     if ((chr = getWholeChar(str, i)) === false) {
         continue;
     } // Adapt this line at the top of any loop, passing in the whole string and the current iteration and returning a variable to represent the individual character; purpose is to treat the first part of a surrogate pair as the whole character and then ignore the second part
     lgth++;
 }
 return lgth;
}

function str_replace(search, replace, subject) {
 // Replaces all occurrences of search in haystack with replace  
 // 
 // version: 812.1017
 // discuss at: http://phpjs.org/functions/str_replace
 // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // +   improved by: Gabriel Paderni
 // +   improved by: Philip Peterson
 // +   improved by: Simon Willison (http://simonwillison.net)
 // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
 // +   bugfixed by: Anton Ongson
 // +      input by: Onno Marsman
 // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // +    tweaked by: Onno Marsman
 // *     example 1: str_replace(' ', '.', 'Kevin van Zonneveld');
 // *     returns 1: 'Kevin.van.Zonneveld'
 // *     example 2: str_replace(['{name}', 'l'], ['hello', 'm'], '{name}, lars');
 // *     returns 2: 'hemmo, mars'
 var f = search, r = replace, s = subject;
 var ra = r instanceof Array, sa = s instanceof Array, f = [].concat(f), r = [].concat(r), i = (s = [].concat(s)).length;

 while (j = 0, i--) {
     if (s[i]) {
         while (s[i] = (s[i]+'').split(f[j]).join(ra ? r[j] || "" : r[0]), ++j in f){};
     }
 };

 return sa ? s : s[0];
}

function is_array(input) {
	return typeof(input)=='object'&&(input instanceof Array);
}

function sizeof ( mixed_var, mode ) {
 // !No description available for sizeof. @php.js developers: Please update the function summary text file.
 // 
 // version: 810.114
 // discuss at: http://phpjs.org/functions/sizeof
 // +   original by: Philip Peterson
 // -    depends on: count
 // *     example 1: sizeof([[0,0],[0,-4]], 'COUNT_RECURSIVE');
 // *     returns 1: 6
 // *     example 2: sizeof({'one' : [1,2,3,4,5]}, 'COUNT_RECURSIVE');
 // *     returns 2: 6
	
	return (mixed_var.length - 1);
	
 // return count( mixed_var, mode );
}

function count( mixed_var, mode ) {
 // Count the number of elements in a variable (usually an array)  
 // 
 // version: 812.316
 // discuss at: http://phpjs.org/functions/count
 // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // +      input by: Waldo Malqui Silva
 // *     example 1: count([[0,0],[0,-4]], 'COUNT_RECURSIVE');
 // *     returns 1: 6
 // *     example 2: count({'one' : [1,2,3,4,5]}, 'COUNT_RECURSIVE');
 // *     returns 2: 6
 var key, cnt = 0;

 if( mode == 'COUNT_RECURSIVE' ) mode = 1;
 if( mode != 1 ) mode = 0;

 for (key in mixed_var){
     cnt++;
     if( mode==1 && mixed_var[key] && (mixed_var[key].constructor === Array || mixed_var[key].constructor === Object) ){
         cnt += count(mixed_var[key], 1);
     }
 }

 return cnt;
}

function trim (str, charlist) {
 // Strips whitespace from the beginning and end of a string  
 // 
 // version: 812.316
 // discuss at: http://phpjs.org/functions/trim
 // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // +   improved by: mdsjack (http://www.mdsjack.bo.it)
 // +   improved by: Alexander Ermolaev (http://snippets.dzone.com/user/AlexanderErmolaev)
 // +      input by: Erkekjetter
 // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // +      input by: DxGx
 // +   improved by: Steven Levithan (http://blog.stevenlevithan.com)
 // +    tweaked by: Jack
 // +   bugfixed by: Onno Marsman
 // *     example 1: trim('    Kevin van Zonneveld    ');
 // *     returns 1: 'Kevin van Zonneveld'
 // *     example 2: trim('Hello World', 'Hdle');
 // *     returns 2: 'o Wor'
 // *     example 3: trim(16, 1);
 // *     returns 3: 6
 var whitespace, l = 0, i = 0;
 str += '';
 
 if (!charlist) {
     // default list
     whitespace = " \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000";
 } else {
     // preg_quote custom list
     charlist += '';
     whitespace = charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '\$1');
 }
 
 l = str.length;
 for (i = 0; i < l; i++) {
     if (whitespace.indexOf(str.charAt(i)) === -1) {
         str = str.substring(i);
         break;
     }
 }
 
 l = str.length;
 for (i = l - 1; i >= 0; i--) {
     if (whitespace.indexOf(str.charAt(i)) === -1) {
         str = str.substring(0, i + 1);
         break;
     }
 }
 
 return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
}

function number_format( number, decimals, dec_point, thousands_sep ) {
 // Formats a number with grouped thousands  
 // 
 // version: 902.1517
 // discuss at: http://phpjs.org/functions/number_format
 // +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
 // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // +     bugfix by: Michael White (http://getsprink.com)
 // +     bugfix by: Benjamin Lupton
 // +     bugfix by: Allan Jensen (http://www.winternet.no)
 // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
 // +     bugfix by: Howard Yeend
 // +    revised by: Luke Smith (http://lucassmith.name)
 // +     bugfix by: Diogo Resende
 // +     bugfix by: Rival
 // %        note 1: For 1000.55 result with precision 1 in FF/Opera is 1,000.5, but in IE is 1,000.6
 // *     example 1: number_format(1234.56);
 // *     returns 1: '1,235'
 // *     example 2: number_format(1234.56, 2, ',', ' ');
 // *     returns 2: '1 234,56'
 // *     example 3: number_format(1234.5678, 2, '.', '');
 // *     returns 3: '1234.57'
 // *     example 4: number_format(67, 2, ',', '.');
 // *     returns 4: '67,00'
 // *     example 5: number_format(1000);
 // *     returns 5: '1,000'
 // *     example 6: number_format(67.311, 2);
 // *     returns 6: '67.31'
 var n = number, prec = decimals;
 n = !isFinite(+n) ? 0 : +n;
 prec = !isFinite(+prec) ? 0 : Math.abs(prec);
 var sep = (typeof thousands_sep == "undefined") ? ',' : thousands_sep;
 var dec = (typeof dec_point == "undefined") ? '.' : dec_point;

 var s = (prec > 0) ? n.toFixed(prec) : Math.round(n).toFixed(prec); //fix for IE parseFloat(0.55).toFixed(0) = 0;

 var abs = Math.abs(n).toFixed(prec);
 var _, i;

 if (abs >= 1000) {
     _ = abs.split(/\D/);
     i = _[0].length % 3 || 3;

     _[0] = s.slice(0,i + (n < 0)) +
           _[0].slice(i).replace(/(\d{3})/g, sep+'$1');

     s = _.join(dec);
 } else {
     s = s.replace('.', dec);
 }

 return s;
}

function sprintf( ) {
 // Return a formatted string  
 // 
 // version: 812.316
 // discuss at: http://phpjs.org/functions/sprintf
 // +   original by: Ash Searle (http://hexmen.com/blog/)
 // + namespaced by: Michael White (http://getsprink.com)
 // +    tweaked by: Jack
 // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // +      input by: Paulo Ricardo F. Santos
 // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // *     example 1: sprintf("%01.2f", 123.1);
 // *     returns 1: 123.10
 // *     example 2: sprintf("[%10s]", 'monkey');
 // *     returns 2: '[    monkey]'
 // *     example 3: sprintf("[%'#10s]", 'monkey');
 // *     returns 3: '[####monkey]'
 var regex = /%%|%(\d+\$)?([-+\'#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuidfegEG])/g;
 var a = arguments, i = 0, format = a[i++];

 // pad()
 var pad = function(str, len, chr, leftJustify) {
     if (!chr) chr = ' ';
     var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr);
     return leftJustify ? str + padding : padding + str;
 };

 // justify()
 var justify = function(value, prefix, leftJustify, minWidth, zeroPad, customPadChar) {
     var diff = minWidth - value.length;
     if (diff > 0) {
         if (leftJustify || !zeroPad) {
             value = pad(value, minWidth, customPadChar, leftJustify);
         } else {
             value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length);
         }
     }
     return value;
 };

 // formatBaseX()
 var formatBaseX = function(value, base, prefix, leftJustify, minWidth, precision, zeroPad) {
     // Note: casts negative numbers to positive ones
     var number = value >>> 0;
     prefix = prefix && number && {'2': '0b', '8': '0', '16': '0x'}[base] || '';
     value = prefix + pad(number.toString(base), precision || 0, '0', false);
     return justify(value, prefix, leftJustify, minWidth, zeroPad);
 };

 // formatString()
 var formatString = function(value, leftJustify, minWidth, precision, zeroPad, customPadChar) {
     if (precision != null) {
         value = value.slice(0, precision);
     }
     return justify(value, '', leftJustify, minWidth, zeroPad, customPadChar);
 };

 // finalFormat()
 var doFormat = function(substring, valueIndex, flags, minWidth, _, precision, type) {
     if (substring == '%%') return '%';

     // parse flags
     var leftJustify = false, positivePrefix = '', zeroPad = false, prefixBaseX = false, customPadChar = ' ';
     var flagsl = flags.length;
     for (var j = 0; flags && j < flagsl; j++) switch (flags.charAt(j)) {
         case ' ': positivePrefix = ' '; break;
         case '+': positivePrefix = '+'; break;
         case '-': leftJustify = true; break;
         case "'": customPadChar = flags.charAt(j+1); break;
         case '0': zeroPad = true; break;
         case '#': prefixBaseX = true; break;
     }

     // parameters may be null, undefined, empty-string or real valued
     // we want to ignore null, undefined and empty-string values
     if (!minWidth) {
         minWidth = 0;
     } else if (minWidth == '*') {
         minWidth = +a[i++];
     } else if (minWidth.charAt(0) == '*') {
         minWidth = +a[minWidth.slice(1, -1)];
     } else {
         minWidth = +minWidth;
     }

     // Note: undocumented perl feature:
     if (minWidth < 0) {
         minWidth = -minWidth;
         leftJustify = true;
     }

     if (!isFinite(minWidth)) {
         throw new Error('sprintf: (minimum-)width must be finite');
     }

     if (!precision) {
         precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : void(0);
     } else if (precision == '*') {
         precision = +a[i++];
     } else if (precision.charAt(0) == '*') {
         precision = +a[precision.slice(1, -1)];
     } else {
         precision = +precision;
     }

     // grab value using valueIndex if required?
     var value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++];

     switch (type) {
         case 's': return formatString(String(value), leftJustify, minWidth, precision, zeroPad, customPadChar);
         case 'c': return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad);
         case 'b': return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
         case 'o': return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
         case 'x': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
         case 'X': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad).toUpperCase();
         case 'u': return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
         case 'i':
         case 'd': {
             var number = parseInt(+value);
             var prefix = number < 0 ? '-' : positivePrefix;
             value = prefix + pad(String(Math.abs(number)), precision, '0', false);
             return justify(value, prefix, leftJustify, minWidth, zeroPad);
         }
         case 'e':
         case 'E':
         case 'f':
         case 'F':
         case 'g':
         case 'G': {
             var number = +value;
             var prefix = number < 0 ? '-' : positivePrefix;
             var method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())];
             var textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];
             value = prefix + Math.abs(number)[method](precision);
             return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform]();
         }
         default: return substring;
     }
 };

 return format.replace(regex, doFormat);
}

function array_keys (input, search_value, argStrict) {
 // Return just the keys from the input array, optionally only for the specified search_value  
 // 
 // version: 1103.1210
 // discuss at: http://phpjs.org/functions/array_keys    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // +      input by: Brett Zamir (http://brett-zamir.me)
 // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
 // +   improved by: jd
 // +   improved by: Brett Zamir (http://brett-zamir.me)    // *     example 1: array_keys( {firstname: 'Kevin', surname: 'van Zonneveld'} );
 // *     returns 1: {0: 'firstname', 1: 'surname'}
 var search = typeof search_value !== 'undefined',
     tmp_arr = [],
     strict = !!argStrict,        include = true,
     key = '';

 for (key in input) {
     if (input.hasOwnProperty(key)) {            include = true;
         if (search) {
             if (strict && input[key] !== search_value) {
                 include = false;
             }                else if (input[key] != search_value) {
                 include = false;
             }
         }
          if (include) {
             tmp_arr[tmp_arr.length] = key;
         }
     }
 } 
 return tmp_arr;
}

function calcDays(date1, date2) {
	// var date1 = document.getElementById('d1').lastChild.data;
	// var date2 = document.getElementById('d2').lastChild.data;
	date1 = date1.split("-");
	date2 = date2.split("-");
	var sDate = new Date(date1[0]+"/"+date1[1]+"/"+date1[2]);
	var eDate = new Date(date2[0]+"/"+date2[1]+"/"+date2[2]);
	var daysApart = Math.abs(Math.round((sDate-eDate)/86400000));
	// document.getElementById('diffDays').lastChild.data = daysApart;
	return daysApart;
}

//end phpJS

