2010-11-01 6 views
10

Làm cách nào bạn có thể đặt giới hạn cho kết quả từ tự động hoàn thành jQuery?Giới hạn kết quả trong jQuery Tự động hoàn thành

Đây là mã của tôi:

 $.ajax({ 
      url: "/cache/search/SearchModels.xml", 
      dataType: "xml", 
      success: function(xmlResponse) { 
       var data = $("SearchModel", xmlResponse).map(function() { 
        return { 
         value: $("Name", this).text() + ", " + $("Description", this).text(), 
         id: $("No", this).text(), 
         name: $("Name", this).text(), 
         url: $("URL", this).text() 
        }; 
       }).get(); 
       $("#txtTopSearch").autocomplete({ 
        source: data, 
        minLength: 2, 
        select: function(event, ui) { 
         BlockUI(); 
         if (typeof (ui.item.url) != 'undefined') { 
          window.location = ui.item.url; 
         } 
         else { 
          alert('Page not found!'); 
          $.unblockUI(); 
         } 
        }, 
        search: function(event, ui) { 
         $('#txtTopSearch').addClass('searchInProgress'); 
        }, 
        close: function(event, ui) { 
         $('#txtTopSearch').removeClass('searchInProgress'); 
        } 
       }).data("autocomplete")._renderItem = function(ul, item) { 
        return $("<li></li>") 
        .data("item.autocomplete", item) 
        .append("<a><span style='font-size:.9em; font-weight:bold;'>" + item.id + "</span><br /><span style='font-size:.8em;'>" + item.name + "</span></a>") 
        .appendTo(ul); 
       }; 
      }, 
      error: function(xhr, textStatus, errorThrown) { 
       alert('Error: ' + xhr.statusText); 
      } 
     }); 

này mã trở lại tất cả các kết quả trong truy vấn, nhưng tôi muốn giới hạn này để chỉ hiển thị 10 kết quả. Trong phiên bản tự động hoàn thành cũ có một tùy chọn cho điều này, nhưng nó bây giờ không được chấp nhận.

Ví dụ về XML:

<?xml version="1.0"?> 
<ArrayOfSearchModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <SearchModel> 
    <No>1</No> 
    <Name>My product</Name> 
    <Description>My description</Description> 
    <Tags>blue;brown;</Tags> 
    <URL>/Products/1</URL> 
    </SearchModel> 
</ArrayOfSearchModel> 

Trả lời

11

Cập nhật cuối cùng
sau khi hiểu được rằng trong câu trả lời trước đây của tôi, tôi đã hạn chế kết quả toàn bộ xml thiết lập và không phải là kết quả của autocomplete

Như các bạn đã ghi đè phương pháp mặc định _renderItem, bạn có thể ghi đè lên mặc định _renderMenu.

$.ui.autocomplete.prototype._renderMenu = function(ul, items) { 
    var self = this; 
    $.each(items, function(index, item) { 
     if (index < 10) // here we define how many results to show 
     {self._renderItem(ul, item);} 
     }); 
} 

câu trả lời được sửa đổi từ này jQueryUI: how can I custom-format the Autocomplete plug-in results? nên nhờ đến @cheeso ..


gốc trả lời

Trong bạn success callback sử dụng $("SearchModel:lt(10)", xmlResponse).map(...

Các :lt(10) được các yếu tố với chỉ số dưới 10. Vì vậy, tối đa 10 resu LTS sẽ được trả lại ..

(tất nhiên số 10 có thể là bất cứ điều gì bạn muốn)

Nhìn vào :lt() cụ chọn ở http://api.jquery.com/lt-selector/

cập nhật

Mặc dù tôi không thể hiểu tại sao câu trả lời đầu tiên không hoạt động, vì SearchModel là một thẻ và chúng tôi nhắm mục tiêu đến .. chúng tôi có thể di chuyển bộ lọc trong phương thức bản đồ.

success: function(xmlResponse) { 
       var data = $("SearchModel", xmlResponse).map(function(index) { 
        if (index<10) 
         { 
         return { 
          value: $("Name", this).text() + ", " + $("Description", this).text(), 
          id: $("No", this).text(), 
          name: $("Name", this).text(), 
          url: $("URL", this).text() 
           }; 
         } 
         else 
         { return null; } 
       }).get(); 

documentation of map()

+0

Đề xuất đầy hứa hẹn, nhưng nó không hoạt động. Nó không giống như 'SearchModel' là một bộ chọn thông thường. – Martin

+0

@Martin, tôi cho rằng đó là một thẻ được sử dụng bên trong xml. Bạn có thể đăng một số nội dung từ tệp XML không? tôi sẽ đăng một giải pháp thay thế bằng cách sử dụng phương thức 'map' –

+0

Cảm ơn bạn, tôi đã cập nhật câu hỏi của mình với ví dụ về một nút. – Martin

3

Tại sao không giới hạn dữ liệu truy vấn của bạn trả về từ nguồn xml của bạn?

Edit:

Bạn phải nhớ rằng các chức năng autocomplete được về cơ bản cách sử dụng một regex để phù hợp với các mục trong nguồn dữ liệu. Có nguồn dữ liệu lớn là xấu vì nó phải phân tích rất nhiều dữ liệu đơn giản để tìm đúng mục.

+0

Chắc chắn, tôi rất thích làm điều đó, nhưng làm thế nào? Tôi đã tìm các tùy chọn giới hạn trong jQuery '.map()' và '.get()' nhưng không tìm thấy bất kỳ, im kinda bị mắc kẹt. – Martin

+0

Giảm kích thước tệp xml. Nếu bạn không quan tâm đến việc hiển thị tất cả các kết quả đang được so khớp trong tệp thì hãy giảm kích thước của tệp (số thứ trong đó). – Achilles

+0

Đủ công bằng, nhưng không có cách nào khác để làm điều này mà không thay đổi tệp XML? – Martin

1

Bạn có thể thêm một handler cho sự kiện "mở":

open:function(event,ui){ 
    var maxListLength=10; 
    var ul = jQuery("#txtTopSearch").autocomplete("widget")[0]; 
    while(ul.childNodes.length > maxListLength) 
      ul.removeChild(ul.childNodes[ul.childNodes.length-1]); 
    } 
2

Đây là những gì tôi đã dựa trên một số đọc các tài liệu autocomplete API

$input.autocomplete({ 
    source: function(request, response) { 
    $.getJSON('search.php', request, function(data, status, xhr) { 
     // return a max of 10 results. 
     response(data.slice(0, 9)); 
    }); 
    } 
}) 

Làm theo mẫu này sẽ tiết kiệm được việc phải làm bất kỳ thứ gì sôi nổi trong lớp kết xuất.

+0

nó sẽ không có ý nghĩa hơn để giới hạn kích thước của tập kết quả ở phía máy chủ? ví dụ: với mệnh đề LIMIT trong truy vấn SQL? – David

+0

Điều đó sẽ tốt hơn nhưng tôi không có quyền truy cập vào bộ mã đó. –

1

Cách nhanh nhất để giới hạn kết quả là làm điều đó trong sự kiện "mở". Chúng ta có thể xóa một phần nội dung được tạo bởi jquery ui, giảm mảng phần tử con.

Giải pháp này giải quyết cùng một vấn đề đối với tôi:

var maxResults = 10; 
$input.autocomplete({ 
    source: somefile.json, 
    open: function(event,ui){ 
      $(this).data("uiAutocomplete").menu.element.children().slice(maxResults).remove(); 
     } 
})