﻿// scripts/common.js
/*---------------------------------------------------------------------------------------*/

// Console.WriteLine(".....Original Html......");

// The stated purpose of XMLHttpRequest is indicated by its name. It loads an XML file from a server using HTTP. 
// However, it can be used to load any kind of file, including a .js file containing JavaScript code. 
// Pass the loaded code to eval(), and it's ready to be called.


/*---------------------------------------------------------------------------------------*/
// frame buster
if (self.location != top.location) { top.location = self.location; }


/*---------------------------------------------------------------------------------------*/
// global variables

var useAjax = false;

var defaultCurrency = '$';

var defaultLanguge = 'en';
//var defaultLocale = 'en_AU'; ??


var mainmapObject = find_object('mainmap');

var mainmapOverlay = find_object('mainmapoverlay');

//var mainmapOverlayLoadingContent = document.getElementById('mainmapoverlaycontent').innerHTML;


var overlay = find_object('overlay');

var overlayContentWrapper = find_object('overlaycontentwrapper');

var overlayContent = find_object('overlaycontent');

var overlayLoadingContent = document.getElementById('overlaycontent').innerHTML;


var showSmallMap = false;


/*---------------------------------------------------------------------------------------*/
// function init_main()

function init_main() {
		
	document.name = 'mainwindow';
	
	// load topjumpmenuform into topjumpmenu div
	load_topjumpmenu();
	
	// show_mainmapoverlay();
	
	// init_links();
	
	// init_tocstring_events();
	
	// modify_placeslist('contract');
	
	// preload_common_images();
	
}

/*---------------------------------------------------------------------------------------*/
// function set_path()
// sets absolute path to site root
// TODO: use location object ??
// console.log(location.hostname);

function set_path() {
	
	var filesRoot = '';
	
	if (location.hostname == 'www.alltravels.com') {		
		filesRoot = 'http://www.alltravels.com';	
	}
	
	else {
		filesRoot = 'http://localhost/1_Travel/AllTravels/site';
	}
	
	return filesRoot;
	
}


/*---------------------------------------------------------------------------------------*/
// function find_object()
// returns the object with the passed objId string
function find_object(objId) {
	
	return document.getElementById(objId);
	
}


/*---------------------------------------------------------------------------------------*/
// function find_position()
// finds out where an element object is on the page
// accepts either an object or a string
// returns X & Y co-ords as an array

function find_position(objDetail) {
	
	var obj = (typeof(objDetail) == 'string') ? find_object(objDetail) : objDetail;
	
	var elemX = 0;
	var elemY = 0;
	
	if (obj.offsetParent) { // offsetParent returns null when the element has style.display set to "none"
		
		do {
			elemX += obj.offsetLeft;
			elemY += obj.offsetTop;
		}
		while (obj = obj.offsetParent);
		
		//return [elemX,elemY];
		return Array(elemX, elemY);
	}
	
	else {
		return false;
	}
}


/*---------------------------------------------------------------------------------------*/
// function set_position()
// subjectObj, anchorObj accepts either an object or a string
// use typeof - change on string or object

function set_position(subjectObj, anchorObj, reqOffsetX, reqOffsetY) {
	
	subjectObj = (typeof(subjectObj) == 'string') ? find_object(subjectObj) : subjectObj;
	
	anchorObj = (typeof(anchorObj) == 'string') ? find_object(anchorObj) : anchorObj;
	
	var anchorPosition = find_position(anchorObj);
	
	if (anchorPosition != false) {
		
		var reqPosnX = anchorPosition[0] + reqOffsetX;
		var reqPosnY = anchorPosition[1] + reqOffsetY;
		
		subjectObj.style.left = reqPosnX + 'px';
		subjectObj.style.top = reqPosnY + 'px';
		
	}
	
}

/*---------------------------------------------------------------------------------------*/
// function display_block()

function display_block(objDetail) {
	
	var objToShow = (typeof(objDetail) == 'string') ? find_object(objDetail) : objDetail;
	
	objToShow.style.display = 'block';
	
}

// function display_none()
function display_none(objDetail) {
	
	var objToHide = (typeof(objDetail) == 'string') ? find_object(objDetail) : objDetail;
	
	objToHide.style.display = 'none';
	
}

/*---------------------------------------------------------------------------------------*/
// function toggle_visibility()
// TODO: useful for removing results from a table display
// objToToggle.style.visibility = 'collapse'; // Collapse is identical to hidden if not used on rows or columns
// When used on a row or column, the element will not be visible. The space of the invisible element is used by the row or column for other content

function toggle_visibility(objDetail) {
	
	var objToToggle = (typeof(objDetail) == 'string') ? find_object(objDetail) : objDetail;
	
	if(objToToggle.style.visibility == 'hidden') {
		
		objToToggle.style.visibility = 'visible'; // Default. The element box is visible
		
	}
	else {
		
		objToToggle.style.visibility = 'hidden'; // The element box is not visible, but still affects layout. 
		
	}
		
}

/*---------------------------------------------------------------------------------------*/
// function get_doc_height()
// http://james.padolsey.com/javascript/get-document-height-cross-browser/
// This function will return any document’s height. It’s been tested in IE6/7, FF2/3, Safari (Windows), Google Chrome and Opera 9.5.
// If the actual document’s body height is less than the viewport height then it will return the viewport height instead
function get_doc_height() {
    
	var d = document;
	
    return Math.max(
        Math.max(d.body.scrollHeight, d.documentElement.scrollHeight),
        Math.max(d.body.offsetHeight, d.documentElement.offsetHeight),
        Math.max(d.body.clientHeight, d.documentElement.clientHeight)
    );
	
}

/*---------------------------------------------------------------------------------------*/
// function get_scroll_height()
// http://code.google.com/p/chromium/issues/detail?id=2891
// http://lists.w3.org/Archives/Public/www-style/2009Oct/0314.html

