﻿//<SharePoint:ScriptLink ID="ScriptLink1" Name="sp.debug.js" LoadAfterUI="true" Localizable="false" runat="server" />
/// <reference name="MicrosoftAjax.js" /> 
/// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.core.debug.js" />
/// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.debug.js" />
// var SPAutoComplete = [{ WebName: "Solutions", ListName: "Pages", ControlId: "searchBox", Include: "Include(Title, ServerUrl)"}];

var SPAC = null;

function StartAutoCompleter() {
    SPAC = new AutoCompleter(SPAutoComplete);
}

function AutoCompleter(configuration) {

    var userWebs = null,
        uiconfig = configuration,
        c = parseConfig(configuration),
        loading = [ { id: 0, text: "Loading..." } ];
    
    loading.Name = "Loading";
    InitializeWebs();

    function parseConfig(c) {
        ret = {};
        for (var i = 0; i < c.length; i++) {
            var ci = c[i], 
                wns = ci.WebName.split(",");
            for (var j = 0; j < wns.length; j++) {
                var wn = wns[j],
                    w = ret[wn] == null
                            ? ret[wn] = newWebConfig(ci)
                            : ret[wn];
                ensureListConfig(w, ci);
            }
        }
        return ret;
    }

    function ensureListConfig(w, ci) {
        var lns = ci.ListName.split(",");
        for (var l = 0; l < lns.length; l++) {
            if (!w.Lists[lns[l]]) w.Lists[lns[l]] = $.extend({}, ci);
        }
        return ci;
    }

    function newWebConfig(ci) {
        var web = { WebName: ci.WebName, Lists: {} };
        ci.Ready = false;
        return web;
    }

    function InitializeWebs() {
        var clientContext = new SP.ClientContext.get_current(),
            web = clientContext.get_site().get_rootWeb();
        userWebs = web.getSubwebsForCurrentUser(null);
        clientContext.load(userWebs);
        clientContext.executeQueryAsync(Function.createDelegate(this, GetWebsSuccess), Function.createDelegate(this, GetWebsFailure));
    }

    function GetWebsSuccess() {
        var ws = userWebs.getEnumerator();
        while (ws.moveNext()) {
            var web = ws.get_current(),
                name = web.get_title().replace(/\s/g,'-'),
                webConfig = c[name];
            if (webConfig) {
                webConfig.SPWEB = web;
                InitializeData(webConfig);
            }
        }
    }

    function GetWebsFailure(sender, args) {
        // alert('Get Data Failure: ' + args.get_message() + '\n' + args.get_stackTrace());    
    }

    function InitializeData(config) {
        var context = new SP.ClientContext.get_current();
        for(var list in config.Lists) {
            var qConfig = config.Lists[list];
            
            if(qConfig.WebName) {
                
                qConfig.SPLIST = config.SPWEB.get_lists().getByTitle(list);
                
                var query = '<View Scope=\'RecursiveAll\'>' +
                                '<Query><OrderBy><FieldRef Name="Title" Ascending="true" /></OrderBy></Query>' +
                            '</View>';

                var camlQuery = new SP.CamlQuery();
                camlQuery.set_viewXml(query);

                qConfig.data = qConfig.SPLIST.getItems(camlQuery);
                context.load(qConfig.data, qConfig.Include);
                context.executeQueryAsync(Function.createDelegate(this, GetDataSuccess), Function.createDelegate(this, GetDataFailure));

            }
        }
    }


    function GetDataSuccess(sender, args) {
        
        for (var i = 0; i < uiconfig.length; i++) {

            if (!uiconfig[i].Ready) {

                var ui = uiconfig[i],
                    wns = ui.WebName.split(","),
                    lns = ui.ListName.split(","),
                    got = 0, lists = [];

                for (var w = 0; w < wns.length; w++) {
                    var web = c[wns[w]],
                        list = web.Lists[lns[w]];

                    if ((list.Ready == false && list.data && GetEnum(list.data)) || list.acdata) {
                        list.Name = wns[w].replace(/-/g, " ");
                        lists[lists.length] = list;
                        got++;
                    }

                }

                if (wns.length == got) {
                    for (var l in lists) {
                        var list = lists[l];
                        if (!list.Ready) {
                            var de = list.data.getEnumerator(),
                            d = [];
                            while (de.moveNext()) {
                                var item = de.get_current();
                                d[d.length] = {
                                    Title: item.get_item('Title'),
                                    Url: item.get_item('ServerUrl')
                                }
                            }
                            list.Ready = true;
                            list.acdata = d;
                        }
                    }
                    ui.Ready = true;
                    ui.Lists = lists;
                    AutoCompleteReady(ui);
                }
            }
        }
    }
    
    function GetEnum(obj) {
        try {
            var e = obj.getEnumerator();
            return true;
        } catch (ex) {
            return false;
        }
    }

    function AutoCompleteReady(config) {

        var settings = { ajaxResults: true, onSelect: AutoCompleteItemSelected, width: config.Width, onSearch: AutoCompleteSearch, multi: config.Lists.length > 1, maxResults: (config.MaxResults == 0 ? undefined : config.MaxResults) };
        var ac =  $("#" + config.ControlId);

        ac.next().click(function () {
                var ac = $(this).prev().prev(),
                        c = $("#" + ac[0].id).data("ACCONFIG");
                AutoCompleteSearch(ac[0], c);
            });
                
        ac.data("ACCONFIG", config)
            .jsonSuggest(function (ac, text, wildCard, caseSensitive, notCharacter) {
                var config = $(ac).data("ACCONFIG"),
                    lists = config.Lists,
                    results = [], 
                    st = text.toLowerCase();
                if (lists != null) {
                    for(var l in lists) {
                        var list = lists[l],
                            data = list.acdata, 
                            r = [];
                        r.Name = list.Name;
                        if (data && data.length > 0) {
                            for (var i = 0; i < data.length; i++) {
                                if (data[i].Title.toLowerCase().indexOf(st) > -1) {
                                    r[r.length] = { id: data[i].Url, text: data[i].Title };
                                }
                            }
                            if (r.length > 0) results[results.length] = r;
                        }
                    }
                } else {
                    results[results.length] = loading;
                }
                return results;
            }, settings)
            

    }

    function AutoCompleteSearch(obj, config) {
        var v = escape($(obj).val());
        if(config&&v&&v!="") window.location.href = config.SearchUrl.replace(/\{TEXT\}/g, v);
    }

    function AutoCompleteItemSelected(item) {
        if (item.id) {
            window.location.href = item.id;
        }
    }

    function GetDataFailure(sender, args) {
        // alert('Get Data Failure: ' + args.get_message() + '\n' + args.get_stackTrace());
    }
};

