﻿// QuickSearch v0.2
// Created by Jan Tielens, http://weblogs.asp.net/jan
// Modified to integrate with standard Seachbox by www.muhimbi.com
// This sample code is provided on an “as is” basis and without warranty of any kind.

// *** Customizable parameters ***
var quickSearchConfig = {
    delay: 500,             // time to wait before executing the query (in ms)
    minCharacters: 3,       // minimum nr of characters to enter before search
    scope: "SPFwww",     // search scope to use 'All Sites'
    numberOfResults: 15,    // number of results to show
    resultsAnimation: 200,  // animation time (in ms) of the search results
    resultAnimation: 0      // animation time (in ms) of individual result (when selected)
};

var quickSearchTimer;
var quickSearchSelectedDivIndex = -1;
var searchBox = null;

// SPF Settings
var topDiff = 43;
var searchResultWidth = 407;

$(document).ready(function () {
    // ** The searchbox uses a dynamic ID so select it by class     
    searchBox = $('.spfSearchBoxInput');

    if (searchBox.length == 0) {
        return;
    }

    // ** Hook up the various events 
    jQuery.event.add(window, "resize", resizeWindow);
    jQuery.event.add(document, "click", hideResultsDiv);

    // Muhimbi, insert the results box after te search area
    searchBox.after("<div id=\"quickSearchResults\" style=\"display: none; z-index:1000\"></div>");

    searchBox.keyup(function (event) {
        var previousSelected = quickSearchSelectedDivIndex;
        var isIndexChanged = false;
        var changeText = true;
        var doSearch = true;
        // catch some keys
        switch (event.keyCode) {
            case 13:    // enter
                var atag = $("#quickSearchResults>div:eq(" + quickSearchSelectedDivIndex + ") a");
                changeText = false;
                break;
            case 38:    // key up
                isIndexChanged = true;
                quickSearchSelectedDivIndex--;
                changeText = false;
                doSearch = false;
                break;
            case 40:    // key down
                isIndexChanged = true;
                quickSearchSelectedDivIndex++;
                changeText = false;
                doSearch = false;
                break;
            case 27: // Esc button
                hideResultsDiv();
                break;
        }

        // check bounds
        if (quickSearchSelectedDivIndex != previousSelected) {
            if (quickSearchSelectedDivIndex < 0)
                quickSearchSelectedDivIndex = 0;
            if (quickSearchSelectedDivIndex >= $("#quickSearchResults>div").length - 1)
                quickSearchSelectedDivIndex = $("#quickSearchResults>div").length - 1;
        }

        // select new div, unselect the previous selected
        if (quickSearchSelectedDivIndex > -1) {
            if (quickSearchSelectedDivIndex != previousSelected) {
                unSelectDiv($("#quickSearchResults>div:eq(" + previousSelected + ")"));
                selectDiv($("#quickSearchResults>div:eq(" + quickSearchSelectedDivIndex + ")"));
            }
        }

        if (isIndexChanged && quickSearchSelectedDivIndex >= 0) {
            var atag = $("#aID" + quickSearchSelectedDivIndex);
            setSearchText(atag, doSearch);
        }
        // if the query is different from the previous one, search again
        if (changeText && $(searchBox).data("query") != $(searchBox).val()) {
            if (quickSearchTimer != null) // cancel the delayed event
                clearTimeout(quickSearchTimer);
            quickSearchTimer = setTimeout(function () { // delay the searching
                $("#quickSearchResults").fadeOut(200, initSearch);
            }, quickSearchConfig.delay);
        }
    });
});

function showResultsDiv(text) {
    var div = $("#quickSearchResults");
    resizeWindow();
    div.append(text).slideDown(quickSearchConfig.resultsAnimation);
}

function hideResultsDiv() {
    var div = $("#quickSearchResults");
    div.slideUp(quickSearchConfig.resultsAnimation);
    div.empty()
}

function resizeWindow() {
    var div = $("#quickSearchResults");
    var searchParent = $(searchBox).parent();

    var divCss = {
        //"left": searchParent.position().left - 9,
        //"padding": 0,
        //"position": "absolute",
        //"top": searchParent.position().top + searchParent.height() + 1 - topDiff,
        //"top": searchParent.position().top + searchParent.height() + 9,
        //"position": "relative",
        //"top" : "11px",
        //"border": "none",
        //"background": "#E0E8EA"
    };

    div.css(divCss);
}

function unSelectDiv(div) {
    // first stop all animations still in progress
    $("#quickSearchResults>div>div").stop(true, true);

    div.removeClass("quickSearchResultDivSelected").addClass("quickSearchResultDivUnselected");
    $("#details", div).hide();
}