function get_scroll_height() {
    
	var d = document;
	
	return (d.documentElement.scrollTop >= d.body.scrollTop) ? d.documentElement.scrollTop : d.body.scrollTop;
	
	// self.YOffset works as well perhaps it has something to do with webkit as safari uses YOffset
	
}

/*---------------------------------------------------------------------------------------*/
/* main overlay */
/*---------------------------------------------------------------------------------------*/

// function set_overlay_height()
// sets overlay height to total content height
function set_overlay_height() {
	
	var docHeight = get_doc_height();
	
	overlay.style.height = docHeight + 'px';
	
}

// function init_overlay()
function init_overlay() {
	
	set_overlay_height();
	
	overlay.style.visibility = 'visible';
	
}

// function init_overlaycontent()
// sets overlay content container position, width and height
// receives topMargin, reqWidth, reqHeight
// TODO: remove height ??
// find_position(
// offsetParent returns null when the element has style.display  set to "none". 

function init_overlaycontent(topMargin, reqWidth, reqHeight) {
	
	init_overlay();
	
	var curScrollPos = get_scroll_height();
	
	var reqScrollPos = (curScrollPos + topMargin);
	
	overlayContentWrapper.style.marginTop = reqScrollPos + 'px';
	
	overlayContentWrapper.style.width = reqWidth + 'px';
	
	//overlayContentWrapper.style.height = reqHeight + 'px';
		
}

// function hide_overlay()
// also resets overlay content to default
function hide_overlay() {
	
	overlay.style.visibility = 'hidden';
	
	overlayContent.innerHTML = overlayLoadingContent;
	
}

/*---------------------------------------------------------------------------------------*/
/* mainmap overlay */
/*---------------------------------------------------------------------------------------*/

// function show_mainmapoverlay()
function show_mainmapoverlay() {
	
	// following not working !!
	//mainmapOverlay.style.width = mainmapObject.style.width + 'px';
	//mainmapOverlay.style.height = mainmapObject.style.height + 'px';
	
	set_position(mainmapOverlay, mainmapObject, 3, 3);
	
	display_block(mainmapOverlay);
	
}

// function hide_mainmapoverlay()
function hide_mainmapoverlay() {
	
	display_none('mainmapoverlay');
	
}


/*---------------------------------------------------------------------------------------*/
// function orderby_send()
// always receives 'this.form' from button
// assumes 'currhref' hidden field

function orderby_send(formObject) {
	
	var currHrefString = formObject.currhref.value;
	//console.log(currHrefString);
	
	var hrefStrings = explode('`', currHrefString);
	
	var currentHrefString = hrefStrings[0];
	//console.log(currentHrefString);	
	
	var currentParamString = hrefStrings[1];
	//console.log(currentParamString);
	
	var currentParamsArray = explode('-', currentParamString);
	// currently 4 variables passed, could be 5 if more limits applied, fe. price range
	// TODO: assoc array ??
	// of JSON objects ??
	
	var current_orderby = currentParamsArray[1];
	//console.log(current_orderby);
	
	var selectObj = formObject.orderbyselect;
	
	var req_orderby = selectObj.options[selectObj.selectedIndex].value;
	//console.log(req_orderby);
	
	currentParamsArray[1] = req_orderby;
	//console.log(currentParamsArray[1]);
	
	var reqParamString = implode('-', currentParamsArray);
	// implode(glue, pieces)
	// accepts JSON objects !
	//console.log(reqParamString);
	
	var reqPathname = currentHrefString + reqParamString;
	//console.log(reqPathname);
	
	window.location = reqPathname;
	
}


/*---------------------------------------------------------------------------------------*/
// function load_topjumpmenu()
/*---------------------------------------------------------------------------------------*/

function load_topjumpmenu() {
	
	if (document.getElementById('topjumpmenucont')) {
		
		var pathDetail = window.location.pathname;
		//console.log(pathDetail);
		
		var serverPage = set_path() + '/ajax/gen_topjumpmenu.php?pathdetail=' + pathDetail;
		//console.log(serverPage);
		
		process_ajax(serverPage, 'topjumpmenucont');
		// process_ajax(serverPage, targetElementId, formValue, openMethod, postString, responseFormat)
		
		//display_block('topjumpmenucont');
		
	}
}


/*---------------------------------------------------------------------------------------*/
// function topjumpmenu_send()
/*---------------------------------------------------------------------------------------*/
// TODO: !!
// placeLevel
// placeId

function topjumpmenu_send(formObject) {	
	
	
	var placeSelectObj = formObject.placename;
	
	var selectedPlace = placeSelectObj.options[placeSelectObj.selectedIndex].value;
	//console.log(selectedPlace);
	
	
	var productSelectObj = formObject.lookfor;
	
	var selectedProduct = productSelectObj.options[productSelectObj.selectedIndex].value;
	
	selectedProduct = (selectedProduct != 'everything') ? selectedProduct : '';
	// console.log(selectedProduct);
	
	
	var targetHref = set_path() + '/' + selectedPlace + '/' + selectedProduct;
	//console.log(targetHref);
	
	//return;
	
	window.location.href = targetHref;
	
}


/*---------------------------------------------------------------------------------------*/
// function show_gizmo()
/*---------------------------------------------------------------------------------------*/
// TODO: in future when using AJAX
// add parameters
// gizmoString
// destination name for use in alt text

function show_gizmo() {
	
	// TODO: when ajax
	//var gizmoImgage = find_object('gizmoimg');
	//gizmoImgage.src = 'http://banners.wunderground.com/banner/gizmotimetemp_both24/global/stations/' + gizmoString + '.gif';
	//gizmoImgage.alt = 'Current time and temperature in ' + destinationName;
	
	var gizmoContainer = find_object('gizmocont');
	
	var anchorObj = find_object('toplogo');
	//var anchorObj = find_object('registerloginimg');
	
	set_position(gizmoContainer, anchorObj, 15, 95);
	//set_position(gizmoContainer, anchorObj, 500, 97);
	
	gizmoContainer.style.visibility = 'visible';
	
}

