var waitHTML = '<div style="height:600px;"><img src="/_resources/common/images/icon_busy.gif">&nbsp;<b>loading...</b></div>';

var AjaxBackURL;
var IsPreviousPageAjax;

var UseAjaxSearch;
var SearchType;

function RunAjax(xmlHttpReq,element,url,waitHTML){
	if(xmlHttpReq) {
		
		if (xmlHttpReq.readyState != 0){
			xmlHttpReq.abort();
			element.innerHTML = waitHTML;
		}
		
		xmlHttpReq.open("GET", url, true);
		xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		xmlHttpReq.onreadystatechange = function() {
			if(xmlHttpReq.readyState == 4 || xmlHttpReq.readyState=="complete") {
				element.innerHTML = xmlHttpReq.responseText;
				try{
					pageTracker._trackPageview(url);
				}
				catch(err){
					//alert(err);	
				}
				setCookie( 'AjaxBackURL', url.replace('GetSearchResults.asp',''), '', '/', '', '' );
				setCookie( 'IsPreviousPageAjax', 'true', '', '/', '', '' );
				//alert("IsCurrentPageAjax = true");
				//alert("IsPreviousPageAjax = " + IsPreviousPageAjax);
			}
		}
		xmlHttpReq.send("");
	}
	else{
		element.innerHTML = "xmlHttpReq undefined";
	}
}

function ChangeSearchPage(url, obj) {

    if (obj && (!url || url == '')) {
        url = $(obj).attr('value')
    }
    url = unescape(url);

    $.query = $.query.load(window.location + '');
    var PrevPageSize = $.query.GET('pagesize');
    var PrevIsPreferred = $.query.GET('ispreferred');
    var PrevIsGS1 = $.query.GET('isgs1');

    var Keyword = undefined;
    var isPreferred = undefined;
    var isGS1 = undefined;
    var PageSize = undefined;

    if (url && url != undefined && url != 0 && url != '0') {
        $.query = $.query.load(url);
        if ($.query.GET('keyword') == true) {
            /* if keyword is present, but it has no value, remove it */
            $.query.REMOVE('keyword');
        }   
        if ($('.search-options-top input[name=isPreferred]').length == 1) {
            $.query.REMOVE('ispreferred');
            isPreferred = $('.search-options-top input[name=isPreferred]').attr('checked');
            if (isPreferred) {
                $.query.SET('ispreferred', '1');
            }
        }
        if ($('.search-options-top input[name=isGS1]').length == 1) {
            $.query.REMOVE('isgs1');
            isGS1 = $('.search-options-top input[name=isGS1]').attr('checked');
            if (isGS1) {
                $.query.SET('isgs1', '1');
            }
        }
        if ($('.search-options-top select[name=pagesize]').length == 1) {            
            $.query.REMOVE('pagesize');
            PageSize = $('.search-options-top select[name=pagesize]').val();
            if (PageSize != '') {
                $.query.SET('pagesize', PageSize);
            }
        }
        if ((PrevPageSize != '' && PageSize && PrevPageSize != PageSize) || (isPreferred && PrevIsPreferred != isPreferred) || (isGS1 && PrevIsGS1 != isGS1)) {
            $.query.REMOVE('page');
        }
        if ($.query.GET('page') == '1') {
            $.query.REMOVE('page');
        }
        url = url.substring(0, url.indexOf('?')) + $.query.toString();
        var count = 0;
        while (url.indexOf('%2B') > 0 && count < 100) {
            url = url.replace('%2B', '+');
            count++;
        }
        window.location = url;
    }
}

function ChangeSearchSupplier(url,mfgid){
	if(UseAjaxSearch){
		if(getElement("mfgid")){
			getElement("mfgid").value = mfgid;
		}
		SearchUpdate(getElement("SearchForm"),'',url);
	}
	else{
		window.location = url;
	}
}

