Friday, August 5, 2016

Type ahead for Search Suggestions in SharePoint 2013

 Solution: Get top 5 results searching only on title field. Other parameters can be added as well
                Query term is what the user has entered with a wildcard appended
  

Pr-requites:
1) There should be a Search Center configured in the site Collection.
2) Create a Result Source to get all results and insert that Source id inside root level Property bag ( Eg:
<Key>SearchSuggestionsResultSource : <Value> 8f23f3c1-de7e-4c9b-bd14-de43cd07a3c9
)
Development Steps:

I could add this functionality to the existing search box on the search center. The search box has three settings for search as you type suggestions. Suggestions based on what everyone searches which is recorded over time (or you can manually add suggestions), suggestions matching people names, and personal favorites – which are searches you perform often.
The search suggestions functionality in SharePoint 2013 is provided by ajaxtoolkit.js. In order to extend the existing functionality I had to override the _update function of the AjaxControlToolkit.AutoCompleteBehavior.prototype which is responsible for the search as you type functionality of the search box.


 Config with Master Page :
1) Design Master -> Edit Page Layouts - > Create Page Layout with Your Master Page -> Click on that and go to the Page -> Click on Snippets
2) In Snippets Gallery select the Web Parts and click on Search Box
3) Change your changes inside Properties for search
4) In our requirement checked Show people name suggestions in Query Suggestions and update it.
5) Now you can copy Clipboard coding (in HTML Snippet) and insert that inside your html master page layout created early by downloading it from master page in settings.
6) Then upload that and published.
7) Now you can copy the search box content into .aspx page of that html master page and published.
8) Get that content and paste that content inside your .master page search box section.
9) Add JS link inside the master page
<script type="text/javascript" src="../Style%20Library/Controller/typeAhead.js">

</script>

Normal Steps in Development:

1.       Drop a content editor web part on the page and give the script link for js file or you can directly copy paste the code to script editor.
function Override() {
    // Keep a copy of the original function
    AjaxControlToolkit.AutoCompleteBehavior.prototype._update2 = AjaxControlToolkit.AutoCompleteBehavior.prototype._update;

    // register the searchOnSuccess on the same prototype object in order for the update2 function to keep the
    // context with all variables
    AjaxControlToolkit.AutoCompleteBehavior.prototype.searchOnSuccess = function (data, prefixText, completionItems, cacheResults) {
        var results = data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results;

        var names = [];
        for (var i = 0; i < results.length; i++) {
            var title = results[i].Cells.results[3].Value;
            // Add highlighting of the search term
            var idx = title.toLowerCase().indexOf(prefixText.toLowerCase());
            if (idx >= 0) {
                var hhtitle = title.substr(0, idx) + "<b>" + title.substr(idx, prefixText.length) + "</b>" + title.substr(idx + prefixText.length);
                names.push(hhtitle);
            } else {
                names.push(title); // fallback if indexof fails
            }
            /*              href = results[i].Cells.results[6].Value; */
        }
        // put our results in the people name container as we're not using it on our page
        completionItems.set_peopleNames(names);
        // call the original update function which renders out the results
        this._update2(prefixText, completionItems, cacheResults);
    };

    // Register an overload update function which executes a real search    
    AjaxControlToolkit.AutoCompleteBehavior.prototype._update = function (prefixText, completionItems, cacheResults) {
        var context = this;
        var root,sourceID = "";
        //var sourceID = localStorage.getItem("SearchSuggestionsResultSource");
        //alert(sourceID);
        $.ajax({
            url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/allProperties?$select=RootSiteCollectionUrl",
            method: "GET",
            headers: { "Accept": "application/json; odata=verbose" },
            success: function (data) {
                root = data.d.RootSiteCollectionUrl;

            },
            error: function (data) {
                console.log(JSON.stringify(data));
            }
        }).done(function () {
            $.ajax({
                url: root + "/_api/web/allProperties?$select=SearchSuggestionsResultSource",
                method: "GET",
                headers: { "Accept": "application/json; odata=verbose" },
                success: function (data) {
                    sourceID = data.d.NYLKMPSearchSuggestionsResultSource;

                },
                error: function (data) {
                    console.log(JSON.stringify(data));
                }

            }).done(function () {
                $.ajax(
                    {
                        // Get top 5 results searching only on title field. Other paramaters can be added as well
                        // Query term is what the user has entered with a wildcard appended            
                       
                        url: _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?rowlimit=5&querytext='title:\"" + prefixText + "*\"'&sourceid='" + sourceID + "'",

                        method: "GET",
                        headers: {
                            "accept": "application/json;odata=verbose;charset=utf-8",
                        },
                        success: function (data) { context.searchOnSuccess(data, prefixText, completionItems, cacheResults); },
                        error: onError
                    });
            });
        });
        function onError(err) {
            //alert(JSON.stringify(err));
            console.log(JSON.stringify(err));
        }
    }

}


// Replace url to your own jquery path
ExecuteOrDelayUntilScriptLoaded(Override, 'ajaxtoolkit.js');

 
2.       Edit Search Result web part and checked show people name in query suggestions.