// function hide_gizmo()
// TODO: in future when using AJAX
// TODO: global gizmoContainer, initiate
/*
function hide_gizmo() {
	
	var gizmoContainer = find_object('gizmocont');
	
	gizmoContainer.style.visibility = 'hidden';
	
}
*/

/*---------------------------------------------------------------------------------------*/
// function hide_submenus()
// 'display_none()' all submenus

// TEMP: set up submenus manually
var submenudetails = [{'submenuId': 'homesubmenu', 'anchorId': 'tochome'}, {'submenuId': 'countrysubmenu', 'anchorId': 'countryoptions'}, {'submenuId': 'admin1submenu', 'anchorId': 'admin1options'}, {'submenuId': 'destsubmenu', 'anchorId': 'destoptions'}];
// TODO: get elements by className
// class="submenus"

function hide_submenus() {
	
	//console.log(submenudetails.length);
	
	var currSubMenuObj;
	var currSubMenuId = '';
	
	for (var j in submenudetails) {
		
		currSubMenuObj = submenudetails[j];
		currSubMenuId = currSubMenuObj.submenuId;
		
		//console.log(currSubMenuId);
		
		display_none(currSubMenuId);
		
	}
	
}

/*---------------------------------------------------------------------------------------*/
// function preload_common_images()
// preloads required images
function preload_common_images() {
	
	var overIcons = new Array('arrow_down_on');
	var overIconImages = new Array();
	
	//var ajaxLoaders = new Array('main', 'pleasewait');
	//var preloadLoaders = new Array();
	
	for (var i in overIcons) {
		//var currentIcon = overIcon[i];
		var currentIconPath = set_path() + '/images/common/icons/' + overIcons[i] + '.png';
		overIconImages[i] = new Image;
		overIconImages[i].src = currentIconPath;
	}
	/*
	for (var j = 0; j < ajaxLoaders.length; j++) {
		var loaderImageName = ajaxLoaders[j];
		var loaderImagePath = set_path() + '/images/common/loaders/' + loaderImageName + '.gif';
		preloadLoaders[j] = new Image;
		preloadLoaders[j].src = loaderImagePath;
	}
	*/
}


/*---------------------------------------------------------------------------------------*/
// function clear_content()
function clear_content(targetElement) {
	
	document.getElementById(targetElement).innerHTML = '&nbsp;';
	
}

/*---------------------------------------------------------------------------------------*/
// function focus_element()
function focus_element(targetElement) {
	
	document.getElementById(targetElement).focus();
	
}

/*---------------------------------------------------------------------------------------*/
var tipLoadingContent = document.getElementById('tipcontent').innerHTML;
//var origLinkObjectTitle = '';

// function show_bubbletip()
// receives entire link object
// show_bubbletip(this)
function show_bubbletip(linkObject) {
	
	var bubbletip = document.getElementById('bubbletip');
	
	display_block('bubbletip');
	// TODO: change display_block() to use object ??
	
	set_position(bubbletip, linkObject, 0, 10);
	
	var linkObjectTitle = linkObject.title;
	
	document.getElementById('tipcontent').innerHTML = linkObjectTitle;
	
	// origLinkObjectTitle = linkObjectTitle;
	//linkObject.title = '';
	
}

function hide_bubbletip(linkObject) {
	
	display_none('bubbletip');
	
	document.getElementById('tipcontent').innerHTML = tipLoadingContent;
	
	//linkObject.title = origLinkObjectTitle;
	
}


/*---------------------------------------------------------------------------------------*/
// function get_block_availability()
// passes original variables to php script
// Validation handled by php script

// currently function call is dependant on 'get_selected_dates()' function below to find selected date variables

function get_block_availability(hotelId, checkinDay, checkinMonth, numNights) {
	
	init_overlaycontent(65, 840, 500);
	
	set_overlay_height();
	
	var detailGeneratorUrl = set_path() + '/ajax/accom/block_availability.php?hotel=' + hotelId + '&checkinDay=' + checkinDay + '&checkinMonth=' + checkinMonth + '&numNights=' + numNights;
	//alert(detailGeneratorUrl);
	
	// use new AJAX object, or check out Google wrapper ??
	GDownloadUrl(detailGeneratorUrl, function (data, responseCode) {
																								
												if (responseCode == 200) {
													
													// data is an HTML string
													overlayContent.innerHTML = data;
													
													// reset overlay height to new content height
													// TODO: set_timeout
													// images take a while to load
													set_overlay_height();
													
												}
												
												else if (responseCode == -1) {
													
													overlayContent.innerHTML = '<div class="bigrednotice">Request Timed Out</div>';
													
												}
												
												else {
												}
												
											  }  //end function(data, responseCode)
											  ); //end GDownloadUrl()
	
}

/*---------------------------------------------------------------------------------------*/
// function get_selected_dates()
// accomm only for now
// checkinMonth, checkinDay, numNights
function get_selected_dates() {
	
	var checkinDayList = document.getElementById('checkinDay');
	checkinDayValue = checkinDayList.options[checkinDayList.selectedIndex].value;
	
	var checkinMonthList = document.getElementById('checkinMonth');
	checkinMonthValue = checkinMonthList.options[checkinMonthList.selectedIndex].value;
		
	var numNightsList = document.getElementById('numNights');
	numNightsValue = numNightsList.options[numNightsList.selectedIndex].value;
	
}

// function show_calendar()
function show_calendar() {
	
	var popupCalendar = document.getElementById('popupcalendar');
	
	var calendarIcon = document.getElementById('calendaricon');
	
	set_position(popupCalendar, calendarIcon, -300, 60);
	
	display_block('popupcalendar');
	
}

