Otomatik Tamamlama eklenti sonuçlarını nasıl özel olarak biçimlendirebilirim?


Yanıtlar:


233

Canlı öneri ile otomatik tamamlama

Evet, maymun yama otomatik tamamlama yaparsanız yapabilirsiniz.

JQuery UI'nin v1.8rc3'ünde bulunan otomatik tamamlama widget'ında, otomatik tamamlama widget'ının _renderMenu işlevinde öneriler açılır. Bu işlev şu şekilde tanımlanır:

_renderMenu: function( ul, items ) {
    var self = this;
    $.each( items, function( index, item ) {
        self._renderItem( ul, item );
    });
},

_RenderItem işlevi şu şekilde tanımlanır:

_renderItem: function( ul, item) {
    return $( "<li></li>" )
        .data( "item.autocomplete", item )
        .append( "<a>" + item.label + "</a>" )
        .appendTo( ul );
},

Yapmanız gereken şey, _renderItem fn yerine istediğiniz efekti üreten kendi yaratımınızla değiştirmek. Bu tekniğe, bir kütüphanede dahili bir işlevi yeniden tanımlayarak, öğrendiğim maymun yaması denir . İşte böyle yaptım:

  function monkeyPatchAutocomplete() {

      // don't really need this, but in case I did, I could store it and chain
      var oldFn = $.ui.autocomplete.prototype._renderItem;

      $.ui.autocomplete.prototype._renderItem = function( ul, item) {
          var re = new RegExp("^" + this.term) ;
          var t = item.label.replace(re,"<span style='font-weight:bold;color:Blue;'>" + 
                  this.term + 
                  "</span>");
          return $( "<li></li>" )
              .data( "item.autocomplete", item )
              .append( "<a>" + t + "</a>" )
              .appendTo( ul );
      };
  }

Bu işlevi bir kez ara $(document).ready(...).

Şimdi, bu bir hack, çünkü:

  • listede oluşturulan her öğe için bir regexp nesnesi oluşturulur. Bu normal ifade nesnesinin tüm öğeler için yeniden kullanılması gerekir.

  • tamamlanan parçanın biçimlendirilmesinde kullanılan bir css sınıfı yoktur. Satır içi bir stil.
    Bu, aynı sayfada birden fazla otomatik tamamlamanız varsa, hepsinin aynı işlemi göreceği anlamına gelir. Bir css stili bunu çözerdi.

... ancak ana tekniği gösterir ve temel gereksinimleriniz için çalışır.

alternatif metin

güncellenmiş çalışma örneği: http://output.jsbin.com/qixaxinuhe


Yazılan karakterlerin durumunu kullanmak yerine, eşleme dizelerinin durumunu korumak için şu satırı kullanın:

var t = item.label.replace(re,"<span style='font-weight:bold;color:Blue;'>" + 
          "$&" + 
          "</span>");

Başka bir deyişle, yukarıda orijinal kodundan başlayarak, sadece değiştirmeniz gerekiyor this.termile "$&".


EDIT
Yukarıdaki sayfadaki tüm otomatik tamamlama widget'larını değiştirir . Yalnızca bir tanesini değiştirmek istiyorsanız, şu soruya bakın:
Bir sayfada Otomatik Tamamlama * nın yalnızca bir * örneğini nasıl yamalatırsınız?


Teşekkürler Cheeso. Bunun için jsbin bağlantınız var mı?
dev.e.loper

1
Eğer zincirleme şeyler yaparsanız, bağlamı sıfırlamanız önemlidir: oldFn.apply (this, [ul, item]);
emanaton

Çok teşekkür ederim! Bu jQuery UI bir parçası olsaydı harika olurdu.
David Ryder

4
Söyleyeceğim bir şey, eşleşen dizenin (yalnızca başlangıç ​​değil) herhangi bir bölümünde sonucu kalınlaştırmak istiyorsanız, RegExp satırını buna değiştirin: var re = new RegExp (this.term);
David Ryder

1
JQueryUI otomatik tamamlama varsayılan olarak büyük / küçük harfe duyarlı olmayan bir arama yapıyor gibi görünüyor, bu nedenle RegExp nesnesine "i" bayrağı eklemek mantıklı. @DavidRyder'in belirttiği gibi normal ifadede "^" kullanmak için de bir neden yoktur. Beğen: var re = new RegExp(this.term, "i"); Harika gönderi!
Sam