function SearchUpdate(form,page,url,mfgid){
	
	setCookie( 'AjaxBackURL', '', '', '/', '', '' );
	
	if(page == ''){
		var temp = url;
		if(temp.indexOf('page=') > 0){
			temp = temp.substr(temp.indexOf('page=') + 5,temp.length - temp.indexOf('page='));
			if(temp.indexOf('&') > 0){
				temp = temp.substr(0,temp.length - temp.indexOf('&'));
			}
			if(temp > 0){
				page = temp;
			}
		}	
	}
	
	if(UseAjaxSearch == false){
		//alert("0");
		form.submit();
	}	
	else if(getElement("ResultsPane") && getCookie('search') == "advanced"){						
		//alert("1");
		AdvancedSearchUpdate(form,'','',page);
	}
	else if(getElement('Search_Basic_Link') && getElement('Search_Advanced_Link') && getElement("ResultsPane") && url != ''){
		if((getElement('Search_Basic_Link').display || getElement('Search_Basic_Link').display != 'none') && (getElement('Search_Advanced_Link').display || getElement('Search_Advanced_Link').display != 'none')){
			//alert("2a");
			BasicSearchUpdate(form,page);
		}
		else{
			//alert("2b");
			form.submit(); // submitting the form will refresh the page and remove the selected category from the left nav
		}
	}
	else{
		//alert("3");
		form.submit();		
	}
	
}

function BasicSearchUpdate(form,page){
	var url;
	if(SearchType == "supplier" && getElement("keyword").value == ''){
		url = "/Products-by-Supplier/GetSearchResults.asp?page="+page+"&rnd="+randomNum();
		if(getElement("mfgid")){
			url = url + "&mfgid="+getElement("mfgid").value
		}
	}
	else{
		url = "GetSearchResults.asp?keyword="+getElement("keyword").value+"&page="+page+"&rnd="+randomNum();
		if(getElement("mfgid")){
			url = url + "&mfgid="+getElement("mfgid").value
		}
		if(SearchType == "supplier"){
			url = "/Search-Suppliers/" + url + "&custom=search-suppliers";
		}
		else{
			url = "/Search/" + url;
		}
	}
	if(InDistributorDashboard){
		url = "/Distributors" + url;
	}
	RunAjax(xmlHttpReq,getElement("ResultsPane"),url,waitHTML);	
}

function AdvancedSearchUpdate(form,thisParentCategoryID,thisCategoryID,page){
	
	if(page > 0 == false){
		page = 1;	
	}
	
	var ParentCategoryID;
	var CategoryID;
	
	var elementName;
	var elementValue;
	
	var CatMod="CatMod="
	var ManMod="ManMod="
	var RegMod="RegMod="
	
	var tmpStr=""
	var tmpLen=0
	
	var modstring = "mod=none"
	
	for(i=0; i < form.elements.length; i++) {
		elementName = form.elements[i].name
		
		if (elementName.indexOf("Category_")==0){
			
			tmpStr = Right(elementName,(elementName.length-9));
			CategoryID = Right(tmpStr,(tmpStr.length-tmpStr.indexOf("_")-1));
			ParentCategoryID = tmpStr.replace("_"+CategoryID,"");
			
			if(ParentCategoryID == thisCategoryID){
				if(getElement(elementName)){
					form.elements[i].checked = getElement("Category_0_"+ParentCategoryID).checked;
				}
			}
			
			elementValue = form.elements[i].checked;
			
			if (elementValue == false){
				CatMod += CategoryID + ",";
				if(ParentCategoryID == thisParentCategoryID && ParentCategoryID != 0){
					// uncheck parent category
					getElement("Category_0_"+ParentCategoryID).checked = false;
					CatMod += ParentCategoryID + ",";
				}
			}
		}
	}
	
	//Clean off any extra commas
	if (Right(CatMod,1) == ",") {
		tmpLen=CatMod.length;
		tmpStr=Left(CatMod,tmpLen-1);
		CatMod=tmpStr;
	}
	
	modstring=CatMod
		
	var url;
	if(SearchType == "supplier" && getElement("keyword").value == ''){
		url = "/Products-by-Supplier/GetSearchResults.asp?page="+page+"&rnd="+randomNum()+"&"+modstring;
		if(getElement("mfgid")){
			url = url + "&mfgid="+getElement("mfgid").value
		}	
	}
	else{
		url = "GetSearchResults.asp?keyword="+getElement("keyword").value+"&page="+page+"&rnd="+randomNum()+"&"+modstring;
		if(getElement("mfgid")){
			url = url + "&mfgid="+getElement("mfgid").value
		}	
		if(SearchType == "supplier"){
			url = "/Search-Suppliers/" + url + "&custom=search-suppliers";
		}
		else{
			url = "/Search/" + url;
		}
	}
	if(InDistributorDashboard){
		url = "/Distributors" + url;
	}

	if((SearchType != "supplier" && getElement("keyword").value != '') || SearchType == "supplier"){
	
		if(getElement("ResultsPane")){	
			
			getElement("ResultsPane").innerHTML = waitHTML;
			
			RunAjax(xmlHttpReq,getElement("ResultsPane"),url,waitHTML);
		
		}
		else{
			
			window.location = url.replace("GetSearchResults.asp","");
			
		}
	}
}