ExecuteOrDelayUntilScriptLoaded(StartAutoCompleter, "sp.js");

/* JQUERY AUTOCOMPLETE PLUGIN */
(function ($) {
    $.fn.jsonSuggest = function (searchData, settings) {
        var defaults = {
            minCharacters: 1,
            maxResults: undefined,
            wildCard: "",
            caseSensitive: false,
            notCharacter: "!",
            maxHeight: 350,
            highlightMatches: true,
            onSelect: undefined,
            onSearch: undefined,
            ajaxResults: false,
            width: "240px",
            multi: false
        };
        settings = $.extend(defaults, settings);
        return this.each(function () {

            function regexEscape(txt, omit) {
                var specials = ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\'];
                if (omit) {
                    for (var i = 0; i < specials.length; i++) {
                        if (specials[i] === omit) {
                            specials.splice(i, 1);
                        }
                    }
                }
                var escapePatt = new RegExp('(\\' + specials.join('|\\') + ')', 'g');
                return txt.replace(escapePatt, '\\$1');
            }
            var obj = $(this),
                wildCardPatt = new RegExp(regexEscape(settings.wildCard || ''), 'g'),
                results = $('<div />'),
                currentSelection, pageX, pageY;

            $(document).click(function() {
                $(results).hide();
            });
            
            $(obj).click(function() {
                return false;
            });

            function selectResultItem(item) {
                obj.val(item.text);
                $(results).html('').hide();
                if (typeof settings.onSelect === 'function') {
                    settings.onSelect(item);
                }
                return false;
            }

            function setHoverClass(el) {
                $('div.resultItem', results).removeClass('hover');
                $(el).addClass('hover');
                currentSelection = el;
            }

            function buildResults(resultGroups, sFilterTxt) {
                sFilterTxt = "(" + sFilterTxt + ")";
                var bOddRow = true,
                    i, rg, iFound = 0,
                    filterPatt = settings.caseSensitive ? new RegExp(sFilterTxt, "g") : new RegExp(sFilterTxt, "ig");

                $(results).html('').hide();
                for(rg = 0; rg<resultGroups.length;rg++) {
                    
                    var resultObjects = resultGroups[rg], apTo = results;
                    
                    if(settings.multi) {
                        var inner = $('<div class="group"><span class="groupName">' + resultObjects.Name + '</span></div>').appendTo(results);
                        apTo = $('<div />').appendTo(inner).addClass("multiItems");
                        if(rg+1<resultGroups.length) inner.after('<div class="groupSplit"></div>');
                    }

                    for (i = 0; i < resultObjects.length; i += 1) {

                        var item = $('<div />'),
                            text = resultObjects[i].text;

                        if (settings.highlightMatches === true) {
                            text = text.replace(filterPatt, "<strong>$1</strong>");
                        }

                        $(item).append('<p class="text">' + text + '</p>');
                        
                        if (typeof resultObjects[i].extra === 'string') {
                            $(item).append('<p class="extra">' + resultObjects[i].extra + '</p>');
                        }
                        
                        if (typeof resultObjects[i].image === 'string') {
                            $(item).prepend('<img src="' + resultObjects[i].image + '" />').append('<br style="clear:both;" />');
                        }
                        
                        $(item).addClass('resultItem').addClass((bOddRow) ? 'odd' : 'even').click(function (n,k) {
                            return function () {
                                selectResultItem(resultGroups[k][n]);
                            };
                        } (i,rg)).mouseover(function (el) {
                            return function () {
                                setHoverClass(el);
                            };
                        } (item));
                        
                        $(apTo).append(item);
                        bOddRow = !bOddRow;
                        iFound += 1;
                        if (typeof settings.maxResults === 'number' && iFound >= settings.maxResults) {
                            break;
                        }
                
                    }

                }
                if ($('div', results).length > 0) {
                    currentSelection = undefined;
                    $(results).show().css('height', 'auto');
                    if ($(results).height() > settings.maxHeight) {
                        $(results).css({
                            'overflow': 'auto',
                            'height': settings.maxHeight + 'px'
                        });
                        var m = $(".multiItems", results);
                        m.css({"width":(m.outerWidth()-20)+"px"});
                    } else {
                        var m = $(".multiItems", results);
                        m.css({"width":(m.outerWidth()-6)+"px"});
                    }
                }
            }

            function runSuggest(e) {
                if (this.value.length < settings.minCharacters) {
                    $(results).html('').hide();
                    return false;
                }
                var resultObjects = [],
                    sFilterTxt = (!settings.wildCard) ? regexEscape(this.value) : regexEscape(this.value, settings.wildCard).replace(wildCardPatt, '.*'),
                    bMatch = true,
                    filterPatt, i;
                if (settings.notCharacter && sFilterTxt.indexOf(settings.notCharacter) === 0) {
                    sFilterTxt = sFilterTxt.substr(settings.notCharacter.length, sFilterTxt.length);
                    if (sFilterTxt.length > 0) {
                        bMatch = false;
                    }
                }
                sFilterTxt = sFilterTxt || '.*';
                sFilterTxt = settings.wildCard ? '^' + sFilterTxt : sFilterTxt;
                filterPatt = settings.caseSensitive ? new RegExp(sFilterTxt) : new RegExp(sFilterTxt, "i");
                if (settings.ajaxResults === true) {
                    resultObjects = searchData(this, this.value, settings.wildCard, settings.caseSensitive, settings.notCharacter);
                } else {
                    for (i = 0; i < searchData.length; i += 1) {
                        if (filterPatt.test(searchData[i].text) === bMatch) {
                            resultObjects.push(searchData[i]);
                        }
                    }
                }
                buildResults(resultObjects, sFilterTxt);
            }

            function keyListener(e) {
                var p = $(currentSelection).parent();
                switch (e.keyCode) {
                    case 13:
                        if($(currentSelection).length > 0) {
                            $(currentSelection).trigger('click');
                        } else {
                            if(typeof settings.onSearch == "function") {
                                settings.onSearch(this, $("#" + this.id).data("ACCONFIG"));
                            }
                        }
                        return false;
                    case 40:
                        if (typeof currentSelection === 'undefined') {
                            currentSelection = $('div.resultItem:first', results).get(0);
                        } else {
                            currentSelection = $(currentSelection).next().get(0);
                            if(!currentSelection && p.hasClass('multiItems')) {
                                p = $(p.parent().next().get(0));
                                if(p.hasClass("groupSplit")) {
                                    currentSelection = $('div.resultItem:first', p.next().get(0)).get(0);
                                }
                            }
                        }
                        setHoverClass(currentSelection);
                        if (currentSelection) {
                            $(results).scrollTop(currentSelection.offsetTop);
                        }
                        return false;
                    case 38:
                        if (typeof currentSelection === 'undefined') {
                            currentSelection = $('div.resultItem:last', results).get(0);
                        } else {
                            currentSelection = $(currentSelection).prev().get(0);
                            if(!currentSelection && p.hasClass('multiItems')) {
                                p = $(p.parent().prev().get(0));
                                if(p.hasClass("groupSplit")) {
                                    currentSelection = $('div.resultItem:last', p.prev().get(0)).get(0);
                                }
                            }
                        }
                        setHoverClass(currentSelection);
                        if (currentSelection) {
                            $(results).scrollTop(currentSelection.offsetTop);
                        }
                        return false;
                    default:
                        runSuggest.apply(this, [e]);
                }
            }
            $(results).addClass('jsonSuggestResults' + (!settings.multi ? "" : " jsonSuggestResultsMulti")).css({
                'top': (obj.position().top + obj.height() + 5) + 'px',
                'left': obj.position().left + 'px',
                'width': settings.width
            }).hide();
            obj.after(results).keyup(keyListener).blur(function (e) {
                var resPos = $(results).offset();
                resPos.bottom = resPos.top + $(results).height();
                resPos.right = resPos.left + $(results).width();
                if (pageY < resPos.top || pageY > resPos.bottom || pageX < resPos.left || pageX > resPos.right) {
                    $(results).hide();
                }
            }).focus(function (e) {
                $(results).css({
                    'top': (obj.position().top + obj.height() + 5) + 'px',
                    'left': obj.position().left + 'px'
                });
                if ($('div', results).length > 0) {
                    $(results).show();
                }
            }).attr('autocomplete', 'off');
            $().mousemove(function (e) {
                pageX = e.pageX;
                pageY = e.pageY;
            });
            if ($.browser.opera) {
                obj.keydown(function (e) {
                    if (e.keyCode === 40) {
                        return keyListener(e);
                    }
                });
            }
            settings.notCharacter = regexEscape(settings.notCharacter || '');
            if (!settings.ajaxResults) {
                if (typeof searchData === 'function') {
                    searchData = searchData();
                }
//                if (typeof searchData === 'string') {
//                    searchData = JSON.parse(searchData);
//                }
            }
        });
    };
})(jQuery);