65

bu da işe yarar:

       $.ui.autocomplete.prototype._renderItem = function (ul, item) {
            item.label = item.label.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(this.term) + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
            return $("<li></li>")
                    .data("item.autocomplete", item)
                    .append("<a>" + item.label + "</a>")
                    .appendTo(ul);
        };

@ Jörn Zaefferer ve @ Cheeso'nun yanıtlarının bir kombinasyonu.


Tüm kelimeyle eşleştiği için bunu daha çok sevdim.
atp

3
Bu iyi çalışıyor. Dikkat edilmesi gereken tek şey, item.label öğesinin değiştirilmesidir. Benim için metin kutuma "<güçlü ..." alıyordum. Değiştirme sonucunu başka bir değişkene atamak bunu temizledi. Verileriniz metin kutusuna yerleştirilen bir değer özelliği içeriyorsa bu sorunla karşılaşmazsınız.
Kijana Woodard

birden çok değeri destekleyen bir otomatik tamamlamanız varsa bu çalışmaz. baska öneri?
leora

Otomatik tamamlama sonuçlarınızda metin vurgulamanın en basit yolu. Açıkçası yukarıdaki leora ve Kijana tarafından işaret edilen böceklere dikkat edin
adamst85

@RNKushwaha aramadan önce herhangi bir yerde$().autocomplete()
Brian Leishman

8

Süper yararlı. Teşekkür ederim. +1.

"String" terimi ile başlamalıdır "şeklinde sıralanan hafif bir sürüm:

function hackAutocomplete(){

    $.extend($.ui.autocomplete, {
        filter: function(array, term){
            var matcher = new RegExp("^" + term, "i");

            return $.grep(array, function(value){
                return matcher.test(value.label || value.value || value);
            });
        }
    });
}

hackAutocomplete();

1
Teşekkürler Orolo, birden fazla yerde otomatik tamamlama kullanıyordum ve sadece yazılan karakterlerle başlayan sonucu göstermek için değişikliği yapabileceğim merkezi bir yer istedim ve bu tam olarak ihtiyacım olan şey!
dreamerkumar

Teşekkürler. Bu en iyi çözümdür. Büyük / küçük harfe duyarlı değildir.
Aniket Kulkarni

7

İşte fonksiyonel tam bir örnek:

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Autocomplete - jQuery</title>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css">
</head>
<body>
<form id="form1" name="form1" method="post" action="">
  <label for="search"></label>
  <input type="text" name="search" id="search" />
</form>

<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.2/jquery-ui.js"></script>
<script>
$(function(){

$.ui.autocomplete.prototype._renderItem = function (ul, item) {
    item.label = item.label.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(this.term) + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
    return $("<li></li>")
            .data("item.autocomplete", item)
            .append("<a>" + item.label + "</a>")
            .appendTo(ul);
};


var availableTags = [
    "JavaScript",
    "ActionScript",
    "C++",
    "Delphi",
    "Cobol",
    "Java",
    "Ruby",
    "Python",
    "Perl",
    "Groove",
    "Lisp",
    "Pascal",
    "Assembly",
    "Cliper",
];

$('#search').autocomplete({
    source: availableTags,
    minLength: 3
});


});
</script>
</body>
</html>

Bu yardımcı olur umarım


6

jQueryUI 1.9.0 _renderItem'in çalışma şeklini değiştirir.

Aşağıdaki kod bu değişikliği dikkate alır ve ayrıca nasıl Jörn Zaefferer'ın jQuery Autocomplete eklentisi kullanarak vurgu eşleme yaptığını gösterir. Genel arama terimindeki tüm ayrı terimleri vurgulayacaktır.

Knockout ve jqAuto kullanmaya başladığımdan beri, sonuçları şekillendirmenin çok daha kolay bir yolunu buldum.