function ShowSubcategories(CategoryID){
	toggleElement("Subcategories_"+CategoryID);
}

function initializeSearch(){
	AjaxBackURL = getCookie("AjaxBackURL") + '';
	if(AjaxBackURL == "null"){ 
		AjaxBackURL = '';
	}
	IsPreviousPageAjax = getCookie('IsPreviousPageAjax');
	setCookie( 'IsPreviousPageAjax', 'false', '', '/', '', '' );
	
	//alert("IsCurrentPageAjax = false");
	//alert("IsPreviousPageAjax = " + IsPreviousPageAjax);
	
	if(getQuerystring("catid") != ''){
		UseAjaxSearch = false;
	}else if(getElement('ResultsPane') && getQuerystring("bc") == '' && getElement('keyword').value != ''){
		UseAjaxSearch = true;
	}
	else if(window.location.pathname.toLowerCase().indexOf("/distributors/products-by-supplier/") >= 0 || (window.location.pathname.toLowerCase().indexOf("/distributors/search-suppliers/") >= 0 && getQuerystring("mfgid") == '' )){
		UseAjaxSearch = true;
	}
	else{
		UseAjaxSearch = false;
	}
	
	if(UseAjaxSearch){
		//setCookie( 'IsPreviousPageAjax', 'true', '', '/', '', '' );
		if(AjaxBackURL != '' && IsPreviousPageAjax == 'false'){			
			setCookie( 'AjaxBackURL', '', '', '/', '', '' );
			// redirect to non ajax version of last ajax page viewed
			//alert("redirect to non ajax version of last ajax page viewed");
			window.location = AjaxBackURL;
		}
	}
	else if(IsPreviousPageAjax == 'true'){
		setCookie( 'IsPreviousPageAjax', 'false', '', '/', '', '' );
		// force page to refresh when back button is hit
		//alert("force page to refresh when back button is hit");
		window.onbeforeunload = function(){}
	}
	
	if(window.location.pathname.toLowerCase() == "/" || window.location.pathname.toLowerCase() == "/default.asp"){
		// if on homepage then clear previous search
		setCookie( 'AjaxBackURL', '', '', '/', '', '' );
	}
	
	if(window.location.pathname.toLowerCase() == "/distributors/" || window.location.pathname.toLowerCase() == "/distributors/default.asp"){
		// if on distributor dashboard homepage then clear previous search
		setCookie( 'AjaxBackURL', '', '', '/', '', '' );
	}
	
	if(UseAjaxSearch){
		showElement('Search_Advanced_Link');
		if(getCookie("search") == "advanced"){						
			showAdvancedSearch();
		}
		else{
			showBasicSearch();
		}
	}
	else{
		hideElement('Search_Advanced');
		hideElement('Search_Basic_Link');
		if(getElement("ProductSearchTitle")){
			if(SearchType == "supplier"){
				getElement("ProductSearchTitle").innerHTML = "Supplier Search";
			}
			else{
				getElement("ProductSearchTitle").innerHTML = "Product Search";
			}
		}
	}
	
}
function showBasicSearch() {
    if (getElement("Search_Advanced")) {
        deleteCookie('search');
        setCookie('search', 'basic', '', '/', '', '');
        hideElement('Search_Advanced');
        hideElement('Search_Basic_Link');
        showElement('Search_Advanced_Link');
        if (getElement("ProductSearchTitle")) {
            if (SearchType == "supplier") {
                getElement("ProductSearchTitle").innerHTML = "Supplier Search";
            }
            else {
                getElement("ProductSearchTitle").innerHTML = "Product Search";
            }
        }
    }
}
function showAdvancedSearch() {
    if (getElement("Search_Advanced")) {
        deleteCookie('search');
        setCookie('search', 'advanced', '', '/', '', '');
        showElement('Search_Advanced');
        hideElement('Search_Advanced_Link');
        showElement('Search_Basic_Link');
        if (SearchType == "supplier" && getElement("ProductSearchTitle")) {
            getElement("ProductSearchTitle").innerHTML = "Supplier Search";
        }
        else {
            getElement("ProductSearchTitle").innerHTML = "Advanced Search";
        }

        // display parent subcategory tree if at least one subcategory is checked...
        var form = getElement("SearchForm");
        var elementName;
        var elementValue;
        var CategoryID;
        var ParentCategoryID;

        for (i = 0; i < form.elements.length; i++) {
            elementName = form.elements[i].name

            tmpStr = Right(elementName, (elementName.length - 9));
            CategoryID = Right(tmpStr, (tmpStr.length - tmpStr.indexOf("_") - 1));
            ParentCategoryID = tmpStr.replace("_" + CategoryID, "");

            if (elementName.indexOf("Category_") == 0 && CategoryID > 0) {

                elementValue = form.elements[i].checked;

                if (elementValue && getElement("Category_0_" + ParentCategoryID)) {
                    if (getElement("Category_0_" + ParentCategoryID).checked == false) {
                        showElement("Subcategories_" + ParentCategoryID);
                    }
                }
            }
        }
    }
}

