none
SharePoint 2013 - Duplicate value in auto search suggestion jquery

    질문

  • I have this script below working fine in google chrome but when i run it in IE, it displays duplicate values as seen below screenshot, how can i fix this duplicate value?                              

    <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
      <script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.js"></script>
      <script type="text/javascript" src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
      <script type="text/javascript">
      $(function() {
       $.ajax({
          url: _spPageContextInfo.siteAbsoluteUrl + "/_api/Web/Lists/GetByTitle('doc2')/Items?$select=FileLeafRef",

          type: "GET",
          headers: {
              "accept": "application/json;odata=verbose",
          },
          success: function (data) {
              var arr = data.d.results;
              console.log(arr);
              // console.log(arr);
              if(arr.length > 0) {
                getUniqueTags(arr);
                console.log(availableTags);
              }
          },
          error: function (error) {
              console.log("Error: " + JSON.stringify(error));
          }
      }); 

        setTimeout(function() {  
            $('input[id*="Search"]').autocomplete({ 
                  source: availableTags 

            });
        }, 1000);
      });

      var availableTags = [];
      function getUniqueTags(_arr) 
      {
        for(k = 0; k < _arr.length; k++) {
          availableTags.push(_arr[k].FileLeafRef);
        } 
      }


       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;
            $.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 + "*\"'", 
                    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)); 
            } 
        }

    }

        $(function () {
            // Make sure ajaxtoolkit is loaded before registering the functions
            ExecuteOrDelayUntilScriptLoaded(Override, 'ajaxtoolkit.js');
        });

      </script>

    Screenshot Error: you can see duplicate value popping up from library column to search box,

    Any idea?

    Thanks

    2018년 5월 15일 화요일 오후 9:43

답변

  • Hi,

    You could remove duplicate when you bind data to autocomplete, here is sample test code.

     <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
        <script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.js"></script>
        <script type="text/javascript" src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    
        <script type="text/javascript">
            $(function () {
                $.ajax({
                    url: _spPageContextInfo.siteAbsoluteUrl + "/_api/Web/Lists/GetByTitle('Doc4')/Items?$select=TAGS",
                    type: "GET",
                    headers: {
                        "accept": "application/json;odata=verbose",
                    },
                    success: function (data) {
                        var arr = data.d.results;
                        // console.log(arr);
                        if (arr.length > 0) {
                            getUniqueTags(arr);
                        }
                    },
                    error: function (error) {
                        console.log("Error: " + JSON.stringify(error));
                    }
                });
    
                setTimeout(function () {
                    // console.log($.unique(availableTags));
                    // $('#SearchBox input').autocomplete({
    
                    var uniqueTAGs = [];
                    $.each(availableTags, function (i, el) {
                        if ($.inArray(el, uniqueTAGs) === -1) uniqueTAGs.push(el);
                    });
                    $('input[id*="Search"]').autocomplete({
                        source: uniqueTAGs//$.unique(uniqueTAGs)
                    });
                }, 1000);
            });
    
            var availableTags = [];
            function getUniqueTags(_arr) {
                for (k = 0; k < _arr.length; k++) {
    
                    // TAGS Data - Metadata Field
                    var tagsArr = _arr[k].TAGS.results;               
                    if (tagsArr.length > 0) {
                        extractArrData(tagsArr);
                    }
    
                    // Single Field
                    addSingleFieldData(_arr[k].SPRINT);
    
                    // SPRINT Data
                    // var sprintArr = _arr[k].SPRINT.results;
                    // if(sprintArr.length > 0) {
                    //    extractArrData(sprintArr);
                    // }
                }
            }
    
            function addSingleFieldData(_val) {
                if (_val) {
                    availableTags.push(_val.toString());
                }
            }
    
            function extractArrData(_arrData) {
                for (p = 0; p < _arrData.length; p++) {
                    availableTags.push(_arrData[p].Label);
                }
            }
    
    
            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
    
                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;
                    $.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
                            // this query string search itesm only from current site colleciton
                            url: _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?rowlimit=5&querytext='title:\"" + prefixText + "*\" SPSiteUrl:" + _spPageContextInfo.siteAbsoluteUrl + "'",
    
    
                            // this below url query string search items from across tenant.
                            //  url: _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?rowlimit=5&querytext='title:\"" + prefixText + "*\"'",
                            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)); */
                    }
                }
    
            }
    
    
            $(function () {
                // Make sure ajaxtoolkit is loaded before registering the functions
                ExecuteOrDelayUntilScriptLoaded(Override, 'ajaxtoolkit.js');
            });
    
        </script>

    Tip:

    $.unique used for DOM objects https://api.jquery.com/jQuery.unique/, so won’t work for string here.

    Best Regards,

    Lee


    Please remember to mark the replies as answers if they helped. If you have feedback for TechNet Subscriber Support, contact tnsf@microsoft.com.


    Click here to learn more. Visit the dedicated forum to share, explore and talk to experts about Microsoft Teams.

    2018년 5월 21일 월요일 오전 1:34