function monkeyPatchAutocomplete() {
   $.ui.autocomplete.prototype._renderItem = function (ul, item) {

      // Escape any regex syntax inside this.term
      var cleanTerm = this.term.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');

      // Build pipe separated string of terms to highlight
      var keywords = $.trim(cleanTerm).replace('  ', ' ').split(' ').join('|');

      // Get the new label text to use with matched terms wrapped
      // in a span tag with a class to do the highlighting
      var re = new RegExp("(" + keywords + ")", "gi");
      var output = item.label.replace(re,  
         '<span class="ui-menu-item-highlight">$1</span>');

      return $("<li>")
         .append($("<a>").html(output))
         .appendTo(ul);
   };
};

$(function () {
   monkeyPatchAutocomplete();
});

'(' Gibi karakterlerle arama yaptığımda hataya neden oluyor ("Yakalanmaamayan SyntaxError: Geçersiz normal ifade: / (sam | at | () /: Sonlandırılmamış grup") zaten regex ile çarpışmayı önleyerek bu sorunu çözmek için?
Idan Shechter

Müthiş cevap! Nerede göründüklerine bakılmaksızın terimleri vurgular. Çok havalı. Yayını güncellediğiniz için teşekkür ederiz. Ben var mıydı bir soru kullandığınız .ui-menü-madde-vurgu sınıf hakkında. Bunun jquery-ui veya tüketiciler tarafından tanımlanması bekleniyor mu? Sınıf adını kendi yöntemime göre değiştirdim ve sadece yazı tipi kalınlığını kalınlaştırdım. .jqAutocompleteMatch { font-weight: bold; }
Sam

@IdanShechter Harika yorum. this.termHerhangi bir işlem yapmadan önce forgegex'ten kaçmak için bazı mantık kullanılmalıdır. Bunu nasıl yapacağınıza dair birçok yanıttan biri olarak Javascript normal ifadesinde kullanmak için Escape dizesi konusuna bakın .
Sam

3

daha da kolay bir yol için şunu deneyin:

$('ul: li: a[class=ui-corner-all]').each (function (){      
 //grab each text value 
 var text1 = $(this).text();     
 //grab user input from the search box
 var val = $('#s').val()
     //convert 
 re = new RegExp(val, "ig") 
 //match with the converted value
 matchNew = text1.match(re);
 //Find the reg expression, replace it with blue coloring/
 text = text1.replace(matchNew, ("<span style='font-weight:bold;color:green;'>")  + matchNew +    ("</span>"));

    $(this).html(text)
});
  }

3

İşte Ted de Koning'in çözümünün yeniden canlandırılması. O içerir :

  • Büyük / küçük harfe duyarlı olmayan arama
  • Aranan dizenin birçok örneğini bulma
$.ui.autocomplete.prototype._renderItem = function (ul, item) {

    var sNeedle     = item.label;
    var iTermLength = this.term.length; 
    var tStrPos     = new Array();      //Positions of this.term in string
    var iPointer    = 0;
    var sOutput     = '';

    //Change style here
    var sPrefix     = '<strong style="color:#3399FF">';
    var sSuffix     = '</strong>';

    //Find all occurences positions
    tTemp = item.label.toLowerCase().split(this.term.toLowerCase());
    var CharCount = 0;
    tTemp[-1] = '';
    for(i=0;i<tTemp.length;i++){
        CharCount += tTemp[i-1].length;
        tStrPos[i] = CharCount + (i * iTermLength) + tTemp[i].length
    }

    //Apply style
    i=0;
    if(tStrPos.length > 0){
        while(iPointer < sNeedle.length){
            if(i<=tStrPos.length){
                //Needle
                if(iPointer == tStrPos[i]){
                    sOutput += sPrefix + sNeedle.substring(iPointer, iPointer + iTermLength) + sSuffix;
                    iPointer += iTermLength;
                    i++;
                }
                else{
                    sOutput += sNeedle.substring(iPointer, tStrPos[i]);
                    iPointer = tStrPos[i];
                }
            }
        }
    }


    return $("<li></li>")
        .data("item.autocomplete", item)
        .append("<a>" + sOutput + "</a>")
        .appendTo(ul);
};

1
Sanırım tekerleği yeniden icat ediyorsun! Neden tüm bu kodlardan daha hızlı, daha kolay ve daha kompakt düzenli ifadeler kullanmıyorsunuz?
George Mavritsakis

2

