function SearchObject(settings) {

    this.searchInputElement = settings.searchInputElement;
    this.autoSuggestElement = settings.autoSuggestElement;
    this.searchGoButton = settings.searchGoButton;
    this.trackingValue = settings.trackingValue;
    this.advSearchToggleElement = settings.advSearchToggleElement;
    this.advSearchXElement = settings.advSearchXElement;
    this.searchArea = settings.searchArea;
    this.advSearchInputs = settings.advSearchInputs;
    this.dateStartElement = settings.dateStartElement;
    this.dateEndElement = settings.dateEndElement;
    this.locationSelects = settings.locationSelects;
    this.zipInputElement = settings.zipInputElement;
    this.categoryCheckboxes = settings.categoryCheckboxes;
    this.searchType = settings.searchType;
    this.prefillFormItems = settings.prefillFormItems;

    this.customCharacters = [['(andamp)', '&'], ['(anddash)', '-']];

    this.suggNum = (settings.suggNum === undefined) ? 15 : settings.suggNum;
    this.significantCharacters = (settings.significantCharacters === undefined) ? 2 : settings.significantCharacters;

    this.useAdvSearch = (settings.useAdvSearch === undefined) ? false : settings.useAdvSearch;
    this.autoCompleteSuggestList = new Array();
    this.autoCompleteCurrentlyFetchingList = '';
    this.redirected = false;
    this.selectedItem = null;
    this.searchTxt = '';
    this.targetIsAutobox = false;
    this.boxText = '';  //used specifically for escape button

    if (this.locationSelects != undefined && this.locationSelects.citySelectElement != undefined)
        this.locationSelects.citySelectOptions = new Object();

    this.Initialize = function () {
        if (this.advSearchToggleElement != undefined)
            if (navigator.userAgent.indexOf('Opera') != -1)
                this.advSearchToggleElement.hide();

        //OPTIONAL search term input
        if (this.searchInputElement != undefined) {
            if (this.searchInputElement.val() == '')
                this.searchInputElement.val(this.searchInputElement.attr('initialtxt'));
            else if (this.searchInputElement.val() != this.searchInputElement.attr('initialtxt'))
                this.searchInputElement.addClass("focus");

            this.searchInputElement.attr('satellite', 'false');

            this.searchInputElement.focus(
                function (event) {
                    if ($(this).val() == $(this).attr('initialtxt')) {
                        $(this).val('');
                        $(this).addClass('focus');
                    }
                }
            );

            this.searchInputElement.blur({ associatedSearchObject: this },
                function (event) {
                    var aso = event.data.associatedSearchObject;

                    if ($(this).val() == '') {
                        $(this).val($(this).attr('initialtxt'));
                        $(this).removeClass('focus');
                    }
                    if (!aso.targetIsAutobox)
                        aso.closeAutoBox();
                }
            );

            // triggers every time a key is hit on the search textbox
			//NOTE: This will not handle pressing arrow key down/up to navigate auto-suggest list
			//NOTE: 13 is the enter event
            this.searchInputElement.keypress({ associatedSearchObject: this },
                function (event) {
                    var aso = event.data.associatedSearchObject;
					
					//enter key
                    if (event.which == 13 && ($(this).val().length > 0 || aso.useAdvSearch)) {
                        if (aso.autoSuggestElement != undefined && !aso.autoSuggestElement.is(':hidden') && aso.useAdvSearch)
                            aso.finalizeChoice();
                        else {
                            if (aso.autoSuggestElement != undefined)
                                aso.closeAutoBox();

                            aso.searchGoButton.click();
                        }
                    }
                    //tab key
                    else if (event.which == 9 && !aso.useAdvSearch) {
                        //don't let tab go to next (hidden) input
                        event.preventDefault();
                    }
                }
            );

            //OPTIONAL autosuggest box
            if (this.autoSuggestElement != undefined) {
                this.searchInputElement.keydown({ associatedSearchObject: this },
                    function (event) {
                        var aso = event.data.associatedSearchObject;

                        //up arrow
                        if (event.keyCode == 38 && aso.autoCompleteSuggestList.length > 0) {
                            if (aso.autoSuggestElement.is(':hidden') && aso.selectedItem != null)
                                aso.openAutoBox();
                            else {
                                //don't use selectedItem to choose next item... use .selected class
                                //these might not be the same because of mouse hover
                                aso.openAutoBox();  //still need to open it for null case
                                var visualSelection = aso.autoSuggestElement.find('.selected');

                                if (visualSelection.length == 0)
                                    visualSelection = aso.selectedItem;

                                if (visualSelection == null)
                                    aso.selectedItem = aso.autoSuggestElement.find('label:last');
                                else if (visualSelection.attr('text') == aso.autoSuggestElement.find('label:first').attr('text')) {
                                    aso.selectedItem = null;
                                    aso.visualSelect(aso.selectedItem); //always reset for null, even for advsearch
                                }
                                else
                                    aso.selectedItem = visualSelection.prev();

                                if (!aso.useAdvSearch)
                                    aso.alterSearchText(aso.selectedItem); //we're still using selectedItem for everything; visualSelection is just to take care of discrepancies between keypress and hover
                            }
                            aso.visualSelect(aso.selectedItem);
                        }
                        //down arrow
                        else if (event.keyCode == 40 && aso.autoCompleteSuggestList.length > 0) {
                            if (aso.autoSuggestElement.is(':hidden') && aso.selectedItem != null)
                                aso.openAutoBox();
                            else {
                                //don't use selectedItem to choose next item... use .selected class
                                //these might not be the same because of mouse hover
                                aso.openAutoBox();  //still need to open it for null case
                                var visualSelection = aso.autoSuggestElement.find('.selected');

                                if (visualSelection.length == 0)
                                    visualSelection = aso.selectedItem;

                                if (visualSelection == null)
                                    aso.selectedItem = aso.autoSuggestElement.find('label:first');
                                else if (visualSelection.attr('text') == aso.autoSuggestElement.find('label:last').attr('text')) {
                                    aso.selectedItem = null;
                                    aso.visualSelect(aso.selectedItem); //always reset for null, even for advsearch
                                }
                                else
                                    aso.selectedItem = visualSelection.next();

                                if (!aso.useAdvSearch)
                                    aso.alterSearchText(aso.selectedItem); //we're still using selectedItem for everything; visualSelection is just to take care of discrepancies between keypress and hover
                            }
                            aso.visualSelect(aso.selectedItem);
                        }
                        //escape key
                        else if (event.keyCode == 27) {
                            if (!aso.useAdvSearch) {
                                aso.resetSearchText();
                                aso.boxText = aso.searchTxt;
                            }
                            //save what's in the box now and go back to that (adv search)
                            else
                                aso.boxText = $(this).val();
                        }
                        //tab key
                        else if (event.keyCode == 9 && !aso.useAdvSearch) {
                            //don't let tab go to next (hidden) input
                            event.preventDefault();
                        }
                    }
                );

                this.searchInputElement.keyup({ associatedSearchObject: this },
                    function (event) {
                        var aso = event.data.associatedSearchObject;

                        //not down arrow, up arrow, or escape key
                        if ($(this).val() != aso.searchTxt && event.keyCode != 38 && event.keyCode != 40 && event.keyCode != 27) {
                            aso.searchTxt = $(this).val();

                            if ($(this).val().length >= (aso.significantCharacters)) {
                                aso.selectedItem = null;
                                var curSuggestSet = null;

                                // get the current 3 letter start to the string
                                var curSearchSeed = $(this).val().substring(0, aso.significantCharacters);
                                var curSearchText = $(this).val();

                                var curSeedIndex = -1;

                                if (aso.autoCompleteCurrentlyFetchingList.indexOf(curSearchSeed) < 0) {
                                    // first add it to the list so that if the user types again before the ajax is done, there will not be
                                    //      a double entry
                                    aso.autoCompleteCurrentlyFetchingList += curSearchSeed + "||";

                                    var unsafeChars = /<[\/\w]/g; //aka, the beginning of an html tag (closing or opening)
                                    //since this is a querystring variable pass we just need to keep html tags out of
                                    //the autocomplete search (it will throw an error and stop working)
                                    if (!curSearchSeed.match(unsafeChars)) {
                                        var encodedSeed = urlEncode(curSearchSeed);
                                        // call ajax autosuggest
                                        $.get(
                                            autoSuggestUrl + "?srchSeed=" + encodedSeed + (aso.searchType != undefined ? "&srchType=" + aso.searchType : ""),
                                            function (data) {
                                                if (data != '')
                                                    curSuggestSet = eval('(' + data + ')');
                                                else
                                                    curSuggestSet = eval('({searchedLetters: "' + curSearchSeed + '", relatedEntities: []})');
                                                curSeedIndex = aso.autoCompleteSuggestList.push(curSuggestSet) - 1;
                                                curSearchText = aso.searchInputElement.val();
                                                var curSuggestList = aso.NarrowDownSuggestList(aso.autoCompleteSuggestList[curSeedIndex].relatedEntities, curSearchText);
                                                // ok now time to show the div, update it
                                                aso.UpdateAndShowSuggestDiv(curSuggestList[0], curSuggestList[1]);
                                            }
                                        );
                                    }
                                }
                                else {
                                    try {
                                        for (var i = 0; i < aso.autoCompleteSuggestList.length; i++) {
                                            if (aso.autoCompleteSuggestList[i].searchedLetters == curSearchSeed) {
                                                curSeedIndex = i;
                                                break;
                                            }
                                        }
                                        // this could fail if the ajax has not finished loading the seed index yet
                                        var curSuggestList = aso.NarrowDownSuggestList(aso.autoCompleteSuggestList[curSeedIndex].relatedEntities, curSearchText);
                                        aso.UpdateAndShowSuggestDiv(curSuggestList[0], curSuggestList[1]);
                                    }
                                    catch (e) {
                                    }
                                }
                            }
                            //if there are less than the needed letters close the box (will take care of backspace, etc.)
                            else
                                aso.closeAutoBox();
                        }
                        //escape key
                        else if (event.keyCode == 27) {
                            aso.autoSuggestElement.hide();
                            $(this).val(aso.boxText);
                        }
                        //tab key
                        else if (event.keyCode == 9 && !aso.useAdvSearch) {
                            //don't let tab go to next (hidden) input
                            event.preventDefault();
                        }
                    }
                );
            }
            else {
                this.searchInputElement.keydown({ associatedSearchObject: this },
                    function (event) {
                        var aso = event.data.associatedSearchObject;

                        //tab key
                        if (event.keyCode == 9 && !aso.useAdvSearch) {
                            //don't let tab go to next (hidden) input
                            event.preventDefault();
                        }
                    }
                );
                this.searchInputElement.keyup({ associatedSearchObject: this },
                    function (event) {
                        var aso = event.data.associatedSearchObject;

                        //tab key
                        if (event.keyCode == 9 && !aso.useAdvSearch) {
                            //don't let tab go to next (hidden) input
                            event.preventDefault();
                        }
                    }
                );
            }
        }

        this.searchGoButton.click({ associatedSearchObject: this },
            function (event) {
                var aso = event.data.associatedSearchObject;

                if (aso.searchInputElement != undefined) {
					
					/*Check the input element for the case where the user clicks or highlights and presses enter on a suggestion*/
					var url = aso.searchInputElement.attr('resultsUrl');
					if(url != undefined) 
						location.href = url;
					else {
						/*The case where the user has typed something, but not interacted with the auto-suggest list*/
						var autoItems = aso.autoSuggestElement.children().filter(function(index){return $(this).attr('text').toLowerCase() == aso.searchInputElement.val().toLowerCase()});
						
						if(autoItems.length > 0) {
							url = autoItems.attr('resultsurl');
							
							if(url != undefined)
								location.href = url;
							else
								aso.RedirFromSearchTerm(aso.searchInputElement.val(), aso.searchInputElement.attr('satellite'));
						}
						else
							aso.RedirFromSearchTerm(aso.searchInputElement.val(), aso.searchInputElement.attr('satellite'));
					}
				}
                else
                    aso.RedirFromSearchTerm('all', false);
            }
        );

        //OPTIONAL advanced search X (close) element
        if (this.advSearchXElement != undefined) {
            this.advSearchXElement.click({ associatedSearchObject: this },
                function (event) {
                    event.data.associatedSearchObject.advSearchToggleElement.click();
                }
            );
        }

        //OPTIONAL advanced search toggle element
        if (this.advSearchToggleElement != undefined) {
            this.advSearchToggleElement.click({ associatedSearchObject: this },
                function (event) {
                    var aso = event.data.associatedSearchObject;

                    if (aso.advSearchXElement != undefined)
                        aso.advSearchXElement.toggle();

                    if (aso.useAdvSearch) {
                        $(this).text($(this).attr('simpleText'));

                        if (aso.searchArea != undefined)
                            aso.searchArea.element.animate({ height: aso.searchArea.simpleHeight }, 500);

                        if (aso.advSearchInputs != undefined)
                            aso.advSearchInputs.element.animate({ height: aso.advSearchInputs.closedHeight }, 500);

                        aso.useAdvSearch = false;
                    }
                    else {
                        $(this).text($(this).attr('advText'));

                        if (aso.searchArea != undefined)
                            aso.searchArea.element.animate({ height: aso.searchArea.advHeight }, 500);

                        if (aso.advSearchInputs != undefined)
                            aso.advSearchInputs.element.animate({ height: aso.advSearchInputs.openHeight }, 500);

                        aso.useAdvSearch = true;
                    }
                }
            );
        }

        //OPTIONAL dateRange elements
        if (this.dateStartElement != undefined && this.dateEndElement != undefined) {
            this.dateStartElement.datepicker({ minDate: 0 });
            var advMinDate = (this.dateStartElement.val() != '') ? new Date(this.dateStartElement.val()) : 0;

            this.dateEndElement.datepicker({ minDate: advMinDate });

            this.dateStartElement.attr('affectedEndElement', this.dateEndElement.attr('id'));
            this.dateStartElement.datepicker('option', 'onSelect', function (theDate) {
                $('#' + $(this).attr('affectedEndElement')).datepicker('option', 'minDate', new Date(theDate));
            });
        }

        //OPTIONAL location select elements
        if (this.locationSelects != undefined) {
            //first, we need to create the necessary state/city selects
            var locationsDoc = loadXMLDoc('/tnxml/united-states-cities.xml');
            var stateOptions = '';
            var states = locationsDoc.getElementsByTagName('state');

            for (var i = 0; i < states.length; i++) {
                var stateName = states[i].getAttribute('name');
                var stateSpid = states[i].getAttribute('spid');
                stateOptions += '<option value="' + stateSpid + '">' + stateName + '</option>';
                var citySelect = '<option value="">-- Select a City --</option>';

                for (var j = 0; j < states[i].childNodes.length; j++) {
                    if (states[i].childNodes[j].nodeName == "city") {
                        var cityNameValue = states[i].childNodes[j].getAttribute('name').replace(/\s/g, "+");
                        //specific changes for some city names
                        switch (cityNameValue) {
                            case 'New+York+City':
                                cityNameValue = 'New+York';
                                break;
                            case 'Washington+D.C.':
                                cityNameValue = 'Washington';
                                break;
                        }
                        var cityName = states[i].childNodes[j].getAttribute('name');
                        citySelect += '<option value="' + cityNameValue + '">' + cityName + '</a><br />';
                    }
                }
                this.locationSelects.citySelectOptions[stateSpid] = citySelect;
            }

            this.locationSelects.stateSelectElement.append(stateOptions);

            this.locationSelects.stateSelectElement.change({ associatedSearchObject: this },
                function (event) {
                    var aso = event.data.associatedSearchObject;
                    var spid = $(this).val();

                    if (spid == '0') {
                        aso.locationSelects.citySelectElement.attr('disabled', true);
                        aso.locationSelects.citySelectElement.html('<option value="">-- Select a City --</option>');
                    }
                    else {
                        aso.locationSelects.citySelectElement.html(aso.locationSelects.citySelectOptions[spid]);
                        aso.locationSelects.citySelectElement.attr('disabled', false);
                    }
                }
            );
        }

        //OPTIONAL zipcode input
        if (this.zipInputElement != undefined) {
            if (this.zipInputElement.val() == '')
                this.zipInputElement.val(this.zipInputElement.attr('initialtxt'));

            this.zipInputElement.focus(
                function () {
                    if ($(this).val() == $(this).attr('initialtxt'))
                        $(this).val('');
                }
            );

            this.zipInputElement.blur(
                function () {
                    if ($(this).val() == '')
                        $(this).val($(this).attr('initialtxt'));
                }
            );

            this.zipInputElement.keypress({ associatedSearchObject: this },
                function (event) {
                    if (event.which == 13)
                        event.data.associatedSearchObject.searchGoButton.click();
                }
            );
        }

        //OPTIONAL category checkboxes
        if (this.categoryCheckboxes != undefined) {
            $('.' + this.categoryCheckboxes.checkboxClass).click({ associatedSearchObject: this },
                function (event) {
                    var aso = event.data.associatedSearchObject;
                    //however, we are going to use a version where 'All' is checked independently - like on search page
                    if ($(this).attr('id') == aso.categoryCheckboxes.allCheckboxID) {
                        $(this).attr('checked', true);
                        $('.' + aso.categoryCheckboxes.checkboxClass + ':not(#' + aso.categoryCheckboxes.allCheckboxID + ')').attr('checked', false);
                    }
                    //otherwise, make sure that the 'All' checkbox correctly reflects the status of the checkboxes
                    else {
                        //to keep consistency with search page, we will only re-check 'All' if everything has been unchecked
                        var allElseUnChecked = true;
                        $('.' + aso.categoryCheckboxes.checkboxClass + ':not(#' + aso.categoryCheckboxes.allCheckboxID + ')').each(function () {
                            if ($(this).is(':checked'))
                                allElseUnChecked = false;
                        });
                        $('#' + aso.categoryCheckboxes.allCheckboxID).attr('checked', allElseUnChecked);
                    }
                }
            );
        }

        //Prefill all specified form items
        if (this.prefillFormItems != undefined) {
            //put the values from the querystring in, or initialTxt
            var queryString = GetQueryStringObj();
            var searchPage = !location.pathname.search("/ticket/(.*)-events\\.aspx");

            if (searchPage) {
                //search term
                if (this.prefillFormItems.searchInput == true && this.searchInputElement != undefined) {
                    var inputValue = this.searchInputElement.val();

                    if (inputValue == '' || inputValue == this.searchInputElement.attr('initialtxt')) {
                        var searchedTerm = urlDecode(location.pathname).replace(new RegExp("/ticket/(.*)-events\\.aspx"), "$1").replace(/-/g, " ");
                        for (var index = 0; index < this.customCharacters.length; index++) {
                            searchedTerm = searchedTerm.replace(new RegExp(RegExp.escape(this.customCharacters[index][0]), "g"), this.customCharacters[index][1]);
                        }

                        if (searchPage && searchedTerm != 'all') {
                            this.searchInputElement.val(searchedTerm);
                            this.searchInputElement.addClass('focus');
                        }
                    }
                }

                if (queryString) {
                    //date range
                    if (this.prefillFormItems.dateStartInput == true && this.dateStartElement != undefined)
                        if (queryString['startDate'] && this.dateStartElement.val() == '')
                            this.dateStartElement.val(urlDecode(queryString['startDate']));

                    if (this.prefillFormItems.dateEndInput == true && this.dateEndElement != undefined)
                        if (queryString['endDate'] && $('#adv_hdr_search_end_date').val() == '')
                            this.dateEndElement.val(urlDecode(queryString['endDate']));

                    //zipcode
                    if (this.prefillFormItems.zipInput == true && this.zipInputElement != undefined) {
                        var inputValue = this.zipInputElement.val();

                        if (queryString['zip'] && (inputValue == '' || inputValue == this.zipInputElement.attr('initialtxt')))
                            this.zipInputElement.val(urlDecode(queryString['zip']));
                    }

                    //state/city selects
                    if (this.prefillFormItems.locationSelects == true && this.locationSelects != undefined) {
                        if (queryString['spid'] && queryString['ctyname']) {
                            this.locationSelects.stateSelectElement.val(queryString['spid']);
                            this.locationSelects.stateSelectElement.change(); //perform change function to determine the correct 'on top' city select
                            this.locationSelects.citySelectElement.val(queryString['ctyname']);
                        }
                    }

                    //category checkboxes
                    if (this.prefillFormItems.categoryCheckboxes == true && this.categoryCheckboxes != undefined) {
                        if (queryString['pcid'] && $('.' + aso.categoryCheckboxes.checkboxClass + ':not(#' + aso.categoryCheckboxes.allCheckboxID + '):checked').length == 0) {
                            //if we have a query string, we need to uncheck 'All', then check each category that's specified
                            $('#' + aso.categoryCheckboxes.allCheckboxID).attr('checked', false);
                            var checkedCats = queryString['pcid'].split('|');

                            for (var i = 0; i < checkedCats.length; i++) {
                                $('.' + aso.categoryCheckboxes.checkboxClass + '[value=' + checkedCats[i] + ']').attr('checked', true);
                            }
                        }
                    }
                }
            }
        }
    };

    this.Initialize();


    this.NarrowDownSuggestList = function (fullList, refineVal) {
        var retList = new Array();
        var retListClean = new Array();
        var refineReg = new RegExp("(" + refineVal + ")", "gi");

        // get the matches, but only up to 15
        for (var i = 0; i < fullList.length && retList.length <= this.suggNum; i++) {
            if (fullList[i].display.toLowerCase().indexOf(refineVal.toLowerCase()) > -1) {
                retList.push(fullList[i].display.replace(refineReg, "<b>$1</b>"));
                retListClean.push(fullList[i]);
            }
        }

        return new Array(retList, retListClean);
    }


    this.UpdateAndShowSuggestDiv = function (suggestList, textList) {
        var suggListHtml = '';

        for (var i = 0; i < suggestList.length; i++) {
            suggListHtml += '<label class="suggest_option" text="' + textList[i].display + '" satellite="' + textList[i].isSatellite + '"' 
			+ (textList[i].resultsPage.length > 0 ? (' resultsUrl="' + textList[i].resultsPage + '">') : '>');
            suggListHtml += suggestList[i];
            suggListHtml += '</label>';
        }

        this.autoSuggestElement.html(suggListHtml);
        this.autoSuggestElement.show();

        // if there are suggestions, add the handlers to them
        if (suggListHtml.length > 0) {
            $('.suggest_option').mouseover({ associatedSearchObject: this },
                function (event) {
                    event.data.associatedSearchObject.visualSelect($(this));
                }
            );

            this.autoSuggestElement.click({ associatedSearchObject: this },
                function (event) {
                    var aso = event.data.associatedSearchObject;
                    if (aso.useAdvSearch) {
                        aso.selectedItem = $(this).children('.selected');
                        aso.finalizeChoice();
                        aso.searchInputElement.focus();
                    }
                    else {
                        aso.selectedItem = $(this).children('.selected');
                        aso.finalizeChoice();
                        aso.searchGoButton.click();
                    }
                }
            );

            this.autoSuggestElement.mouseup({ associatedSearchObject: this },
                function (event) {
                    event.data.associatedSearchObject.searchInputElement.focus();
                }
            );

            this.autoSuggestElement.mouseover({ associatedSearchObject: this },
                function (event) {
                    event.data.associatedSearchObject.targetIsAutobox = true;
                }
            );

            this.autoSuggestElement.mouseout({ associatedSearchObject: this },
                function (event) {
                    event.data.associatedSearchObject.targetIsAutobox = false;
                }
            );
        }
    }


    this.RedirFromSearchTerm = function (srchTerm, isSatellite) {
        if (!this.redirected) {
            var redirLoc = "";

            if (this.searchInputElement != undefined) {
                if (srchTerm.trim() == this.searchInputElement.attr('initialtxt') || srchTerm.trim() == '') {
                    if (this.useAdvSearch) {
                        if (this.dateEndElement != undefined && this.dateEndElement.val() != "")
                            srchTerm = 'all';
                        else
                            return;
                    }
                    else
                        return;
                }
            }
            else {
                if (!this.useAdvSearch)
                    return;

                var spid = this.locationSelects.stateSelectElement != undefined ? $('#adv_search_state_select').val() : 0;
                var cityName = this.locationSelects.citySelectElement != undefined ? $('#adv_search_city_select').val() : '';
                var zipCode = this.zipInputElement != undefined ? $('#adv_search_zip').val() : '';

                if ((spid == 0 || cityName == '') && zipCode.search("^(\\d{5})(-\\d{4})?$")) {
                    alert("Please enter a valid US zipcode, or pick a city from the dropdown menu.");
                    return;
                }
            }

            this.redirected = true;

            if (this.trackingValue != undefined) {
                try {
                    pageTracker._trackEvent('Event Search', srchTerm.toLowerCase(), this.trackingValue);
                }
                catch (e) {
                }
            }

            srchTerm = srchTerm.trim();
            for (var index = 0; index < this.customCharacters.length; index++) {
                srchTerm = srchTerm.replace(new RegExp(RegExp.escape(this.customCharacters[index][1]), "g"), this.customCharacters[index][0]);
            }
            srchTerm = srchTerm.replace(/[-+]+/g, " ").replace(new RegExp("[^\\d\\w\\s!`~@\\$\\(\\)_=;',\\./\u00C0-\u017E]", "g"), "").replace(/\s+/g, "-");
            //if / is at the front of a search term it will break... we need to remove it in that case
            srchTerm = srchTerm.replace(/^\/+/, "");
            srchTerm = urlEncode(srchTerm); //custom encode that will allow C# to correctly read url
            //if . is in front of an escaped term (%something) the page will have an error - prevent this situation
            srchTerm = srchTerm.replace(/\.%/g, "%");

            redirLoc = searchPageRedirectUrl.replace('@@srchTerm', srchTerm).toLowerCase();

            var queryString = "";

            if (this.useAdvSearch) {
                //zipcode/location
                if (this.zipInputElement != undefined && !zipCode.search("^(\\d{5})(-\\d{4})?$"))
                    queryString += (queryString.length > 0 ? "&" : "") + "zip=" + urlEncode(zipCode);
                else if (this.locationSelects != undefined) {
                    if (cityName == 'New+York')
                        queryString += (queryString.length > 0 ? "&" : "") + "inLoc=New+York+-+Five+Boroughs";
                    else
                        queryString += (queryString.length > 0 ? "&" : "") + "cid=217&spid=" + urlEncode(spid) + '&ctyname=' + cityName;
                }

                //date range
                if (this.dateStartElement != undefined && this.dateEndElement != undefined) {
                    var startDate = this.dateStartElement.val();

                    if (startDate != "")
                        queryString += (queryString.length > 0 ? "&" : "") + "startDate=" + urlEncode(startDate);

                    var endDate = this.dateEndElement.val();

                    if (endDate != "")
                        queryString += (queryString.length > 0 ? "&" : "") + "endDate=" + urlEncode(endDate);
                }

                //category
                if (this.categoryCheckboxes != undefined) {
                    var category = 0;
                    var possibleCats = '';
                    var allElseChecked = true;

                    $('.' + this.categoryCheckboxes.checkboxClass + ':not(#' + this.categoryCheckboxes.allCheckboxID + ')').each(function () {
                        if (!$(this).is(':checked'))
                            allElseChecked = false;
                        else
                            possibleCats += ((possibleCats.length > 0) ? '|' : '') + $(this).val();
                    });
                    //if not 'All' categories are chosen, then we want to change this to the actual categories
                    if (!allElseChecked && !$('#' + this.categoryCheckboxes.allCheckboxID).is(':checked'))
                        category = possibleCats;

                    if (category != 0)
                        queryString += (queryString.length > 0 ? "&" : "") + "pcid=" + urlEncode(category);
                }
            }

            if (isSatellite == 'true')
                queryString += (queryString.length > 0 ? "&" : "") + "satellite=true";

            if (queryString.length > 0)
                redirLoc += "?" + queryString;

            location.href = redirLoc;
        }
    }
    
    
    this.closeAutoBox = function () {
        this.autoSuggestElement.hide();

        if (this.selectedItem != null) {
            this.searchTxt = this.selectedItem.attr('text');
            this.selectedItem.removeClass('selected');
        }
    }


    this.openAutoBox = function () {
        this.autoSuggestElement.show();
    }


    this.visualSelect = function (element) {
        this.autoSuggestElement.find('.selected').removeClass('selected');

        if (element != null)
            element.addClass('selected');
    }


    this.resetSearchText = function () {
        this.searchInputElement.val(this.searchTxt);
        this.searchInputElement.attr('satellite', 'false');
    }


    this.alterSearchText = function (element) {
        if (element != null) {
            this.searchInputElement.val(element.attr('text'));
            this.searchInputElement.attr('satellite', element.attr('satellite'));
			if(element.attr('resultsUrl') != undefined)
				this.searchInputElement.attr('resultsUrl', element.attr('resultsUrl'));
        }
        else
            this.resetSearchText();
    }


    this.finalizeChoice = function () {
        this.closeAutoBox();
        this.alterSearchText(this.selectedItem);
    }


    this.OpenStartDate = function () {
        this.dateStartElement.datepicker('show');
    }


    this.OpenEndDate = function () {
        this.dateEndElement.datepicker('show');
    }
}