/* make magnifying glass clickable */
$(document).ready(function () {
    $('.SearchBox_Keywords_Left').each(function () {
        $(this).click(function () {
            $(this).parents('form:first').submit();
        });
    });
});

/* related searches */
$(document).ready(function () {
    function toggleSupplemental(obj, action) {
        if (action == 'hide') {
            $('.related-searches ul').attr('class', 'hide more');
        }
        else {
            $('.related-searches ul').attr('class', 'more');
            $('ul li.related-supplemental', $(obj).parent()).attr('class', '');
        }
        var topX;
        var thisX;
        var count = 0;
        var lastItem;
        $('li', obj).not('.clear').each(function () {
            count++;
            thisX = $(this).offset().top;
            if (count == 1) {
                topX = thisX;
            }
            if (thisX > topX) {
                if (action == 'hide') {
                    $(this).attr('class', 'related-supplemental');
                }
                else {
                    $(this).attr('class', '');
                }
                if (!lastItem) {
                    lastItem = $(this).prev('li');
                    $(this).prev('li').each(function () {
                        var innerHTML = lastItem.html();
                        if (innerHTML.length > 0) {
                            if (action == 'hide') {
                                if (innerHTML.substring(innerHTML.length, innerHTML.length - 1) == ',') {
                                    $(this).html(innerHTML.substring(0, innerHTML.length - 1));
                                }
                            }
                            else {
                                if (innerHTML.substring(innerHTML.length, innerHTML.length - 1) != ',') {
                                    $(this).html(innerHTML + ',');
                                }
                            }
                        }
                    });
                }
            }

        });
    }
    function initializeRelatedSearches(obj) {
        $(obj).attr('class', '');
        var actualHeight = $(obj).height();
        $(obj).attr('class', 'hide');
        var cssHeight = $(obj).css('height') + '';
        if (cssHeight != '') {
            cssHeight = cssHeight.replace('px', '');
            if (isNumeric(cssHeight)) {
                cssHeight = parseInt(cssHeight);
            }
            else {
                cssHeight = 0;
            }
        }
        if (cssHeight > 0 && actualHeight > cssHeight) {
            $('.related-more').css('display', 'block');
            $(obj).attr('class', 'hide more');
            toggleSupplemental(obj, 'hide');
        }
    }
    initializeRelatedSearches($('.related-searches ul'));
    $('.related-more', this).click(function () {
        if ($(this).attr('class') == 'related-more') {
            $(this).html('<span>Less...</span>');
            $(this).attr('class', 'related-less');
            toggleSupplemental($('.related-searches ul'), 'show');
        }
        else {
            $(this).html('<span>More...</span>');
            $(this).attr('class', 'related-more');
            toggleSupplemental($('.related-searches ul'), 'hide');
        }

    });
    $('.related-searches a.related-more').each(function () {
        $(this).attr('href', 'javascript:void(0);');
        $(this).html('<span>More...</span>');
    });
});