Burada, normal ifadeler gerektirmeyen ve etiketteki birden çok sonuçla eşleşen bir sürüm var.

$.ui.autocomplete.prototype._renderItem = function (ul, item) {
            var highlighted = item.label.split(this.term).join('<strong>' + this.term +  '</strong>');
            return $("<li></li>")
                .data("item.autocomplete", item)
                .append("<a>" + highlighted + "</a>")
                .appendTo(ul);
};

Bu muhtemelen en iyi çözümdür, ancak string.split sadece büyük / küçük harfe duyarlı eşleşmeler yapabileceğine inanıyorum.
Noel Abrahams

Büyük / küçük harfe duyarlı olmayan kelimeleri temel alarak eşleştirmenin bir yolu var mı? Çünkü "alfa" aramam varsa, "Alfa" yı vurgulamayacaktır
Patrick


1

İşte benim sürüm:

  • Dizeleri kırmak / yayılma aralığı etiketlerini kesmek için RegEx yerine DOM işlevlerini kullanır
  • Yalnızca belirtilen otomatik tamamlama etkilenir, hepsi değil
  • UI sürüm 1.9.x ile çalışır
function highlightText(text, $node) {
    var searchText = $.trim(text).toLowerCase(),
        currentNode = $node.get(0).firstChild,
        matchIndex,
        newTextNode,
        newSpanNode;
    while ((matchIndex = currentNode.data.toLowerCase().indexOf(searchText)) >= 0) {
        newTextNode = currentNode.splitText(matchIndex);
        currentNode = newTextNode.splitText(searchText.length);
        newSpanNode = document.createElement("span");
        newSpanNode.className = "highlight";
        currentNode.parentNode.insertBefore(newSpanNode, currentNode);
        newSpanNode.appendChild(newTextNode);
    }
}
$("#autocomplete").autocomplete({
    source: data
}).data("ui-autocomplete")._renderItem = function (ul, item) {
    var $a = $("<a></a>").text(item.label);
    highlightText(this.term, $a);
    return $("<li></li>").append($a).appendTo(ul);
};

Eşleşen metni vurgulama örneği


1

aşağıdaki kodu kullanabilirsiniz:

lib:

$.widget("custom.highlightedautocomplete", $.ui.autocomplete, {
    _renderItem: function (ul, item) {
        var $li = $.ui.autocomplete.prototype._renderItem.call(this,ul,item);
        //any manipulation with li
        return $li;
    }
});

ve mantık:

$('selector').highlightedautocomplete({...});

orijinal eklenti prototipinin _renderItemüzerine yazmadan geçersiz kılabilecek özel widget oluşturur _renderItem.

benim örneğimde bazı kodları basitleştirmek için orijinal render fonksiyonu da kullanıldı

eklentiyi farklı otomatik tamamlama görünümüne sahip farklı yerlerde kullanmak ve kodunuzu kırmak istemiyorsanız önemlidir.


Genel olarak, daha önce cevaplanmış olan 6 yaşında bir soruyu cevaplamak yerine, daha yeni soruları cevaplamak için zaman harcamak daha iyidir.
zchrykng

0

Bunun yerine 3. taraf eklentisini kullanırsanız, bir vurgulama seçeneği vardır: http://docs.jquery.com/Plugins/Autocomplete/autocomplete#url_or_dataoptions

(Seçenekler sekmesine bakın)


evet bu eklentinin farkındayım. Ancak, uygulamamızda jQueryUI kullanıyoruz, bu yüzden jQueryUI Otomatik Tamamlama eklentisi ile bu çalışmayı elde etmek güzel olurdu
dev.e.loper

1
2010-06-23 itibariyle, jQuery Otomatik Tamamlama eklentisi, jQuery UI Otomatik Tamamlama eklentisi lehine kullanımdan kaldırılmıştır. Daha fazla bilgi için bassistance.de/jquery-plugins/jquery-plugin-autocomplete adresini ziyaret edin
shek

0

Birden çok değeri desteklemek için aşağıdaki işlevi eklemeniz yeterlidir:

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

var t = String(item.value).replace(new RegExp(getLastTerm(this.term), "gi"), "<span class='ui-state-highlight'>$&</span>");
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.