﻿//http: //www.onemoretake.com/2009/10/11/ajaxqueue-and-jquery-1-3/
(function($) { 

    var ajax = $.ajax;

    var pendingRequests = {};

    var synced = [];
    var syncedData = [];
    var valueSelected = false;

    $.ajax = function(settings) {
        // create settings for compatibility with ajaxSetup
        settings = jQuery.extend(settings, jQuery.extend({}, jQuery.ajaxSettings, settings));

        var port = settings.port;

        switch (settings.mode) {
            case "sync":
                var pos = synced.length;

                synced[pos] = {
                    error: settings.error,
                    success: settings.success,
                    complete: settings.complete,
                    done: false
                };

                syncedData[pos] = {
                    error: [],
                    success: [],
                    complete: []
                };

                settings.error = function() { syncedData[pos].error = arguments; };
                settings.success = function() { syncedData[pos].success = arguments; };
                settings.complete = function() {
                    syncedData[pos].complete = arguments;
                    synced[pos].done = true;

                    if (pos == 0 || !synced[pos - 1])
                        for (var i = pos; i < synced.length && synced[i].done; i++) {
                        if (synced[i].error) synced[i].error.apply(jQuery, syncedData[i].error);
                        if (synced[i].success) synced[i].success.apply(jQuery, syncedData[i].success);
                        if (synced[i].complete) synced[i].complete.apply(jQuery, syncedData[i].complete);

                        synced[i] = null;
                        syncedData[i] = null;
                    }
                };
        }
        return ajax.apply(this, arguments);
    };

})(jQuery);
/**
*@preserve Autocomplete - jQuery plugin 1.1pre
*
* Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, JÃ¶rn Zaefferer
*
* Dual licensed under the MIT and GPL licenses:
*   http://www.opensource.org/licenses/mit-license.php
*   http://www.gnu.org/licenses/gpl.html
*
* Revision: $Id: jquery.autocomplete.js 5785 2008-07-12 10:37:33Z joern.zaefferer $
*
*/
/**************** Core AutoComplete Logic ***********************/
jQuery.autocomplete = function (input, options) {
    // Create a link to self
    var me = this;
    var resultHidden = true;
    var currentAjax = null;
    var enabled = true;

    // Create jQuery object for input element
    var $input = $(input).attr("autocomplete", "off");

    // Apply inputClass if necessary
    if (options.inputClass) {
        $input.addClass(options.inputClass);
    }

    // Create results
    var results = document.createElement("div");

    // Create jQuery object for results
    var $results = $(results).hide().addClass(options.resultsClass).css("position", "absolute");
    if (options.width > 0) {
        $results.css("width", options.width);
    }
    if (options.useiframe && $.browser.msie && $.browser.version.substring(0, 1) == 6) {
        // we put a styled iframe behind the autosuggest so HTML SELECT elements don't show through
        $results.append(document.createElement('iframe'));
    }

    // Add to body element
    if (options.attachedToBody) {
        $("body").append(results);
    } else {
        $input.parent().append(results);
    }

    input.autocompleter = me;

    var timeout = null;
    var prev = "";
    var active = -1;
    var keyb = false;
    var hasFocus = false;
    var lastKeyPressCode = null;
    var mouseDownOnSelect = false;
    var hidingResults = false;
    var xAdj = 0;
    if ($.browser.msie) {
        xAdj = 1;
    }

    $input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function (e) {

        if (!enabled) return;

        var $this = $(this);

        lastKeyPressCode = e.keyCode;
        switch (e.keyCode) {
            case 38: // up
                e.preventDefault();
                moveSelect(-1);
                break;
            case 40: // down
                e.preventDefault();
                moveSelect(1);
                break;
            case 9:
            case 13: // return
                if (selectCurrent()) {
                    // make sure to blur off the current field
                    valueSelected = true;
                    $input.get(0).blur();
                    e.preventDefault();
                }
                else {
                    if ((e.keyCode != 9) && ($this.val().length > 2)) {
                        var $homeSearchBtn = $("#hc_home_search");
                        if ($homeSearchBtn.length == 1) {
                            $homeSearchBtn.click();
                        }
                    }
                }
                break;
            case 37: //left
                moveSelect(-1);
                break;
            case 39: //right
                moveSelect(1);
                break;
            case 8: //backspace need to throttle
                active = -1;
                if (timeout) clearTimeout(timeout);
                timeout = setTimeout(function () { onChange(); }, 100);
                break;
            default:
                active = -1;
                if (timeout) clearTimeout(timeout);
                timeout = setTimeout(function () { onChange(); }, options.delay);
                break;
        }
    })
	.focus(function () {
	    // track whether the field has focus, we shouldn't process any results if the field no longer has focus
	    hasFocus = true;
	})
	.blur(function () {
	    //If only 1 result then always autoselect
	    if (results.style.display != "none" && options.selectOnly && enabled) {
	        var $li = $("li", results);
	        if ($li.length == 1) {
	            li = $li[0];
	            if ($('a', li).length == 1) {
	                // redirect to a link
	            }
	            else {
	                // set the value to the input box
	                selectItem(li, { eventType: "blur" });
	            }
	        }
	    }

	    // track whether the field has focus
	    hasFocus = false;
	    if (!mouseDownOnSelect) {
	        hideResults();
	    }
	});

    hideResultsNow();

    function onChange() {
        // ignore if the following keys are pressed: [del] [shift] [capslock]
        valueSelected = false;
        if (lastKeyPressCode == 46 || (lastKeyPressCode > 8 && lastKeyPressCode < 32)) return $results.hide();
        var v = $input.val();
        if (v == prev) return;
        prev = v;
        if (v.length >= options.minChars) {
            resultHidden = false;
            requestData(v);
        } else {
            resultHidden = true;
            $results.hide();
        }
    };

    function moveSelect(step) {

        var lis = $("li", results);
        if (!lis) return;

        active += step;

        if (active < 0) {
            active = 0;
        } else if (active >= lis.size()) {
            active = lis.size() - 1;
        }

        lis.removeClass("ac_over");

        $(lis[active]).addClass("ac_over");

    };

    function selectCurrent() {
        var li = $("li.ac_over", results)[0];
        var non_search_li = $("li.ac_over a")[0];

        if (non_search_li) {
            redirectNonSearchLi($(non_search_li).attr("href"));
            return true;
        }

        if (!li) {
            var $li = $("li", results);
            if (options.selectOnly) {
                if ($li.length == 1) li = $li[0];
            } else if (options.selectFirst) {
                li = $li[0];
            }
        }

        if (li) {
            var misspelling = (li.misspelling == 1 ? true : false);

            // bypass for misspellings - fails for some misspellings eg. 'newy' for 'new ' ('new york') or 'singapoor' & 'singapore'
            if ((!misspelling) && (removeAccents(li.selectValue.toLowerCase().substring(0, $input.val().length)) != removeAccents($input.val().toLowerCase()))) {
                return false;
            }

            selectItem(li);

            return true;
        } else {
            return false;
        }
    };

    function selectItem(li, extraData) {
        if (!li) {
            li = document.createElement("li");
            li.extra = [];
            li.selectValue = "";
        }

        var v = $.trim(li.selectValue ? li.selectValue : li.innerHTML);
        input.lastSelected = v;
        prev = v;

        $("ul", $results).remove();
        $input.val(v);
        hideResultsNow();
        if (options.onItemSelect) {
            setTimeout(function () { options.onItemSelect(li, extraData) }, 1);
        }
    };

    function showResults() {
        var iWidth = (options.width > 0) ? options.width : $input.width();

        //Need to calculate the offset differently depending on how the autocomplete is attached
        if (options.attachedToBody) {
            $results.css({
                width: parseInt(iWidth) + "px",
                top: ($input.offset().top + input.offsetHeight - 1) + "px",
                left: $input.offset().left + xAdj + "px"
            }).show();
        } else {
            $results.css({
                width: parseInt(iWidth) + "px",
                top: ($input.position().top + input.offsetHeight - 1) + "px",
                left: $input.position().left + xAdj + "px"
            }).show();
        }

    };

    function hideResults() {
        if (timeout) clearTimeout(timeout);
        hideResultsNow();
    };

    function hideResultsNow() {
        if (hidingResults) {
            return;
        }
        hidingResults = true;

        if (timeout) {
            clearTimeout(timeout);
        }

        var v = $input.val();

        if ($results.is(":visible")) {
            $results.hide();
        }

        if (options.mustMatch) {
            if (!input.lastSelected || input.lastSelected != v) {
                selectItem(null);
            }
        }

        hidingResults = false;
    };

    function receiveData(q, data) {

        $("ul", $results).remove();
        if (data) {
            if (!hasFocus || data.length == 0) return hideResultsNow();
        }

        $results.append(dataToDom(data));
        showResults();
    };

    function parseData(data) {

        if (!data) return null;
        var parsed = [];
        var rows = data.split(options.lineSeparator);
        for (var i = 0; i < rows.length; i++) {
            var row = $.trim(rows[i]);
            if (row) {
                parsed[parsed.length] = row.split(options.cellSeparator);
            }
        }
        return parsed;
    };

    function dataToDom(data) {
        var ul = document.createElement("ul");
        var num = 0;

        if (data != null) {
            num = data.length;
        }

        // limited results to a max number
        if ((options.maxItemsToShow > 0) && (options.maxItemsToShow < num)) num = options.maxItemsToShow;


        for (var i = 0; i < num; i++) {
            var row = data[i];
            var li = document.createElement("li");
            var extra = null;

            if (i > 0) {
                var lastrow = data[i - 1];
            }

            // skip if multiple misspellings
            if ((!row) || ((i > 0) && (row[3] == lastrow[3]))) {

                continue;
            }

            if (options.formatItem) {
                li.innerHTML = options.formatItem(row, 0, num, true);
                li.selectValue = options.formatItem(row, 0, num, false);
                li.otherValue = row[1];
                li.misspelling = row[4];
            } else {
                li.innerHTML = row[0];
                li.selectValue = row[0];
                li.otherValue = row[1];
                li.misspelling = row[4];
            }

            if (row.length > 1) {
                extra = [];
                for (var j = 1; j < row.length; j++) {
                    extra[extra.length] = row[j];
                }
            }

            li.extra = extra;
            ul.appendChild(li);

            $(li).hover(
				function () {
				    $("li", ul).removeClass("ac_over");
				    $(this).addClass("ac_over");
				    active = $("li", ul).indexOf($(this).get(0));
				},
				function () {
				    $(this).removeClass("ac_over");
				}
			).click(function (e) {
			    e.preventDefault();
			    e.stopPropagation();
			    selectItem(this)
			});

            if (i == 0) {
                $(li).addClass("ac_over");
                active = 0;
            }
        }


		if (options.showBrowseByCountry){

		} else {	
	        browseLink(ul, num);
	    }

        $(ul).mousedown(function () {
            mouseDownOnSelect = true;
        }).mouseup(function () {
            mouseDownOnSelect = false;
        });

        return ul;
    };

    function requestData(q) {

        var data = null;
        if (!options.affiliate) {
            currentAjax = $.ajax({
                mode: "sync",
                port: "autocomplete" + input.name,
                url: makeUrl(q),
                success: function (data) {
                    if (valueSelected) return;
                    if ($input.val().length < options.minChars) return;
                    data = parseData(data);
                    receiveData(q, data);
                }
            });
        } else {
            var resultTag = document.getElementById("acResultDiv");
            if (resultTag) {
                var scriptTag = document.createElement("script");
                resultTag.appendChild(scriptTag);
                scriptTag.src = makeUrl(q);
            }
        }
    };

    function browseLink(ul, num) {
        // trailing link - browse/see all link item
        var languageCode = "EN";
        var browse = document.createElement("li");
        var browseText = $("#browseText").val();

        if (!(typeof HC.gLanguageCode == "undefined")) {
            languageCode = HC.gLanguageCode;
        }

        if (num == 0) {
            browse.className = "lastlink sgle";
        }
        else {
            browse.className = "lastlink";
        }

        //Workout what parameters to pass across
        var params = "";
        var link = '<a id="browselink" href="[domain]/BrowseByCountry.aspx?[params]">' + browseText + '</a>';
        if (typeof languageCode == undefined) {
            params = "languageCode=EN";
        } else {
            params = "languageCode=" + languageCode;
        }


        if (!options.affiliate) {
            browse.innerHTML = link.replace("[domain]", "").replace("[params]", params);

        } else {

            if (options.affiliateData) {

                //If they have a domain use that
                var finalDomain = "www.hotelscombined.com"; ;
                var brandDomain = options.affiliateData.domain;
                if (brandDomain && brandDomain != "") {

                    finalDomain = brandDomain;

                } else {

                    var brandId = options.affiliateData.brandId;
                    if (brandId && brandId != "") {
                        params += "&brandId" + brandId;
                    }
                    params += "&a_aid=" + options.affiliateData.affiliateId;
                }

                browse.innerHTML = link.replace("[domain]", "http://" + finalDomain).replace("[params]", params);

            } else {

                return;

            }

        }

        browse.selectValue = " ";
        browse.extra = "";

        if (num == 0) {
            $(browse).addClass("ac_over");
            active = 0;
        }

        $(browse).hover(
			function () {
			    $("li", ul).removeClass("ac_over");
			    $(this).addClass("ac_over");
			},
			function () {
			    $(this).removeClass("ac_over");
			}
		);

        ul.appendChild(browse);
    };

    // affiliate-specific callback function
    this.success = function (data, q) {

        if (valueSelected) return;
        if ($input.val().length < options.minChars) return;
        // data = parseData(data); // do we need this here?
        receiveData(q, data);
    }

    function makeUrl(q) {
        var sep = options.url.indexOf('?') == -1 ? '?' : '&';
        var url = options.url + sep + "query=" + encodeURI(q);
        for (var i in options.extraParams) {
            url += "&" + i + "=" + encodeURI(options.extraParams[i]);
        }
        return url;
    };

    this.setExtraParams = function (p) {
        options.extraParams = p;
    };

    this.disable = function () {
        enabled = false;
    };

    this.enable = function () {
        enabled = true;
    };

    function removeAccents(strAccents) {
        strAccents = strAccents.split('');
        strAccentsOut = new Array();
        strAccentsLen = strAccents.length;
        var accents = 'ÀÁÂÃÄÅàáâãäåÒÓÔÕÕÖØòóôõöøÈÉÊËèéêëðÇçÐÌÍÎÏìíîïÙÚÛÜùúûüÑñŠšŸÿýŽž';
        var accentsOut = ['A', 'A', 'A', 'A', 'A', 'A', 'a', 'a', 'a', 'a', 'a', 'a', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'o', 'o', 'o', 'o', 'o', 'o', 'E', 'E', 'E', 'E', 'e', 'e', 'e', 'e', 'e', 'C', 'c', 'D', 'I', 'I', 'I', 'I', 'i', 'i', 'i', 'i', 'U', 'U', 'U', 'U', 'u', 'u', 'u', 'u', 'N', 'n', 'S', 's', 'Y', 'y', 'y', 'Z', 'z'];
        for (var y = 0; y < strAccentsLen; y++) {
            if (accents.indexOf(strAccents[y]) != -1) {
                strAccentsOut[y] = accentsOut[accents.indexOf(strAccents[y])];
            }
            else
                strAccentsOut[y] = strAccents[y];
        }
        strAccentsOut = strAccentsOut.join('');
        return strAccentsOut;
    }

    function redirectNonSearchLi(link) {
        if ((typeof (link) != 'undefined') && (link != "")) {
            var absolutePath = link.indexOf("http");
            if (absolutePath != -1) {
                window.location.href = link;
            }
            else {
                var base = window.location.protocol + "//" + window.location.host;
                link = link.replace(base, ""); // for IE
                window.location.href = base + link;
            }
        }
    };

}