모든 응답

  • Hi,

    Try to add &trimduplicates=true for your search rest api endpoint.

     url: _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?rowlimit=5&querytext='title:\"" + prefixText + "*\"'&trimduplicates=true", 

    You could check more details for this parameter below.

    https://docs.microsoft.com/en-us/sharepoint/dev/general-development/sharepoint-search-rest-api-overview

    Best Regards,

    Lee


    Please remember to mark the replies as answers if they helped. If you have feedback for TechNet Subscriber Support, contact tnsf@microsoft.com.


    Click here to learn more. Visit the dedicated forum to share, explore and talk to experts about Microsoft Teams.

    2018년 5월 16일 수요일 오전 1:54
  • Lee,

    in my script, it is popping up column value to search box and that code has been written in beginning of script, check below,

    url: _spPageContextInfo.siteAbsoluteUrl + "/_api/Web/Lists/GetByTitle('doc2')/Items?$select=FileLeafRef"

    I don't think so i need to update  &trimduplicates=true for search rest api endpoint which does not work even when i tried. i need to update in array which results coming from column "FileLeafRef" of DOC2 document library.

    Thanks

    2018년 5월 16일 수요일 오후 1:21
  • Hi,

    There is something I misunderstanding for my previous reply, I tried to test your code, there is no duplicate items.

    Is any duplicate items if you debug the script as below?

    Best Regards,

    Lee


    Please remember to mark the replies as answers if they helped. If you have feedback for TechNet Subscriber Support, contact tnsf@microsoft.com.


    Click here to learn more. Visit the dedicated forum to share, explore and talk to experts about Microsoft Teams.

    2018년 5월 17일 목요일 오전 1:33
  • Lee,

    In my document library, whenever users uploads documents, they attach keyword from column Keywords.

    i have couple of docs attached with keyword called "ADPH" and "Medical" . check following screenshot, 

     so whenever users search keywork in search box, it should not pop up same value multiple times which is happening here. 

    let me know 

    thanks,

    2018년 5월 17일 목요일 오전 2:17
  • Hi,

    What’s the field type for KEYWORDS?

    And the code you posted seems not the one you used, as the code you posted use file name as autocomplete source.

    And the function getUniqueTags don’t unique the items actually, so need update the function logic.

    Best Regards,

    Lee


    Please remember to mark the replies as answers if they helped. If you have feedback for TechNet Subscriber Support, contact tnsf@microsoft.com.


    Click here to learn more. Visit the dedicated forum to share, explore and talk to experts about Microsoft Teams.

    2018년 5월 18일 금요일 오전 1:26
  • Lee,

    This is my script here, KEYWORDS(Internal name is TAGS) is my column name and it is managed metadata type. users are allowed to select multiple options while uploading files to library.  script is popping up values from two coumns (TAGS and SPRINT) to search box but problem is that it populates duplicate values whereas we need unique value.

    see below script,

    <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
      <script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.js"></script>
      <script type="text/javascript" src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

        <script type="text/javascript">            

      $(function() {
       $.ajax({
          url: _spPageContextInfo.siteAbsoluteUrl + "/_api/Web/Lists/GetByTitle('Documents')/Items?$select=TAGS,SPRINT",
          type: "GET",
          headers: {
              "accept": "application/json;odata=verbose",
          },
          success: function (data) {
              var arr = data.d.results;
              // console.log(arr);
              if(arr.length > 0) {
                getUniqueTags(arr);
              }
          },
          error: function (error) {
              console.log("Error: " + JSON.stringify(error));
          }
      }); 

        setTimeout(function() {  
            // console.log($.unique(availableTags));
           // $('#SearchBox input').autocomplete({ 
      $('input[id*="Search"]').autocomplete({ 
              source: $.unique(availableTags)
                      });
        }, 1000);
      });

      var availableTags = [];
      function getUniqueTags(_arr) {
        for(k = 0; k < _arr.length; k++) {

          // TAGS Data - Metadata Field
          var tagsArr = _arr[k].TAGS.results;
          if(tagsArr.length > 0) {
             extractArrData(tagsArr);
          }

          // Single Field
          addSingleFieldData(_arr[k].SPRINT);

          // SPRINT Data
          // var sprintArr = _arr[k].SPRINT.results;
          // if(sprintArr.length > 0) {
          //    extractArrData(sprintArr);
          // }
        }
      }

      function addSingleFieldData(_val) {
        if(_val) {
          availableTags.push(_val.toString());
        }
      }

      function extractArrData(_arrData) {
        for(p = 0; p < _arrData.length; p++) {
          availableTags.push(_arrData[p].Label);
        }
      }


      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

        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;
            $.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
                  // this query string search itesm only from current site colleciton
                    url: _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?rowlimit=5&querytext='title:\"" + prefixText + "*\" SPSiteUrl:" + _spPageContextInfo.siteAbsoluteUrl + "'",


                  // this below url query string search items from across tenant.
                  //  url: _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?rowlimit=5&querytext='title:\"" + prefixText + "*\"'", 
                    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)); */
            } 
        }

    }


        $(function () {
            // Make sure ajaxtoolkit is loaded before registering the functions
            ExecuteOrDelayUntilScriptLoaded(Override, 'ajaxtoolkit.js');
        });

    </script>

    ------------------------------------

    Let me know if you can help.

    Thanks

    2018년 5월 18일 금요일 오후 1:09
  • Hi,

    You could remove duplicate when you bind data to autocomplete, here is sample test code.

     <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
        <script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.js"></script>
        <script type="text/javascript" src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    
        <script type="text/javascript">
            $(function () {
                $.ajax({
                    url: _spPageContextInfo.siteAbsoluteUrl + "/_api/Web/Lists/GetByTitle('Doc4')/Items?$select=TAGS",
                    type: "GET",
                    headers: {
                        "accept": "application/json;odata=verbose",
                    },
                    success: function (data) {
                        var arr = data.d.results;
                        // console.log(arr);
                        if (arr.length > 0) {
                            getUniqueTags(arr);
                        }
                    },
                    error: function (error) {
                        console.log("Error: " + JSON.stringify(error));
                    }
                });
    
                setTimeout(function () {
                    // console.log($.unique(availableTags));
                    // $('#SearchBox input').autocomplete({
    
                    var uniqueTAGs = [];
                    $.each(availableTags, function (i, el) {
                        if ($.inArray(el, uniqueTAGs) === -1) uniqueTAGs.push(el);
                    });
                    $('input[id*="Search"]').autocomplete({
                        source: uniqueTAGs//$.unique(uniqueTAGs)
                    });
                }, 1000);
            });
    
            var availableTags = [];
            function getUniqueTags(_arr) {
                for (k = 0; k < _arr.length; k++) {
    
                    // TAGS Data - Metadata Field
                    var tagsArr = _arr[k].TAGS.results;               
                    if (tagsArr.length > 0) {
                        extractArrData(tagsArr);
                    }
    
                    // Single Field
                    addSingleFieldData(_arr[k].SPRINT);
    
                    // SPRINT Data
                    // var sprintArr = _arr[k].SPRINT.results;
                    // if(sprintArr.length > 0) {
                    //    extractArrData(sprintArr);
                    // }
                }
            }
    
            function addSingleFieldData(_val) {
                if (_val) {
                    availableTags.push(_val.toString());
                }
            }
    
            function extractArrData(_arrData) {
                for (p = 0; p < _arrData.length; p++) {
                    availableTags.push(_arrData[p].Label);
                }
            }
    
    
            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
    
                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;
                    $.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
                            // this query string search itesm only from current site colleciton
                            url: _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?rowlimit=5&querytext='title:\"" + prefixText + "*\" SPSiteUrl:" + _spPageContextInfo.siteAbsoluteUrl + "'",
    
    
                            // this below url query string search items from across tenant.
                            //  url: _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?rowlimit=5&querytext='title:\"" + prefixText + "*\"'",
                            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)); */
                    }
                }
    
            }
    
    
            $(function () {
                // Make sure ajaxtoolkit is loaded before registering the functions
                ExecuteOrDelayUntilScriptLoaded(Override, 'ajaxtoolkit.js');
            });
    
        </script>

    Tip:

    $.unique used for DOM objects https://api.jquery.com/jQuery.unique/, so won’t work for string here.

    Best Regards,

    Lee


    Please remember to mark the replies as answers if they helped. If you have feedback for TechNet Subscriber Support, contact tnsf@microsoft.com.


    Click here to learn more. Visit the dedicated forum to share, explore and talk to experts about Microsoft Teams.

    2018년 5월 21일 월요일 오전 1:34
  • Lee, 

    this works fine as needed finally. 

    Thanks !!

    DK

    11시간 52분 전