Bagaimana saya bisa memformat hasil plug-in Autocomplete?

Jawaban:

233

Lengkapi otomatis dengan saran langsung

Ya, Anda bisa jika Anda melengkapi-monyet secara otomatis.

Dalam widget pelengkapan otomatis yang disertakan dalam v1.8rc3 dari jQuery UI, sembulan saran dibuat di fungsi _renderMenu dari widget pelengkapan otomatis. Fungsi ini didefinisikan seperti ini:

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

Fungsi _renderItem didefinisikan seperti ini:

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

Jadi yang perlu Anda lakukan adalah mengganti _renderItem fn itu dengan kreasi Anda sendiri yang menghasilkan efek yang diinginkan. Teknik ini, mendefinisikan kembali fungsi internal di perpustakaan, yang kemudian saya pelajari disebut monyet-tambalan . Begini cara saya melakukannya:

  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 );
      };
  }

Panggil fungsi itu sekali dalam $(document).ready(...).

Sekarang, ini adalah retasan, karena:

  • ada keberatan regexp yang dibuat untuk setiap item yang diberikan dalam daftar. Keberatan regexp itu harus digunakan kembali untuk semua item.

  • tidak ada kelas css yang digunakan untuk memformat bagian yang selesai. Ini gaya inline.
    Ini berarti jika Anda memiliki beberapa pelengkapan otomatis pada halaman yang sama, mereka semua akan mendapatkan perlakuan yang sama. Gaya css akan menyelesaikannya.

... tetapi ini menggambarkan teknik utama, dan itu berfungsi untuk kebutuhan dasar Anda.

teks alternatif

contoh kerja yang diperbarui: http://output.jsbin.com/qixaxinuhe


Untuk mempertahankan case dari string yang cocok, sebagai ganti menggunakan case dari karakter yang diketik, gunakan baris ini:

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

Dengan kata lain, mulai dari kode asli di atas, Anda hanya perlu mengganti this.termdengan "$&".


EDIT
Di atas mengubah setiap widget pelengkapan otomatis pada halaman. Jika Anda ingin mengubah hanya satu, lihat pertanyaan ini:
Bagaimana cara menambal * hanya satu * contoh Pelengkapan Otomatis pada halaman?

Cheeso
sumber
Terima kasih Cheeso. Apakah Anda memiliki tautan jsbin untuk ini?
dev.e.loper
1
Perhatikan bahwa jika Anda melakukan rantai hal bersama, penting untuk mengatur ulang konteks: oldFn.apply (ini, [ul, item]);
emanaton
Terima kasih banyak! Akan luar biasa jika ini menjadi bagian dari jQuery UI.
David Ryder
4
Satu hal yang akan saya katakan adalah jika Anda ingin menebalkan hasilnya di bagian mana pun dari string yang cocok (bukan hanya awal), modifikasi baris RegExp untuk ini: var re = new RegExp (this.term);
David Ryder
1
Pelengkapan otomatis JQueryUI tampaknya melakukan pencarian case-insensitive secara default, jadi masuk akal untuk menambahkan flag "i" di objek RegExp. Juga tidak ada alasan untuk menggunakan "^" di regex seperti yang disebutkan @DavidRyder. Suka: var re = new RegExp(this.term, "i"); Pos hebat!
Sam
65

ini juga berfungsi:

       $.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);
        };

kombinasi jawaban @ Jörn Zaefferer dan @ Cheeso.

Raj
sumber
Saya lebih suka yang ini, karena cocok dengan seluruh kata.
atp
3
Ini bekerja dengan baik. Satu-satunya hal yang harus diperhatikan adalah item.label diganti. Bagi saya, saya mendapatkan "<kuat ..." di kotak teks saya. Hanya dengan menetapkan hasil penggantian ke variabel lain, hapus itu. Anda tidak akan memiliki masalah ini jika data Anda berisi properti nilai yang dimasukkan ke dalam kotak teks.
Kijana Woodard
ini tidak berfungsi jika Anda memiliki pelengkapan otomatis yang mendukung beberapa nilai. ada saran?
leora
Cara termudah untuk mendapatkan sorotan teks dalam hasil pelengkapan otomatis Anda. Jelas melihat bug seperti yang ditunjukkan oleh leora dan Kijana di atas
adamst85
@RNKushwaha di mana saja sebelum Anda menelepon ke$().autocomplete()
Brian Leishman
8

Sangat membantu. Terima kasih. +1.

Berikut ini adalah versi ringan yang mengurutkan pada "String harus dimulai dengan istilah":

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();
orolo
sumber
1
Terima kasih Orolo, saya menggunakan pelengkapan otomatis di beberapa lokasi dan menginginkan tempat sentral di mana saya dapat membuat perubahan untuk hanya menampilkan hasil yang dimulai dengan karakter yang diketik dan yang ini adalah yang saya butuhkan!
dreamerkumar
Terima kasih. Ini adalah solusi terbaik dari semuanya. Ini berfungsi untuk case-sensitive.
Aniket Kulkarni
7