function selectDiv(div) {
    div.addClass("quickSearchResultDivSelected");
    $("#details", div).slideDown(quickSearchConfig.resultAnimation);
}

function initSearch() {
    // first store query in data
    $(searchBox).data("query", $(searchBox).val());

    // clear the results
    $("#quickSearchResults").empty();

    // start the search
    var query = $(searchBox).val();
    if (query.length >= quickSearchConfig.minCharacters) {
        showResultsDiv("Söker ..."); // display status
        search(query);
    }
}

function search(query) {
    quickSearchSelectedDivIndex = -1;
    var queryXML =
            "<QueryPacket xmlns='urn:Microsoft.Search.Query' Revision='1000'> \
            <Query domain='QDomain'> \
             <SupportedFormats> \
                <Format>urn:Microsoft.Search.Response.Document.Document</Format> \
             </SupportedFormats> \
             <Context> \
              <QueryText language='en-US' type='STRING' >SCOPE:\"" +
                 quickSearchConfig.scope + "\"Title:" + query + "</QueryText> \
             </Context> \
             <SortByProperties> \
               <SortByProperty name='Rank' direction='Descending' order='1'/> \
             </SortByProperties> \
             <Range><StartAt>1</StartAt><Count>" + quickSearchConfig.numberOfResults + "</Count></Range> \
             <EnableStemming>false</EnableStemming> \
             <TrimDuplicates>true</TrimDuplicates> \
             <IgnoreAllNoiseQuery>true</IgnoreAllNoiseQuery> \
             <ImplicitAndBehavior>true</ImplicitAndBehavior> \
             <IncludeRelevanceResults>true</IncludeRelevanceResults> \
             <IncludeSpecialTermResults>true</IncludeSpecialTermResults> \
             <IncludeHighConfidenceResults>true</IncludeHighConfidenceResults> \
            </Query></QueryPacket>";

    var soapEnv =
            "<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'" +
            " xmlns:xsd='http://www.w3.org/2001/XMLSchema' \
              xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'> \
              <soap:Body> \
                <Query xmlns='urn:Microsoft.Search'> \
                  <queryXml>" + escapeHTML(queryXML) + "</queryXml> \
                </Query> \
              </soap:Body> \
            </soap:Envelope>";

    $.ajax({
        url: L_Menu_BaseUrl + "/_vti_bin/search.asmx",
        type: "POST",
        dataType: "xml",
        data: soapEnv,
        complete: processResult,
        contentType: "text/xml; charset=\"utf-8\""
    });

    function processResult(xData, status) {
        var html = "";
        $(xData.responseXML).find("QueryResult").each(function () {
            var divWidth = $(searchBox).parent().width() + 18;

            if (jQuery.browser.msie && (jQuery.browser.version == "8.0" || jQuery.browser.version == "7.0")) {
                var x = $("<xml>" + $(this).text() + "</xml>");
            }
            else {
                var x = $($(this).text());
            }

            var idCount = 0;
            var searchQuery = $("#spfSearchBox").val();
            x.find("Document").each(function () {
                var title = $("Title", $(this)).text();
                var url = $("Action>LinkUrl", $(this)).text();
                var description = $("Description", $(this)).text();
                var date = $("Date", $(this)).text().substring(0, 10);
                reg = new RegExp(searchQuery, 'gi');
                var fancyTitle = title.replace(reg, function (str) { return '<b>' + str + '</b>' });
                html +=
                        "<div class='quickSearchResultDivUnselected' style='width:" + divWidth +
                              "px;max-width:" + divWidth + "px'> \
                            <a href=\"" + "#" + "\" onclick=\"setSearchTextFromText(\'" + title + "\', true)\" title=\"" + title + "\""  + "id=\"aID" + idCount + "\" >" + fancyTitle + "</a> \
                        </div>";
                idCount++;
            });
        });

        $("#quickSearchResults").empty().append(html);
        $("#quickSearchResults>div>a").hover(
                function () { selectDiv($(this).parent()); },
                function () { unSelectDiv($(this).parent()); }
            );
        showResultsDiv();
    }
}

function setSearchText(atag, doSearch) {
    $("#spfSearchBox").val($(atag).attr('title'));
    if (doSearch) {
        $("#spfSearchBtn").click();
    }
}

function setSearchTextFromText(text, doSearch) {
    $("#spfSearchBox").val(text);
    if (doSearch) {
        $("#spfSearchBtn").click();
    }
}

function escapeHTML(str) {
    return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