/* refine search */
$(document).ready(function () {
    if ($('.refine-search ul li').length > 0) {
        $('.refine-search ul li').has('.refine-supplemental').each(function () {
            $('.refine-more', this).attr('style', 'display:block;');
            $('.refine-more', this).click(function () {
                if ($(this).attr('class') == 'refine-more') {
                    $(this).html('<span>Less...</span>');
                    $(this).attr('class', 'refine-less');
                    $('ul li.refine-supplemental', $(this).parent()).attr('style', 'display:block;');
                }
                else {
                    $(this).html('<span>More...</span>');
                    $(this).attr('class', 'refine-more');
                    $('ul li.refine-supplemental', $(this).parent()).attr('style', 'display:none;');
                }

            });
        });
        $('.refine-search li.refine-supplemental').each(function () {
            $(this).attr('style', 'display:none;');
        });
        $('.refine-search a.refine-more').each(function () {
            $(this).attr('href', 'javascript:void(0);');
            $(this).html('<span>More...</span>');
        });
    }
});

/* search options */
$(document).ready(function () {
    $('.search-options-top form').submit(function () {
        var obj;
        if ($('.search-options-top select[name=url]').length == 1) {
            obj = $('.search-options-top select[name=url]');
        }
        else if ($('.search-options-top input[name=url]').length == 1) {
            obj = $('.search-options-top input[name=url]');
        }
        if (obj) {
            ChangeSearchPage('', obj);
        }
        return false;
    });
    $('.search-options-top input[type=checkbox]').change(function () {
        $(this).parents('form:first').submit();
    });
    $('.search-options-top select[name=pagesize]').change(function () {
        $(this).parents('form:first').submit();
    });
});

/* advanced search */
var subcategoriesajax;
$(document).ready(function () {
    var catselect = $('.advanced-search select[name=searchcategory]');
    var subcatselect = $('.advanced-search select[name=searchsubcategory]');
    if (catselect) {
        function getSubcategories(obj) {
            var subcategoryList = [];
            if (subcategoriesajax) {
                subcategoriesajax.abort();
            }
            var selectedValue = $(obj).val();
            if (isNumeric(selectedValue)) {
                selectedValue = parseInt(selectedValue);
            }
            else {
                selectedValue = 0;
            }
            if (selectedValue > 0) {
                //alert(selectedValue);
                subcategoriesajax = $.ajax({
                    url: '/ajax_subcategories.asp',
                    data: 'catid=' + escape(selectedValue),
                    type: 'GET',
                    dataType: 'xml',
                    success: function (returnedXMLResponse) {
                        //alert('success');
                        $('subcategory', returnedXMLResponse).each(function () {
                            subcategoryList.push([$(this).attr('id'), $(this).text()]);
                        });
                        if (subcategoryList.length > 0) {
                            for (var i = 0, len = subcategoryList.length; i < len; ++i) {
                                //alert(subcategoryList[i]);
                                matchesFound = true;
                            }
                        }
                        else {
                            //alert('no items');
                            matchesFound = false;
                        }
                    },
                    complete: function (returnedXMLResponse) {
                        $(subcatselect).children().remove();
                        $(subcatselect).append('<option>All Subcategories</option>');
                        if (matchesFound) {
                            for (var i = 0, len = subcategoryList.length; i < len; ++i) {
                                $(subcatselect).append('<option value="' + subcategoryList[i][0] + '">' + subcategoryList[i][1] + '</option>');
                            }
                            $(subcatselect).attr('disabled', '');
                        }
                        else {
                            $(subcatselect).attr('disabled', 'disabled');
                        }
                    }
                });
            }
            else {
                $(catselect).val(0);
                $(subcatselect).children().remove();
                $(subcatselect).append('<option>All Subcategories</option>');
                $(subcatselect).attr('disabled', 'disabled');
            }
        }
        $(catselect).change(function () {
            getSubcategories($(this));
        });
        $(catselect).keypress(function (e) {
            getSubcategories($(this));
        });
        getSubcategories($(catselect));
    }
});