// function hide_calendar()
function hide_calendar() {
	
	display_none('popupcalendar');
	
	// store dates if user has selected
	// should synch automatically ??
	// if so can remove this function and just use display_none()
	
}

/*---------------------------------------------------------------------------------------*/
// function url_encode()
// same as the php function
// returns string with spaces encoded as plus (+) signs
// eg. Australia+and+New+Zealand

function url_encode(thestring) {
	
	return thestring.replace(' ', '+')
	
}


/*---------------------------------------------------------------------------------------*/
// function explode()
// http://phpjs.org/functions/explode:396

function explode(delimiter, string, limit) {
    // +     original 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 implode()
// http://phpjs.org/functions/implode:430

function implode(glue, pieces) {
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Itsacon (http://www.itsacon.net/)
    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
    // *     example 1: implode(' ', ['Kevin', 'van', 'Zonneveld']);
    // *     returns 1: 'Kevin van Zonneveld'
    // *     example 2: implode(' ', {first:'Kevin', last: 'van Zonneveld'});
    // *     returns 2: 'Kevin van Zonneveld'

    var i = '', retVal='', tGlue='';
    if (arguments.length === 1) {
        pieces = glue;
        glue = '';
    }
    if (typeof(pieces) === 'object') {
        if (pieces instanceof Array) {
            return pieces.join(glue);
        }
        else {
            for (i in pieces) {
                retVal += tGlue + pieces[i];
                tGlue = glue;
            }
            return retVal;
        }
    }
    else {
        return pieces;
    }
}

/*---------------------------------------------------------------------------------------*/
// function modify_navlist()
// currently receives contract/expand
// TODO: pass required height ??
// or work it out from default height ??
function modify_placeslist(doWhat) {
	
	var placeslistcont = document.getElementById('placeslistcont');
	
	// TODO: 
	//var containerHeight = placeslistcont.height;
	
	if (doWhat == 'contract') {
		placeslistcont.style.overflow = 'hidden';
		placeslistcont.style.height = '350px'; // 250
	}
	
	else if (doWhat == 'expand') {
		placeslistcont.style.overflow = 'visible';
	}
}

/*---------------------------------------------------------------------------------------*/
// function swap_img_src(targetImageId, sourceUri)

function swap_img_src(targetImageId, sourceUri) {
	
	var targetImage = document.getElementById(targetImageId);
	
	targetImage.src = sourceUri;
	
}

// function swap_cam_view(imageUrl)

function swap_cam_view(imageUrl, imageAlt) {
	
	var camImage = document.getElementById('mainmapimage');
	
	camImage.src = imageUrl;
	
	camImage.alt = imageAlt;
	
}

/*---------------------------------------------------------------------------------------*/
// function set_padding()
// TODO: targetId as an array
function set_padding(obj, targetId) {
	
	var linkPosn = findPosition(obj);
	// returns Array(elemX, elemY);
	
	var reqPadding = (linkPosn[1] - 150);
	
	if (reqPadding > 0) {
		
		document.getElementById(targetId).style.paddingTop = reqPadding + 'px';
		
	}
	else {
		
		document.getElementById(targetId).style.paddingTop = '0px';
		
	}
	
}

/*---------------------------------------------------------------------------------------*/
// function load_script()
/**
 * Appends a JavaScript file to the page.
 * @param {string} scriptUri
 */

function load_script(scriptUri) {
	
	var reqScript = document.createElement('script');
	
	reqScript.type = 'text/javascript';
	// script.setAttribute('type','text/javascript');
	
	reqScript.src = scriptUri;
	
	document.body.appendChild(reqScript);
	
}

/*---------------------------------------------------------------------------------------*/
// function insert_after()
// when the second parameter of insertBefore is null then the newNode is appended to the end of the parentNode
function insert_after(referenceNode, newNode) {
    
	referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
	
}

/*---------------------------------------------------------------------------------------*/
function topsearchinput_focus() {
	
	var topsearchinput = document.getElementById('topsearchinput');
	
	topsearchinput.className = 'inputon';
	
	topsearchinput.value = '';
	
	topsearchinput.style.backgroundImage="url(http://www.alltravels.com/images/trans.png)";
	
}
// TODO: declare var topsearchinput at top
function topsearchinput_blur() {
	
	var topsearchinput = document.getElementById('topsearchinput');
	
	topsearchinput.className = 'inputoff';
	
	if (topsearchinput.value == '') {
		topsearchinput.value = 'Search Site With:';
	}
	
	topsearchinput.style.backgroundImage="url(http://www.alltravels.com/images/common/backs/google_custom_search.png)";
	
}

function topsearchinput_suggest() {
	// set timeout 3 secs
	// ajax search suggest
}

/*---------------------------------------------------------------------------------------*/
// function init_links()

function init_links() {
	
	var lnkcont = document.getElementById('linkcontainer');
	//if (!lnkcont) {return};
	
	var links = lnkcont.getElementsByTagName('a');
	//if (!links) {return};
	
	for (var i = 0; i < links.length; i++) {
		links[i].onclick = function() {
									sendHttpRequest('readfile.php?file=' + this.href, 'displayFileContents');
									return false;
									}
	}
	
}

/*---------------------------------------------------------------------------------------*/
// function check_uncheck_group()
// checks or unchecks all items in a radio or checkbox group, uses '.click()' cos 'checked == ' is buggy
// targetGroup is an array
// reqAction can be 'check' or 'uncheck'
function check_uncheck_group(targetGroup, reqAction) {
	
	var inputGroup = document.getElementsByName(targetGroup);
	
	for (var i = 0; i < inputGroup.length; i++) {
		
		if (reqAction == 'check') {
			if (inputGroup[i].checked == false) {
				inputGroup[i].click();
			}
		}
		
		else {
			if (inputGroup[i].checked == true) {
				inputGroup[i].click();
			}
		}
	}
	
}

/*---------------------------------------------------------------------------------------*/
// function get_selected_radio()
// receives radio group as an object
// get_selected_radio(document.contactform.messageSubject);
// check that at least one is selected, returns value of selected if so
// returns false if none selected
function get_selected_radio(groupObject) { 
	
	for (var i = 0; i < groupObject.length; i++) {
		
		if (groupObject[i].checked) {
			return groupObject[i].value;
		}
		
	}
	
	return false;
	
}

/*---------------------------------------------------------------------------------------*/
// The Slider component fires these three events:

// change  Continually when dragging the thumb OR once after a move caused by clicking the background
// Event the fires when the value of the control changes. If the control is animated the event will fire every point along the way.

// slideStart  Once at the beginning of a slide operation 
// slideEnd  Once after the thumb reaches its destination 

// DualSliders maintain two read only properties, minVal and maxVal, for the current positions of the two thumbs. 
// To set the values in your code, use methods setMinValue(n), setMaxValue(n), or setValues(n,n).

function init_rates_slider() {
   
   var rateSliderRange = 202;
   
   var rateSliderTickSize = 10;
   
   //var initRateSliderVals = '[12, 85]';
   
   var rateSlider = YAHOO.widget.Slider.getHorizDualSlider('ratesliderback', 'minratethumb', 'maxratethumb', rateSliderRange);
   //var rateSlider = YAHOO.widget.Slider.getHorizDualSlider('ratesliderback', 'minratethumb', 'maxratethumb', rateSliderRange, rateSliderTickSize, initRateSliderVals);
   
   //rateSlider.minSlider.animate = false;
   //rateSlider.maxSlider.animate = false;
   // If you include the YUI Animation Utility in your web page, the slider animates when its background is clicked. 
   // The animation is a smooth "ease-in" transition unless you define tick marks for the slider. In that case the slider snaps to all tick marks on its way to the final destination.
   // don't animate if using background images, IE bug
   
   //rateSlider.minRange = 10; // rateSliderTickSize
   // Keep in mind that minVal and maxVal are calculated from the center of the thumbs
   
   rateSlider.subscribe('slideEnd', function() { 
										 
										 var minRatePixels = rateSlider.minSlider.getValue();
										 var maxRatePixels = rateSlider.maxSlider.getValue();
										 
										 var minRateVal = minRatePixels;
										 var maxRateVal = maxRatePixels;
										 
										 //alert(minRateVal + '-' + maxRateVal);
										 
										 document.getElementById('displayminrate').innerHTML = hotelCurrency + minRateVal;
										 document.getElementById('displaymaxrate').innerHTML = hotelCurrency + maxRateVal;
										 
										 }
										);
   
   
   // roundedVal = val - (val % 10); // rateSliderTickSize
   // setTimeout(function () { slider.setValue(roundedVal); },0);
   // YAHOO.util.Dom.setStyle(myElement,'background-color','#9f9');
   // YAHOO.log("The thumb has arrived");
   
}

/*---------------------------------------------------------------------------------------*/
// function ajax_object()
// creates a new request object with availability switch
function ajax_object(avail) {
	
	this.avail = avail; // can set to 1 by default ?
	
	this.formValue = false; // can set to false by default ?
	
	if (window.XMLHttpRequest) {
		
		this.ajaxObject = new XMLHttpRequest();
		
	}
	else if (window.ActiveXObject) {
		
		this.ajaxObject = new ActiveXObject('Microsoft.XMLHTTP');
		// change if (window.ActiveXObject) to try/catch ??
		
	}
	
	// else ?
	//this.ajaxObject = false;
	
}

/*---------------------------------------------------------------------------------------*/
// http://code.google.com/apis/maps/articles/phpsqlajax_v3.html
// Since XMLHttpRequest is asynchronous, the callback function won't be called as soon as you invoke downloadUrl. The bigger your XML file, the longer it may take. 
// Don't put any code after downloadUrl that relies on the markers existing already—put it inside the callback function instead.

// var request = window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest;

function downloadUrl(url, callback) {
	
	var request = window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest;
	
	request.onreadystatechange = function() {
									if (request.readyState == 4) {
										request.onreadystatechange = doNothing;
										callback(request.responseText, request.status);
									}
								 };
	
	request.open('GET', url, true);
	
	request.send(null);
	
}

// http://gmaps-samples-v3.googlecode.com/svn/trunk/xmlparsing/downloadurl.html
/**
 * Parses the given XML string and returns the parsed document in a
 * DOM data structure. This function will return an empty DOM node if
 * XML parsing is not supported in this browser.
 * @param {string} str XML string.
 * @return {Element|Document} DOM.
 */
function xmlParse(str) {
  if (typeof ActiveXObject != 'undefined' && typeof GetObject != 'undefined') {
    var doc = new ActiveXObject('Microsoft.XMLDOM');
    doc.loadXML(str);
    return doc;
  }

  if (typeof DOMParser != 'undefined') {
    return (new DOMParser()).parseFromString(str, 'text/xml');
  }

  return createElement('div', null);
}

/*---------------------------------------------------------------------------------------*/
// function process_ajax()
// the ultimate AJAX function
// handles multiple ajax requests
// major browsers will only process 2 requests at a time ??

// TODO: add parameter for loading content
// set up array of typical loading messages ?
// eg. '<span class="">Loading...</span>', 'Checking...'

var ajaxObjects = new Array();
var targetElements = new Array();
var fieldValues = new Array();

function process_ajax(serverPage, targetElementId, formValue, openMethod, postString, responseFormat) {
	
	// check for undefined parameters
	// only serverPage, targetElementId are required in all function calls
	// typeof used for cross browser compatibility - Safari doesn't like if(!parameter)
	if (typeof formValue == 'undefined') formValue = false;
	if (typeof openMethod == 'undefined') openMethod = 'get';
	if (typeof postString == 'undefined') postString = null;
	if (typeof responseFormat == 'undefined') responseFormat = 'text';
	
	// search for a free ajaxObject
	var pos = -1;	
	for (var i = 0; i < ajaxObjects.length; i++) {
		if (ajaxObjects[i].avail == 1) {
			pos = i;
			break;
		}
	}	
	// if none available create a new (free) ajaxObject and append it to the ajaxObjects array
	if (pos == -1) {
		pos = ajaxObjects.length;
		ajaxObjects[pos] = new ajax_object(1);
	}
	
	// if new object created
	if (ajaxObjects[pos].ajaxObject) {
		
		// lock this ajaxObject
		ajaxObjects[pos].avail = 0;
		
		// set formValue attribute
		ajaxObjects[pos].formValue = formValue;
		
		// add target element to array
		targetElements[pos] = targetElementId;
		
		// if get method
		if (openMethod == 'get') {		
		
			ajaxObjects[pos].ajaxObject.open('GET', serverPage, true);
			
			ajaxObjects[pos].ajaxObject.onreadystatechange = function() {
				
				if (ajaxObjects[pos].ajaxObject.readyState == 1 || ajaxObjects[pos].ajaxObject.readyState == 2 || ajaxObjects[pos].ajaxObject.readyState == 3) {
					if (!ajaxObjects[pos].formValue) {
						document.getElementById(targetElements[pos]).innerHTML = '<span class="checking">Loading...</span>';
					}
					else {
						document.getElementById(targetElements[pos]).value = 'Checking...';
					}
				}
				
				if (ajaxObjects[pos].ajaxObject.readyState == 4) {
					
					if (ajaxObjects[pos].ajaxObject.status == 200) { // || ajaxObjects[pos].ajaxObject.status == 304
						
						// handle_response(targetElementId, responseContent, responseContentType);
						
						if (responseFormat == 'text') {
							
							// if we're changing a form field value
							if (ajaxObjects[pos].formValue) {
								// check for problem flag '<#>' in ajaxObjects[pos].ajaxObject.responseText;
								fieldValues[pos] = ajaxObjects[pos].ajaxObject.responseText;
								
								if (fieldValues[pos].search('<#>') != -1) {
									// if found remove <#> from string
									fieldValues[pos].replace(/<#>/, '');
									// set color flags
									document.getElementById(targetElements[pos]).style.color = '#990000';
									//document.getElementById(targetElements[pos]).style.color = '#990000'; // border color
								} else {
									document.getElementById(targetElements[pos]).style.color = '#009900';
								}
								
								document.getElementById(targetElements[pos]).value = fieldValues[pos];
								
							}
							// else we're changing an element's innerHTML
							else {
								// status flag set in server response
								// <span class="passed">/<span class="problem">
								
								document.getElementById(targetElements[pos]).innerHTML = ajaxObjects[pos].ajaxObject.responseText;
							}
						}
						else {
							
							// process XML
							
						}
						
					} //end if status == 200
					
					else {
						// handle_error(targetElementId, responseCode);
					}
					
					// unlock this ajaxObject regardless of response code
					ajaxObjects[pos].avail = 1;
					
				} //end if readyState == 4
				
			} //end onreadystatechange = function()
			
			ajaxObjects[pos].ajaxObject.send(null);
						
		} //end if get method
		
		// if post method
		else {
			
			ajaxObjects[pos].ajaxObject.open('POST', serverPage, true);
			
			ajaxObjects[pos].ajaxObject.onreadystatechange = function() {
				
				if (ajaxObjects[pos].ajaxObject.readyState == 1 || ajaxObjects[pos].ajaxObject.readyState == 2 || ajaxObjects[pos].ajaxObject.readyState == 3) {
					document.getElementById(targetElements[pos]).innerHTML = '<span class="posting">Posting...</span>';
				}
				
				if (ajaxObjects[pos].ajaxObject.readyState == 4) {
					
					if (ajaxObjects[pos].ajaxObject.status == 200) { // || ajaxObjects[pos].ajaxObject.status == 304
						
						// handle_response() function
						if (responseFormat == 'text') {
							document.getElementById(targetElements[pos]).innerHTML = ajaxObjects[pos].ajaxObject.responseText;
						} else {
							// process XML
						}
						
					} //end if status == 200
					
					else {
						// handle_error();
					}
					
					// unlock this ajaxObject regardless of response code
					ajaxObjects[pos].avail = 1;
					
				} //end if readyState == 4
				
			} //end onreadystatechange = function()
				
			ajaxObjects[pos].ajaxObject.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			ajaxObjects[pos].ajaxObject.send(postString);
			
		} //end if post method
		
	} //end if (ajaxObjects[pos].ajaxObject)
	
	else {
		// call function recursively ??
	}
	
} //end function process_ajax()

/*---------------------------------------------------------------------------------------*/
// function formData2QueryString()
// not exactly the original
// http://blueb.net/blog/attach/1/980547.txt
function formData2QueryString(docForm) {
	
	var formElement = '';
	
	var submitString = '';
	
	var lastElementName = '';
	
	for (i = 0 ; i < docForm.elements.length ; i++) {
		
		formElement = docForm.elements[i];
		
		switch (formElement.type) {
			
			case 'text' :
			case 'button' :
			case 'select-one' :
			case 'hidden' :
			case 'password' :
			
			case 'textarea' :
				submitString += formElement.name + '=' + escape(formElement.value) + '&';
				break;
			
			case 'radio' :
				if (formElement.checked) {
					submitString += formElement.name + '=' + escape(formElement.value) + '&';
				}
				break;
							
			// Checkboxes
			case 'checkbox':
				if (formElement.checked) {
					// Continuing multiple, same-name checkboxes
					if (formElement.name = lastElementName) {
						// Strip of end ampersand if there is one
						if (submitString.lastIndexOf('&') == submitString.length-1) {
							submitString = submitString.substr(0, submitString.length - 1);
						}
						// Append value as comma-delimited string
						submitString += ',' + escape(formElement.value);
					}
					else {
						submitString += formElement.name + '=' + escape(formElement.value);
					}
					submitString += '&';
					lastElementName = formElement.name;
				}
				break;
				
		}
	}
	
	submitString = submitString.substring(0, submitString.length - 1);
	
	return submitString;
	
}

/*---------------------------------------------------------------------------------------*/
function MM_findObj(n, d) { //v4.01
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  if(!x && d.getElementById) x=d.getElementById(n); return x;
}

function YY_checkform() { //v4.66
//copyright (c)1998,2002 Yaromat.com
  var args = YY_checkform.arguments; var myDot=true; var myV=''; var myErr='';var addErr=false;var myReq;
  for (var i=1; i<args.length;i=i+4){
    if (args[i+1].charAt(0)=='#'){myReq=true; args[i+1]=args[i+1].substring(1);}else{myReq=false}
    var myObj = MM_findObj(args[i].replace(/\[\d+\]/ig,""));
    myV=myObj.value;
    if (myObj.type=='text'||myObj.type=='password'||myObj.type=='hidden'){
      if (myReq&&myObj.value.length==0){addErr=true}
      if ((myV.length>0)&&(args[i+2]==1)){ //fromto
        var myMa=args[i+1].split('_');if(isNaN(myV)||myV<myMa[0]/1||myV > myMa[1]/1){addErr=true}
      } else if ((myV.length>0)&&(args[i+2]==2)){
          var rx=new RegExp("^[\\w\.=-]+@[\\w\\.-]+\\.[a-z]{2,4}$");if(!rx.test(myV))addErr=true;
      } else if ((myV.length>0)&&(args[i+2]==3)){ // date
        var myMa=args[i+1].split("#"); var myAt=myV.match(myMa[0]);
        if(myAt){
          var myD=(myAt[myMa[1]])?myAt[myMa[1]]:1; var myM=myAt[myMa[2]]-1; var myY=myAt[myMa[3]];
          var myDate=new Date(myY,myM,myD);
          if(myDate.getFullYear()!=myY||myDate.getDate()!=myD||myDate.getMonth()!=myM){addErr=true};
        }else{addErr=true}
      } else if ((myV.length>0)&&(args[i+2]==4)){ // time
        var myMa=args[i+1].split("#"); var myAt=myV.match(myMa[0]);if(!myAt){addErr=true}
      } else if (myV.length>0&&args[i+2]==5){ // check this 2
            var myObj1 = MM_findObj(args[i+1].replace(/\[\d+\]/ig,""));
            if(myObj1.length)myObj1=myObj1[args[i+1].replace(/(.*\[)|(\].*)/ig,"")];
            if(!myObj1.checked){addErr=true}
      } else if (myV.length>0&&args[i+2]==6){ // the same
            var myObj1 = MM_findObj(args[i+1]);
            if(myV!=myObj1.value){addErr=true}
      }
    } else
    if (!myObj.type&&myObj.length>0&&myObj[0].type=='radio'){
          var myTest = args[i].match(/(.*)\[(\d+)\].*/i);
          var myObj1=(myObj.length>1)?myObj[myTest[2]]:myObj;
      if (args[i+2]==1&&myObj1&&myObj1.checked&&MM_findObj(args[i+1]).value.length/1==0){addErr=true}
      if (args[i+2]==2){
        var myDot=false;
        for(var j=0;j<myObj.length;j++){myDot=myDot||myObj[j].checked}
        if(!myDot){myErr+='* ' +args[i+3]+'\n'}
      }
    } else if (myObj.type=='checkbox'){
      if(args[i+2]==1&&myObj.checked==false){addErr=true}
      if(args[i+2]==2&&myObj.checked&&MM_findObj(args[i+1]).value.length/1==0){addErr=true}
    } else if (myObj.type=='select-one'||myObj.type=='select-multiple'){
      if(args[i+2]==1&&myObj.selectedIndex/1==0){addErr=true}
    }else if (myObj.type=='textarea'){
      if(myV.length<args[i+1]){addErr=true}
    }
    if (addErr){myErr+='* '+args[i+3]+'\n'; addErr=false}
  }
  if (myErr!=''){alert('The required information is incomplete or contains errors:\t\t\t\t\t\n\n'+myErr)}
  document.MM_returnValue = (myErr=='');
}

/*---------------------------------------------------------------------------------------*/
// function duplicateSidePic()
// duplicate listingpic to sidepic - individual listings pages
function duplicateSidePic() {
	var sourcePic = document.getElementById("listingpic");
	var targetPic = document.getElementById("sidepic");
	targetPic.src = sourcePic.src;
	targetPic.alt = sourcePic.alt;
}

/*---------------------------------------------------------------------------------------*/
// function format_date()
// The code prints: 21st April 2009 with superscript

function format_date() {
	
	var m_names = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
	
	var d = new Date();
	var curr_date = d.getDate();
	
	var sup = '';
	
	if (curr_date == 1 || curr_date == 21 || curr_date ==31) {
	   sup = "st";
	}
	else if (curr_date == 2 || curr_date == 22) {
	   sup = "nd";
	}
	else if (curr_date == 3 || curr_date == 23) {
	   sup = "rd";
	}
	else {
	   sup = "th";
	}
	
	var curr_month = d.getMonth();
	var curr_year = d.getFullYear();
	
	document.write(curr_date + "<sup>" + sup + "</sup> " + m_names[curr_month] + " " + curr_year);
	
}

/*---------------------------------------------------------------------------------------*/
// function init_tocstring_events()
// causing problems, using inline funcion calls for now

function init_tocstring_events() {
	
	// check if tocstring exists on this page
	var tocstring = document.getElementById('tocstring');
		
	if (tocstring) {
		
		/*---------------------------------------------------------------------------------------*/
		// setup submenus and triggers
		var currentMenuObj, currentMenuId, currentAnchorObj, currentAnchorId;
		
		var currentMenuIds = [];
		
		for (var i in submenudetails) {
			
			// TODO: add triggerObj
			
			currentAnchorId = submenudetails[i].anchorId;
			
			currentAnchorObj = document.getElementById(currentAnchorId);
			
			if (currentAnchorObj) {
				
				currentMenuId = submenudetails[i].submenuId;
				
				currentMenuIds[i] = currentMenuId;
				
				//console.log(currentMenuId + ' : ' + currentAnchorId);
				
				currentMenuObj = document.getElementById(currentMenuId);
				
				set_position(currentMenuObj, currentAnchorObj, -48, 21);
				
				currentAnchorObj.onmouseover = function() {
					
					this.className = 'downarrow_over';
					
					//display_block(currentMenuId);
					
				}
				
				currentAnchorObj.onmouseout = function() {
					
					this.className = 'downarrow';
					
				}				
				
			}
						
		} // end if (currentAnchorObj)
		
		/*---------------------------------------------------------------------------------------*/
		// add listener for all tocstring anchors to hide all submenus
		var tocstringAnchors = tocstring.getElementsByTagName('a');
		
		for (var i in tocstringAnchors) {
			
			tocstringAnchors[i].onmouseover = function() {
				
				hide_submenus();
				
			}
			
		} // end for (var i in tocstringAnchors)
		
		
	} // end if (tocstring)
	
} //end function init_tocstring_events()


/*---------------------------------------------------------------------------------------*/
// function parseScript(sourceString)
// http://www.webdeveloper.com/forum/showthread.php?t=138830

// In Microsoft Internet Explorer, when you try to run a program (script) to parse or insert HTML, the script and Internet Explorer may unexpectedly close (crash).
// This behavior may occur if the script contains a certain tag without the same closing tag, or if the script contains the IHTMLTxtRange::pasteHTML function.
// Microsoft Internet Explorer 6.0,

function parseScript(sourceString) {
	
	//console.log('hello');
	
	//var source = _source;
	
	var scripts = new Array();
	
	// Strip out tags
	while(sourceString.indexOf("<script") > -1 || sourceString.indexOf("</script") > -1) {
		var s = sourceString.indexOf("<script");
		var s_e = sourceString.indexOf(">", s);
		var e = sourceString.indexOf("</script", s);
		var e_e = sourceString.indexOf(">", e);
		
		// Add to scripts array
		scripts.push(sourceString.substring(s_e+1, e));
		
		// Strip from sourceString
		sourceString = sourceString.substring(0, s) + sourceString.substring(e_e+1);
		
	}
	
	// Loop through every script collected and eval it
	for (var i=0; i<scripts.length; i++) {
		
		try {
			eval(scripts[i]);
		}
			catch(ex) {
			// do what you want here when a script fails
		}
	}
	
	// Return the cleaned sourceString
	return sourceString;
	
}

/*---------------------------------------------------------------------------------------*/
// from http://code.google.com/apis/maps/documentation/v3/

// If you wish to have your application work well on mobile devices, we recommend the following:
// Set the <div> containing your map to have width and height attributes of 100%. 
// Be aware that some older desktop browsers don't display well with these values, however.

// The iPhone device respects the following <meta> tag:
// <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
// Android devices running software version 1.5 (Cupcake) also support these parameters. 
// Note that the iPhone's Safari browser requires this <meta> tag be included within the page's <head> element.

/*
function detectBrowser() {
  
  var useragent = navigator.userAgent;
  // You can detect iPhone and Android devices by inspecting the navigator.userAgent property within the DOM
  
  var mapdiv = document.getElementById("map_canvas");
    
  if (useragent.indexOf('iPhone') != -1 || useragent.indexOf('Android') != -1 ) {
    mapdiv.style.width = '100%';
    mapdiv.style.height = '100%';
  }
  
  else {
    mapdiv.style.width = '600px';
    mapdiv.style.height = '800px';
  }
  
}

*/

/*---------------------------------------------------------------------------------------*/
// https://developer.mozilla.org/en/DOM/window.location
// Display the properties of the current URL in an alert dialog:

/*
function showLoc() {
   var x = window.location;
   var t = ['Property - Typeof - Value',
            'window.location - ' + (typeof x) + ' - ' + x ];
   for (var prop in x){
     t.push(prop + ' - ' + (typeof x[prop]) + ' - ' +  (x[prop] || 'n/a'));
   }
   alert(t.join('\n'));
 }
*/
// in html: <button onclick="showLoc();">Show location properties</button>


/*---------------------------------------------------------------------------------------*/
/*

var text = "cats make great pets for the home";
if (text.indexOf("pet") > -1) {
	alert("We have a match!")
}
else {
	alert("No match found.")
}

*/

/*---------------------------------------------------------------------------------------*/
/*
var a = [2,4,5,63,4,5,63,2,4,43];
 
function quicksort(arr) {
    if (arr.length == 0)
        return [];
 
    var left = new Array();
    var right = new Array();
    var pivot = arr[0];
 
    for (var i = 1; i < arr.length; i++) {
        if (arr[i] < pivot) {
           left.push(arr[i]);
        } else {
           right.push(arr[i]);
        }
    }
 
    return quicksort(left).concat(pivot, quicksort(right));
}
 
console.log(quicksort(a));
*/

/*---------------------------------------------------------------------------------------*/
// http://www.richardcastera.com/2009/06/22/javascript-passing-multiple-parameters-through-settimeout/
/*
var _st = window.setTimeout;
window.setTimeout = function(fRef, mDelay) { 
	if(typeof fRef == "function") {  
		var argu = Array.prototype.slice.call(arguments,2); 
		var f = (function(){ fRef.apply(null, argu); }); 
		return _st(f, mDelay); 
	} 
	return _st(fRef,mDelay);
}
// setTimeout(alertMe, 2000, message, name);
*/

/*---------------------------------------------------------------------------------------*/