Ini dia, contoh lengkap fungsional:

<!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>

Semoga ini membantu

Fabio Nolasco
sumber
6

jQueryUI 1.9.0 mengubah cara kerja _renderItem.

Kode di bawah ini mempertimbangkan perubahan ini dan juga menunjukkan bagaimana saya melakukan pencocokan sorotan menggunakan plugin jQuery Autocomplete dari Jörn Zaefferer. Ini akan menyoroti semua istilah individual dalam keseluruhan istilah pencarian.

Sejak pindah ke menggunakan Knockout dan jqAuto saya menemukan ini cara yang lebih mudah untuk menata hasil.

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();
});
79IT
sumber
Ketika saya mencari dengan karakter seperti '(' itu menyebabkan kesalahan ("Uncaught SyntaxError: Ekspresi reguler yang tidak valid: / (sam | at | () /: grup Unterminated") tetap menyelesaikan masalah ini dengan mencegah collision dengan regex?
Idan Shechter
Jawaban yang luar biasa! Senang bahwa itu menyoroti persyaratan terlepas dari di mana mereka muncul. Sangat keren. Terima kasih telah memperbarui pos. Satu pertanyaan yang saya miliki adalah tentang kelas .ui-menu-item-highlight yang Anda gunakan. Apakah ini diharapkan akan didefinisikan oleh jquery-ui atau oleh konsumen? Saya mengubah nama kelas menjadi sesuai dengan kemampuan saya sendiri dan membuat huruf tebal menjadi tebal. .jqAutocompleteMatch { font-weight: bold; }
Sam
@IdanShechter Komentar luar biasa. Beberapa logika untuk menghindari this.termregex harus digunakan sebelum melakukan pemrosesan apa pun. Lihat Escape string untuk digunakan dalam regex Javascript sebagai salah satu dari banyak jawaban untuk melakukan ini.
Sam
3

untuk cara yang lebih mudah, coba ini:

$('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)
});
  }
Harun
sumber
3

Inilah pengulangan solusi Ted de Koning. Itu termasuk :

  • Pencarian case sensitif
  • Menemukan banyak kemunculan string yang dicari
$.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);
};
Pierre
sumber
1
Saya pikir Anda sedang menciptakan kembali roda! Mengapa Anda tidak menggunakan ekspresi reguler yang lebih cepat, lebih mudah, dan lebih kompak daripada semua kode ini?
George Mavritsakis
2

Ini adalah versi yang tidak memerlukan ekspresi reguler dan cocok dengan banyak hasil dalam label.

$.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);
};
Ted de Koning
sumber
Ini mungkin solusi terbaik, tetapi string.split hanya mampu untuk pertandingan yang sensitif huruf, saya percaya.
Noel Abrahams
Apakah Anda memiliki cara untuk mencocokkan kata berdasarkan non-case-sensitive? Karena jika saya memiliki pencarian "alfa", itu tidak akan menyoroti "Alfa"
Patrick
1

Ini versi saya:

  • Menggunakan fungsi DOM alih-alih RegEx untuk memecah string / menyuntikkan tag rentang
  • Hanya pelengkapan otomatis yang ditentukan yang terpengaruh, tidak semua
  • Bekerja dengan UI versi 1.9.x
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);
};

Sorot contoh teks yang cocok

Salman A
sumber
1

Anda dapat menggunakan kode berikut:

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;
    }
});

dan logika:

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

itu menciptakan widget khusus yang dapat menggantikan _renderItemtanpa menimpa _renderItemprototipe plugin asli.

dalam contoh saya juga menggunakan fungsi render asli untuk menyederhanakan kode

itu penting jika Anda ingin menggunakan plugin di tempat yang berbeda dengan tampilan autocomplete yang berbeda dan tidak ingin merusak kode Anda.

E.Monogarov
sumber
Secara umum lebih baik menghabiskan waktu untuk menjawab pertanyaan yang lebih baru, atau yang tanpa jawaban daripada menjawab pertanyaan yang berusia 6 tahun yang sudah dijawab.
zchrykng
0

Jika Anda menggunakan plugin pihak ke-3, itu memiliki opsi sorot: http://docs.jquery.com/Plugins/Autocomplete/autocomplete#url_or_dataoptions

(lihat tab Opsi)

Brian Luft
sumber
ya saya mengetahui plug-in ini. Namun, kami menggunakan jQueryUI di aplikasi kami sehingga akan lebih baik untuk bekerja dengan plug-in jQueryUI Autocomplete
dev.e.loper
1
Pada 2010-06-23, plugin jQuery Autocomplete telah ditinggalkan karena plugin jQuery UI Autocomplete. Lihat bassistance.de/jquery-plugins/jquery-plugin-autocomplete untuk informasi lebih lanjut
shek
0

Untuk mendukung banyak nilai, cukup tambahkan fungsi berikut:

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>");
ZaieN
sumber