2013-01-02 29 views
2

我有以下JS方法將jQuery UI自動填充小部件綁定到搜索文本框。一切工作正常,包括緩存,除了我追加我的搜索字詞時不必要的服務器調用,因爲我不重複剛剛檢索的結果。如何在追加搜索詞時重用jquery-ui-autocomplete緩存結果?

例如,搜索「ab」從服務器獲取一些結果。在搜索框中的「ab」之後鍵入「c」會從服務器獲取「abc」結果,而不是重複使用緩存的「ab」結果,並省略與「abc」不匹配的結果。

我沿着手動查找「ab」搜索結果的路徑,使用正則表達式來篩選它們以選擇「abc」子集,但是這看起來完全像是在重新發明輪子。什麼是正確的,規範的方式告訴小部件使用「ab」結果,但過濾他們的「ABC」條款,並重新顯示縮短的下拉?

function bindSearchForm() { 
    "use strict"; 
    var cache = new Object(); 

    $('#search_text_field').autocomplete({ 
     minLength: 2, 
     source: function (request, response) { 
      var term = request.term; 
      if (term in cache) { 
       response(cache[term]); 
       return; 
      } 
      $.ajax({type: 'POST', 
        dataType: 'json', 
        url: '/get_search_data', 
        data: {q: term}, 
        success: function (data) { 
         cache[term] = data; 
         response(data); 
        } 
      }); 
    }); 
} 
+0

有趣的問題,但多少這實際上節省了你?看起來它可能比它的價值更麻煩...... –

+0

@Andrew Whitaker:這對於大型數據集可以節省很多;例如將「c」和「d」附加到最初的「ab」搜索詞當前會導致三次服務器調用,可能只是一次初始調用。 – gorus

+0

夠公平的。我不知道有這樣一個規範的方法。您將不得不遍歷緩存中的每個項目,並檢索緩存的結果,該結果是您搜索的內容的前綴。然後,您需要按當前搜索詞過濾* that *搜索的結果。 –

回答

2

這是我的「蠻力,重新發明輪子」的方法,現在看起來就像是正確的解決方案。

function bindSearchForm() { 
    "use strict"; 
    var cache = new Object(); 
    var terms = new Array(); 

    function cacheNewTerm(newTerm, results) { 
     // maintain a 10-term cache 
     if (terms.push(newTerm) > 10) { 
      delete cache[terms.shift()]; 
     } 
     cache[newTerm] = results; 
    }; 

    $('#search_text_field').autocomplete({ 
     minLength: 2, 
     source: function (request, response) { 
      var term = request.term.toLowerCase(); 
      if (term in cache) { 
       response(cache[term]); 
       return; 
      } else if (terms.length) { 
       var lastTerm = terms[terms.length - 1]; 
       if (term.substring(0, lastTerm.length) === lastTerm) { 
        var results = new Array(); 
        for (var i = 0; i < cache[lastTerm].length; i++) { 
         if (cache[lastTerm][i].label.toLowerCase().indexOf(term) !== -1) { 
          results.push(cache[lastTerm][i]); 
         } 
        } 
        response(results); 
        return; 
       } 
      } 
      $.ajax({type: 'POST', 
        dataType: 'json', 
        url: '/get_search_data', 
        data: {q: term}, 
        success: function (data) { 
         cacheNewTerm(term, data); 
         response(data); 
         return; 
        } 
      }); 
    }); 
} 
+0

僅供參考我試圖將您的解決方案應用到我的多個自動完成選擇器中,但我花了近一天的時間試圖讓它現在正常工作,所以只需要保留緩存,並且有更多的訪問服務器:( – Blingers

0

如果有人想支持在文本框中的多個條目,那麼請參見下面的版本:

$(function() { 
function split(val) { 
    return val.split(/,\s*/); 
} 

function extractLast(term) { 
    return split(term).pop(); 
} 

var cache = new Object(); 
var terms = new Array(); 

function cacheNewTerm(newTerm, results) { 
    // keep cache of 10 terms 
    if (terms.push(newTerm) > 10) { 
     delete cache[terms.shift()]; 
    } 
    cache[newTerm] = results; 
} 

$("#searchTextField") 
    .on("keydown", 
     function (event) { 
      if (event.keyCode === $.ui.keyCode.TAB && 
       $(this).autocomplete("instance").menu.active) { 
       event.preventDefault(); 
      } 
     }) 
    .autocomplete({ 
     minLength: 2, 
     source: function (request, response) { 
      var term = extractLast(request.term.toLowerCase()); 
      if (term in cache) { 
       response(cache[term]); 
       return; 
      } else if (terms.length) { 
       var lastTerm = terms[terms.length - 1]; 
       console.log('LAst Term: ' + lastTerm); 
       if (term.substring(0, lastTerm.length) === lastTerm) { 
        var results = new Array(); 
        for (var i = 0; i < cache[lastTerm].length; i++) { 
         console.log('Total cache[lastTerm[.length] = ' + 
          cache[lastTerm].length + 
          '....' + 
          i + 
          '-' + 
          lastTerm[i]); 
         console.log('Label-' + cache[lastTerm][i]); 
         var cachedItem = cache[lastTerm][i]; 
         if (cachedItem != null) { 
          if (cachedItem.toLowerCase().indexOf(term) !== -1) { 
           results.push(cache[lastTerm][i]); 
          } 
         } 
        } 
        response(results); 
        return; 
       } 
      } 

      $.ajax({ 
       url: '@Url.Action("GetSearchData", "Home")', 
       dataType: "json", 
       contentType: 'application/json, charset=utf-8', 
       data: { 
        term: extractLast(request.term) 
       }, 
       success: function (data) { 
        cacheNewTerm(term, data); 
        response($.map(data, 
         function (item) { 
          return { 
           label: item 
          }; 
         })); 
       }, 
       error: function (xhr, status, error) { 
        alert(error); 
       } 
      }); 
     }, 
     search: function() { 
      var term = extractLast(this.value); 
      if (term.length < 2) { 
       return false; 
      } 
     }, 
     focus: function() { 
      return false; 
     }, 
     select: function (event, ui) { 
      var terms = split(this.value); 
      terms.pop(); 
      terms.push(ui.item.value); 
      terms.push(""); 
      this.value = terms.join(", "); 
      return false; 
     } 
    });