jQuery.fn.autocomplete = function(url, options, data) {
    options = options || {};
    options.url = url;
    options.data = ((typeof data == "object") && (data.constructor == Array)) ? data : null;

    // Set default values for required options
    options = $.extend({
        inputClass: "ac_input",
        resultsClass: "ac_results",
        lineSeparator: "\n",
        cellSeparator: "|",
        minChars: 3,
        delay: 10,
        mustMatch: 0,
        extraParams: {},
        loadingElement: null,
        selectFirst: true,
        selectOnly: true,
        maxItemsToShow: 10,
        width: 0,
        useiframe: false,
        affiliate: false,
        attachedToBody: false
    }, options);
    options.width = parseInt(options.width, 10);
    this.each(function() {
        var input = this;
        new jQuery.autocomplete(input, options);
    });

    // Don't break the chain
    return this;
}

jQuery.fn.autocompleteArray = function(data, options) {
    return this.autocomplete(null, options, data);
}

jQuery.fn.indexOf = function(e) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] == e) return i;
    }
    return -1;
};

function bind(element, options) {
    function searchTermTypeEnum() { }
    searchTermTypeEnum = { City: 1, Location: 2, Area: 3, State: 4, Country: 5 }

    var languageCode = "EN";
    if (options.languageCode != undefined && options.languageCode != "") {
        languageCode = options.languageCode;
    } else if (!(typeof HC.gLanguageCode == "undefined")) {
        languageCode = HC.gLanguageCode;
    }

    if ($("#selectSearchTermType").length == 0 && options.searchTermFilter == undefined) {
        //Mainly for affiliates using old search box html. 
        //If they dont have the hidden field then they can not search upon destinations other than the standard.
        options.searchTermFilter = [1, 2, 4];
    }

    var minimumNoChars = 3;
    if(languageCode == "JA" || languageCode == "CS" || languageCode == "CN") 
    {
        //In Chinese and Japanese languages a lot of places can be spelt with just 2 chars.
        //This will set autocomplete to search for a destination in these languages with just 1 chars.
        minimumNoChars = 1;
    }

    options = options || {};
    options = $.extend({
              width:280,
              useiframe: false,
              affiliate: false,
              searchTermFilter: "",
              attachedToBody:false
          }, options);

    var affiliateData;
    if (options.affiliateId || options.brandDomain) {
        affiliateData = { brandId: options.brandId, affiliateId: options.affiliateId, domain: options.brandDomain };
    }
          
    var url = (options.affiliate)?"http://www.hotelscombined.com/AutoComplete.ashx":"/AutoComplete.ashx";
    $(element).autocomplete(url, {
        maxItemsToShow: 10,
        selectFirst: true,
        selectOnly: true,
        onItemSelect: function (item, extraData) {
            $("#selectedLocationID").val("");
            $("#selectedCountryCode").val("");
            $("#selectSearchTermType").val(item.extra[1]);
            if (item.extra[1] == searchTermTypeEnum.Location) {
                $("#selectedLocationID").val(item.extra[2]);
            } else if (item.extra[1] == searchTermTypeEnum.Country) {
                $("#selectedCountryCode").val(item.extra[2]);
            } else if (item.extra[1] == searchTermTypeEnum.City) {
                $("#selectedCityID").val(item.extra[2]);
            }
            $("#selectedFileName").val(item.extra[0]);
            $("#selectedCityName").val(jQuery.trim(item.selectValue));
            if (!(extraData && extraData.eventType == "blur")) {
                $(element).focus();
            }
        },
        formatItem: function (row, i, num, displayHtml) {
            var originalLength = row[i].split(",").length;
            var display = row[i].ellipsisString(47);
            var parts = display.split(",");
            var result = "";
			
			var part0 = parts[0];
			var misspelling = (row[4] == 1)?true:false;
			var altRealName = parts[0].split(" - ");
			
			// parse alternative name &/or misspelling
			if (misspelling) { 
				if (altRealName.length == 2) {
					// check abbreviation or code (i.e. airport code)
					var abbreCode = true;
					if (altRealName[0].length == 3) {
						for (var u = 0; u < 3; u++) {
							if (altRealName[0].charAt(u) != altRealName[0].charAt(u).toUpperCase()) {
								codeUpper = false;
								break;
							}
						}
					}
					else {
						abbreCode = false;
					}
					
					if (displayHtml) {
						if (abbreCode) {
							part0 = "<em>" + altRealName[0] + " (" + altRealName[1] + ")</em>";
						}
						else {
							part0 = "<em>" + altRealName[1] + "</em>";
						}
					}
					else {
						if (abbreCode) {
							part0 = altRealName[0] + " (" + altRealName[1] + ")";
						}
						else {
							part0 = altRealName[1];							
						}
					}
				}
				else {
					if (displayHtml) {
						part0 = "<em>" + altRealName[0] + "</em>";
					}
					else {
						part0 = altRealName[0];
					}
				}
			}
			else {
				part0 = altRealName[0];
			}
			
            if (parts.length > 2) {
                result = part0 + ", " + parts[1] + ", " + (displayHtml ? "<b>" + parts[2] + "</b>" : parts[2]);
            } 
			else if (parts.length == 2 && originalLength == 3) {
                result = part0 + ", " + parts[1];
            } 
			else if (parts.length == 2 && altRealName.length == 2 && !misspelling) {
			    part0 = altRealName[0] + ' - ' + altRealName[1];
                result = part0 + ", " + parts[1];
            } 
			else if (parts.length == 2) {
                if (row[2] == searchTermTypeEnum.Country) {
                    result = (displayHtml ? "<b>" + part0 + "</b>" : part0);
                } 
				else {
                    result = part0 + ", " + (displayHtml ? "<b>" + parts[1] + "</b>" : parts[1]);
                }
            } 
			else {
                result = (displayHtml ? "<b>" + part0 + "</b>" : part0);
            }
			
			return result;

        },
        width: options.width,
        useiframe: options.useiframe,
        affiliate: options.affiliate,
        affiliateData: affiliateData,
        maxItemsToShow: options.maxItemsToShow,
        showBrowseByCountry: options.showBrowseByCountry,
        minChars: minimumNoChars,
        extraParams: {
            languageCode: languageCode,
            format: (options.affiliate) ? "script" : "text",
            limit: "10", 
            searchTermFilter: (options.searchTermFilter !== undefined) ? options.searchTermFilter : "" },
        attachedToBody: options.attachedToBody
    });
}