function isNumeric(value) {
    if (value) {
        if (value.match(/^\d+$/) == null) {
            return false;
        }
        else {
            return true;
        }
    }
    else {
        return false;
    }
}





/**
* jQuery.query - Query String Modification and Creation for jQuery
* Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
* Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
* Date: 2009/8/13
*
* @author Blair Mitchelmore
* @version 2.1.7
*
**/
new function (settings) {
    // Various Settings
    var $separator = settings.separator || '&';
    var $spaces = settings.spaces === false ? false : true;
    var $suffix = settings.suffix === false ? '' : '[]';
    var $prefix = settings.prefix === false ? false : true;
    var $hash = $prefix ? settings.hash === true ? "#" : "?" : "";
    var $numbers = settings.numbers === false ? false : true;

    jQuery.query = new function () {
        var is = function (o, t) {
            return o != undefined && o !== null && (!!t ? o.constructor == t : true);
        };
        var parse = function (path) {
            var m, rx = /\[([^[]*)\]/g, match = /^([^[]+)(\[.*\])?$/.exec(path), base = match[1], tokens = [];
            while (m = rx.exec(match[2])) tokens.push(m[1]);
            return [base, tokens];
        };
        var set = function (target, tokens, value) {
            var o, token = tokens.shift();
            if (typeof target != 'object') target = null;
            if (token === "") {
                if (!target) target = [];
                if (is(target, Array)) {
                    target.push(tokens.length == 0 ? value : set(null, tokens.slice(0), value));
                } else if (is(target, Object)) {
                    var i = 0;
                    while (target[i++] != null);
                    target[--i] = tokens.length == 0 ? value : set(target[i], tokens.slice(0), value);
                } else {
                    target = [];
                    target.push(tokens.length == 0 ? value : set(null, tokens.slice(0), value));
                }
            } else if (token && token.match(/^\s*[0-9]+\s*$/)) {
                var index = parseInt(token, 10);
                if (!target) target = [];
                target[index] = tokens.length == 0 ? value : set(target[index], tokens.slice(0), value);
            } else if (token) {
                var index = token.replace(/^\s*|\s*$/g, "");
                if (!target) target = {};
                if (is(target, Array)) {
                    var temp = {};
                    for (var i = 0; i < target.length; ++i) {
                        temp[i] = target[i];
                    }
                    target = temp;
                }
                target[index] = tokens.length == 0 ? value : set(target[index], tokens.slice(0), value);
            } else {
                return value;
            }
            return target;
        };

        var queryObject = function (a) {
            var self = this;
            self.keys = {};

            if (a.queryObject) {
                jQuery.each(a.get(), function (key, val) {
                    self.SET(key, val);
                });
            } else {
                jQuery.each(arguments, function () {
                    var q = "" + this;
                    q = q.replace(/^[?#]/, ''); // remove any leading ? || #
                    q = q.replace(/[;&]$/, ''); // remove any trailing & || ;
                    if ($spaces) q = q.replace(/[+]/g, ' '); // replace +'s with spaces

                    jQuery.each(q.split(/[&;]/), function () {
                        var key = decodeURIComponent(this.split('=')[0] || "");
                        var val = decodeURIComponent(this.split('=')[1] || "");

                        if (!key) return;

                        if ($numbers) {
                            if (/^[+-]?[0-9]+\.[0-9]*$/.test(val)) // simple float regex
                                val = parseFloat(val);
                            else if (/^[+-]?[0-9]+$/.test(val)) // simple int regex
                                val = parseInt(val, 10);
                        }

                        val = (!val && val !== 0) ? true : val;

                        if (val !== false && val !== true && typeof val != 'number')
                            val = val;

                        self.SET(key, val);
                    });
                });
            }
            return self;
        };

        queryObject.prototype = {
            queryObject: true,
            has: function (key, type) {
                var value = this.get(key);
                return is(value, type);
            },
            GET: function (key) {
                if (!is(key)) return this.keys;
                var parsed = parse(key), base = parsed[0], tokens = parsed[1];
                var target = this.keys[base];
                while (target != null && tokens.length != 0) {
                    target = target[tokens.shift()];
                }
                return typeof target == 'number' ? target : target || "";
            },
            get: function (key) {
                var target = this.GET(key);
                if (is(target, Object))
                    return jQuery.extend(true, {}, target);
                else if (is(target, Array))
                    return target.slice(0);
                return target;
            },
            SET: function (key, val) {
                var value = !is(val) ? null : val;
                var parsed = parse(key), base = parsed[0], tokens = parsed[1];
                var target = this.keys[base];
                this.keys[base] = set(target, tokens.slice(0), value);
                return this;
            },
            set: function (key, val) {
                return this.copy().SET(key, val);
            },
            REMOVE: function (key) {
                return this.SET(key, null).COMPACT();
            },
            remove: function (key) {
                return this.copy().REMOVE(key);
            },
            EMPTY: function () {
                var self = this;
                jQuery.each(self.keys, function (key, value) {
                    delete self.keys[key];
                });
                return self;
            },
            load: function (url) {
                var hash = url.replace(/^.*?[#](.+?)(?:\?.+)?$/, "$1");
                var search = url.replace(/^.*?[?](.+?)(?:#.+)?$/, "$1");
                return new queryObject(url.length == search.length ? '' : search, url.length == hash.length ? '' : hash);
            },
            empty: function () {
                return this.copy().EMPTY();
            },
            copy: function () {
                return new queryObject(this);
            },
            COMPACT: function () {
                function build(orig) {
                    var obj = typeof orig == "object" ? is(orig, Array) ? [] : {} : orig;
                    if (typeof orig == 'object') {
                        function add(o, key, value) {
                            if (is(o, Array))
                                o.push(value);
                            else
                                o[key] = value;
                        }
                        jQuery.each(orig, function (key, value) {
                            if (!is(value)) return true;
                            add(obj, key, build(value));
                        });
                    }
                    return obj;
                }
                this.keys = build(this.keys);
                return this;
            },
            compact: function () {
                return this.copy().COMPACT();
            },
            toString: function () {
                var i = 0, queryString = [], chunks = [], self = this;
                var encode = function (str) {
                    str = str + "";
                    if ($spaces) str = str.replace(/ /g, "+");
                    return encodeURIComponent(str);
                };
                var addFields = function (arr, key, value) {
                    if (!is(value) || value === false) return;
                    var o = [encode(key)];
                    if (value !== true) {
                        o.push("=");
                        o.push(encode(value));
                    }
                    arr.push(o.join(""));
                };
                var build = function (obj, base) {
                    var newKey = function (key) {
                        return !base || base == "" ? [key].join("") : [base, "[", key, "]"].join("");
                    };
                    jQuery.each(obj, function (key, value) {
                        if (typeof value == 'object')
                            build(value, newKey(key));
                        else
                            addFields(chunks, newKey(key), value);
                    });
                };

                build(this.keys);

                if (chunks.length > 0) queryString.push($hash);
                queryString.push(chunks.join($separator));

                return queryString.join("");
            }
        };

        return new queryObject(location.search, location.hash);
    };
} (jQuery.query || {}); // Pass in jQuery.query as settings object
