JQuery UI otomatik tamamlamada hiçbir sonuç tespit edilemiyor


89

Siz beni onlara yönlendirmeden önce, evet, bu konudaki yarım düzine gönderiyi gözden geçirdim, ancak bunun neden işe yaramadığı konusunda hala engelliyim.

Amacım, otomatik tamamlamanın ne zaman 0 sonuç verdiğini tespit etmektir. İşte kod:

 $.ajax({
   url:'sample_list.foo2',
   type: 'get',
   success: function(data, textStatus, XMLHttpRequest) {
      var suggestions=data.split(",");

  $("#entitySearch").autocomplete({ 
    source: suggestions,
    minLength: 3,
    select: function(e, ui) {  
     entityAdd(ui.item.value);
     },
    open: function(e, ui) { 
     console.log($(".ui-autocomplete li").size());
     },
    search: function(e,ui) {
     console.log("search returned: " + $(".ui-autocomplete li").size());

    },
    close: function(e,ui) {  
     console.log("on close" +  $(".ui-autocomplete li").size());    
     $("#entitySearch").val("");
    }
   }); 

  $("#entitySearch").autocomplete("result", function(event, data) {

   if (!data) { alert('nothing found!'); }

  })
 }
}); 

Aramanın kendisi iyi çalışıyor, sonuçların sorunsuz görünmesini sağlayabilirim. Anladığım kadarıyla, ben gereken otomatik tamamlama ( "sonuç") işleyicisi ile sonuçlarını durdurmak mümkün olacaktır. Bu durumda asla ateşlenmez. (Sonuçların sayısına atıfta bulunmayan genel bir uyarı veya console.log bile asla tetiklenmez). Açık olay işleyicisi, doğru sonuç sayısını gösterir (sonuçlar olduğunda) ve arama ve kapatma olay işleyicileri, her zaman bir adım geride olan bir sonuç boyutu bildirir.

Burada bariz ve apaçık bir şeyi kaçırdığımı hissediyorum ama bunu göremiyorum.


İstemci tarafı verilerle yönlendirilen bir otomatik tamamlama aracı ile bunu başarmanın kolay bir yolu yok gibi görünüyor. Widget için uzak bir kaynak kullanmak bir seçenek midir?
Andrew Whitaker

Yanıtlar:


201

jQueryUI 1.9

jQueryUI 1.9, otomatik tamamlama widget'ını responseetkinlikle kutsadı; bu , hiçbir sonucun döndürülmediğini tespit etmek için yararlanabileceğimiz bir etkinlik:

Bir arama tamamlandıktan sonra menü gösterilmeden önce tetiklenir. Özel bir kaynak seçeneği geri aramasının gerekli olmadığı durumlarda öneri verilerinin yerel olarak işlenmesi için kullanışlıdır. Bu olay, sonuç olmadığından veya Otomatik Tamamlama devre dışı bırakıldığından menü gösterilmese bile, bir arama tamamlandığında her zaman tetiklenir.

Bu nedenle, bunu akılda tutarak, jQueryUI 1.8'de yapmamız gereken hackleme şu şekilde değiştirildi:

$(function() {
    $("input").autocomplete({
        source: /* */,
        response: function(event, ui) {
            // ui.content is the array that's about to be sent to the response callback.
            if (ui.content.length === 0) {
                $("#empty-message").text("No results found");
            } else {
                $("#empty-message").empty();
            }
        }
    });
});​

Örnek: http://jsfiddle.net/andrewwhitaker/x5q6Q/


jQueryUI 1.8

Bunu jQueryUI API ile yapmanın kolay bir yolunu bulamadım, ancak autocomplete._responseişlevi kendi işlevinizle değiştirebilir ve ardından varsayılan jQueryUI işlevini çağırabilirsiniz ( otomatik tamamlamanın prototypenesnesini genişletmek için güncellendi ) :

var __response = $.ui.autocomplete.prototype._response;
$.ui.autocomplete.prototype._response = function(content) {
    __response.apply(this, [content]);
    this.element.trigger("autocompletesearchcomplete", [content]);
};

Ve sonra olaya bir olay işleyicisini bağlayın autocompletesearchcomplete(içerik, aramanın sonucudur, bir dizidir):

$("input").bind("autocompletesearchcomplete", function(event, contents) {
    $("#results").html(contents.length);
});

Burada olan şey, otomatik tamamlamanın responseişlevini bir değişkene ( __response) kaydetmeniz ve ardından applyonu tekrar çağırmak için kullanmanızdır . Varsayılan yöntemi çağırdığınız için bu yöntemin herhangi bir yan etkisi olduğunu düşünemiyorum. Nesnenin prototipini değiştirdiğimiz için, bu tüm otomatik tamamlama widget'ları için çalışacaktır.

İşte çalışan bir örnek : http://jsfiddle.net/andrewwhitaker/VEhyV/

Örneğim, veri kaynağı olarak yerel bir dizi kullanıyor, ancak bunun önemli olması gerektiğini düşünmüyorum.


Güncelleme: Ayrıca, yeni işlevselliği kendi pencere aracına da sığdırarak varsayılan otomatik tamamlama işlevini genişletebilirsiniz:

$.widget("ui.customautocomplete", $.extend({}, $.ui.autocomplete.prototype, {

  _response: function(contents){
      $.ui.autocomplete.prototype._response.apply(this, arguments);
      $(this.element).trigger("autocompletesearchcomplete", [contents]);
  }
}));

Aramanızı şu şekilde .autocomplete({...});değiştirme:

$("input").customautocomplete({..});

Daha sonra özel autocompletesearchcompleteetkinliğe bağlanın :

$("input").bind("autocompletesearchcomplete", function(event, contents) {
    $("#results").html(contents.length);
});

Burada bir örneğe bakın : http://jsfiddle.net/andrewwhitaker/VBTGJ/


Bu soru / cevap biraz dikkat çektiğinden, bunu başarmak için bu cevabı daha da güncelleyeceğimi düşündüm. Bu yöntem en çok , sayfada yalnızca bir otomatik tamamlama widget'ınız olduğunda kullanışlıdır . Bunu yapmanın bu yolu, uzak veya yerel bir kaynak kullanan bir otomatik tamamlama widget'ına uygulanabilir:

var src = [...];

$("#auto").autocomplete({
    source: function (request, response) {
        var results = $.ui.autocomplete.filter(src, request.term);

        if (!results.length) {
            $("#no-results").text("No results found!");
        } else {
            $("#no-results").empty();
        }

        response(results);
    }
});

İçinde ifhiçbir sonuç tespit edilmediğinde çalıştırmak için özel mantığınızı yerleştireceğiniz yer burasıdır.

Örnek: http://jsfiddle.net/qz29K/

Uzak bir veri kaynağı kullanıyorsanız, şuna benzer bir şey söyleyin:

$("#auto").autocomplete({
    source: "my_remote_src"
});

Ardından, AJAX'ın kendiniz araması ve 0 sonuç geldiğinde bunu algılayabilmesi için kodunuzu değiştirmeniz gerekir:

$("#auto").autocomplete({
    source: function (request, response) {
        $.ajax({
            url: "my_remote_src", 
            data: request,
            success: function (data) {
                response(data);
                if (data.length === 0) {
                    // Do logic for empty result.
                }
            },
            error: function () {
                response([]);
            }
        });
    }
});

@Andrew, jQuery kullanarak "content" dizisindeki öğelere nasıl erişebileceğim hakkında bir fikriniz var mı ???
Bongs

1
@Bongs: Dizine doğrudan erişebilmelisinizcontents[0]
Andrew Whitaker

Aslında önemli olan, içerik dizisinin kullanıcı adı ve görüntüsü ile doldurulmuş olması ve dizin değerini belirterek ona erişememesidir. Ama çözümü buldum. İçindekiler [i] .user.username ... :) cevabınız ve harika çözüm için teşekkürler ...
Bongs

Yukarıdaki çözüm, aynı jQuery eklentisine dayanan PrimeFaces otomatik tamamlama (2.2.x) için de harika çalışıyor.
wrschneider

3
JqueryUI 1.8.19'da, _response işlevi __response olarak yeniden adlandırıldı. ( goo.gl/zAl88 ). Böylece, $ .ui.autocomplete.prototype._response, $ .ui.autocomplete.prototype .__ yanıt oldu
crazyphoton

6

Herkes kolay, yerleşik yolu görmezden geliyor gibi görünüyor: mesajları kullanın: noResults olayı.

$('#field_name').autocomplete({
  source: $('#field_name').data('autocomplete-source'),
  messages: {
    noResults: function(count) {
      console.log("There were no matches.")
    },
    results: function(count) {
      console.log("There were " + count + " matches")
    }
  }
})

Bu özellik, jQuery 1.9'da deneysel bir özellik olarak eklenmiştir ( burada açıklanmıştır ). Temmuz 2017 itibarıyla henüz API'de belgelenmemiştir .


2

Uzak bir veri kaynağı kullanıyorsanız (bir MySQL veritabanı, PHP veya sunucu tarafında herhangi bir şey) istemciye geri dönecek veri olmadığında (herhangi bir veri kaynağına ihtiyaç duymadan hackler veya temel kod UI kodu değişiklikleri).

Uzak veri kaynağım olarak PHP ve MySQL ve aralarında bilgi aktarmak için JSON kullanıyorum. Benim durumumda, JSON isteği sunucudan bir tür yanıt almadıysa jQuery istisna hataları alıyor gibiydim, bu yüzden veri olmadığında sunucu tarafından boş bir JSON yanıtı döndürmeyi ve ardından istemciyi işlemeyi daha kolay buldum oradan yanıt:

if (preg_match("/^[a-zA-Z0-9_]*$/", $_GET['callback'])) {//sanitize callback name
    $callback = $_GET['callback'];
} else { die(); }

die($callback . "([])");

Başka bir yol da, eşleşen veri olmadığını belirtmek için sunucudan gelen yanıtta bir bayrak döndürmek ve yanıttaki bayrağın varlığına (ve veya değerine) dayalı olarak istemci tarafında eylemler gerçekleştirmektir. Bu durumda sunucuların yanıtı aşağıdaki gibi olacaktır:

die($callback . "([{'nodata':true}])");

Daha sonra bu bayrağa göre istemci tarafında eylemler gerçekleştirilebilir:

$.getJSON('response.php?callback=?', request, function (response) {
    if (typeof response[0].nodata !== 'undefined' && response[0].nodata === true) {
        alert('No data to display!');
    } else {
        //Do whatever needs to be done in the event that there is actually data to display.
    }
});

2

Otomatik tamamlama öğenizi başlattıktan sonra, mesaj göstergesi için varsayılan aralıkları kullanmak istiyorsanız mesaj seçeneğini ayarlayın:

$(<yourselector>).autocomplete('option', 'messages', {
    noResults: 'myKewlMessage',
    results: function( amount ) {
        return amount + ( amount > 1 ? " results were" : " result was" ) + " found.";
    }
});

NOT : Bu deneysel bir API'dir (belgelenmemiştir). jQuery kullanıcı arabirimi geliştiricileri, hala dize işleme ve uluslararasılaştırma için tam bir çözüm araştırmaktadır.


0

Saatler süren oynadıktan sonra nihayet No match foundjQuery otomatik tamamlamada görüntülenecek bir numara buldum . Yukarıdaki koda bakın ve divbenim durumumda basitçe a ekleyin #ulNoMatchve stili displap:none. Geri arama başarı yönteminde, döndürülen dizinin sahip olup olmadığını kontrol edin length == 0. Oradaysa git, gününü yaptın! :)

<pre><div class="ui-widget1" style="width: auto;">
    <asp:TextBox ID="txtSearch" class="tb" runat="server" Width="150px">
    </asp:TextBox>
    <ul id="ulNoMatch" class="ui-autocomplete ui-menu ui-widget1 ui-widget1-content ui-corner-all"
        role="listbox" aria-activedescendant="ui-active-menuitem" style="z-index: 16;
        display: none; width: 150px;">
        <li class="ui-menu-item" role="menuitem"><a class="ui-corner-all" tabindex="-1">No Matches
            Found</a></li>
    </ul>
    </div><pre>
<b>
<b>

Enter code here

<script>
    $(function () {
        $("input[id$='txtSearch']").autocomplete({
            source: function (request, response) {
                $.ajax({
                    url: "splah.aspx/GetByName",
                    data: "{ 'strName': '" + request.term.trim() + "' }",
                    dataType: "json",
                    type: "POST",
                    //cacheLength: 1,
                    contentType: "application/json; charset=utf-8",
                    dataFilter: function (data) {
                        return data; },
                    success: function (data) {
                        var found = $.map(data.d, function (item) {
                            return {
                                value: item.Name,
                                id: item.id
                            }
                         });

                         if (found.length == 0)
                         {
                             $("#ulNoMatch").show();
                         }
                         else
                         {
                             $("#ulNoMatch").hide();
                         }
                         response(found);
                    },
                    error: function (XMLHttpRequest, textStatus, errorThrown) {
                        alert(textStatus);
                    }
                });
            },
            select: function (event, ui) {
                $("input[id$='txtSearch']").val(ui.item.label);
                $("input[id$='txtID']").val(ui.item.id);
                return false;
            },
            minLength: 1
        });
    });
</script>

0
The easiest straight forward way to do it.

$("#search-box").autocomplete({
                    minLength: 2,
                    source:function (request, response) {
                        $.ajax({
                            url: urlPref + "/Api/SearchItems",
                            data: {
                                term: request.term
                            },
                            success: function (data) {
                                if (data.length == 0) {
                                    data.push({
                                        Id: 0,
                                        Title: "No results found"
                                    });
                                }
                                response(data);
                            }
                            });
                        },

Bu cevap yeni bir katkı sağlamaz, kabul edilen cevap aynı koda sahiptir.
Martin

0

sourceÖzel geri aramalı parametrenin neden yeterli olmadığını anlamıyorum :

$("#autocomplete").autocomplete({
    source: function (request, response) {
        $.ajax({
            url: "http://example.com/service.json",
            data: {
                q: this.term
            },
            success: function (data, textStatus, jqXHR) {
                // data would be an array containing 0 or more items
                console.log("[SUCCESS] search returned " + data.length + " item(s)");
                response(data);
            },
            error: function (jqXHR, textStatus, errorThrown) {
                // triggered when AJAX failed because of, for example, malformed JSON
                console.log("[FAILURE] search returned error");
                response([]);
            }
        });
    }
});

-1
function SearchText() {
 $(".autosuggest").autocomplete({
   source: function (request, response) {
    $.ajax({
     type: "POST",
     contentType: "application/json; charset=utf-8",
      url: "Default.aspx/GetAutoCompleteData",
      data: "{'username':'" + document.getElementById('txtSearch').value + "'}",
        dataType: "json",
        success: function (data.d) {
        if ((data.d).length == 0) {
         alert("no result found");
          }
           response(data.d);
         },
         error: function (result) {
              alert("Error");
         }
         });
        }
     });
  }

Bu cevap yeni bir katkı sağlamaz, kabul edilen cevap aynı koda sahiptir.
Martin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.