Wie kann ich die Ergebnisse des Autocomplete-Plug-Ins individuell formatieren?


Antworten:


233

Autocomplete mit Live-Vorschlag

Ja, Sie können, wenn Sie Affen-Patch automatisch vervollständigen.

In dem in v1.8rc3 der jQuery-Benutzeroberfläche enthaltenen Widget für die automatische Vervollständigung wird das Popup mit Vorschlägen in der Funktion _renderMenu des Widgets für die automatische Vervollständigung erstellt. Diese Funktion ist wie folgt definiert:

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

Die Funktion _renderItem ist wie folgt definiert:

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

Sie müssen also das _renderItem fn durch Ihre eigene Kreation ersetzen, die den gewünschten Effekt erzeugt. Diese Technik, die eine interne Funktion in einer Bibliothek neu definiert, wird als Affen-Patching bezeichnet . So habe ich es gemacht:

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

Rufen Sie diese Funktion einmal auf $(document).ready(...).

Nun, das ist ein Hack, weil:

  • Für jedes in der Liste gerenderte Element wird ein reguläres Ausdrucksobjekt erstellt. Dieses reguläre Ausdrucksobjekt sollte für alle Elemente wiederverwendet werden.

  • Für die Formatierung des fertigen Teils wird keine CSS-Klasse verwendet. Es ist ein Inline-Stil.
    Das heißt, wenn Sie mehrere Autovervollständigungen auf derselben Seite hätten, würden alle die gleiche Behandlung erhalten. Ein CSS-Stil würde das lösen.

... aber es veranschaulicht die Haupttechnik und funktioniert für Ihre Grundanforderungen.

Alt-Text

aktualisiertes Arbeitsbeispiel: http://output.jsbin.com/qixaxinuhe


Verwenden Sie diese Zeile, um die Groß- und Kleinschreibung der Übereinstimmungszeichenfolgen beizubehalten, anstatt die Groß- und Kleinschreibung der eingegebenen Zeichen zu verwenden:

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

Mit anderen Worten, von dem ursprünglichen Startcode oben, müssen Sie nur zu ersetzen , this.termmit "$&".


BEARBEITEN
Das Obige ändert jedes Autocomplete-Widget auf der Seite. Wenn Sie nur eine ändern möchten, lesen Sie die folgende Frage:
Wie kann * nur eine * Instanz von Autocomplete auf einer Seite gepatcht werden?


Danke Cheeso. Hast du einen jsbin Link dafür?
dev.e.loper

1
Beachten Sie, dass es wichtig ist, den Kontext zurückzusetzen, wenn Sie Dinge verketten: oldFn.apply (this, [ul, item]);
Emanaton

Vielen Dank! Wäre großartig, wenn dies Teil der jQuery-Benutzeroberfläche würde.
David Ryder

4
Eine Sache, die ich sagen würde, ist, wenn Sie möchten, dass das Ergebnis in einem beliebigen Teil der übereinstimmenden Zeichenfolge (nicht nur am Anfang) fett gedruckt wird, ändern Sie die RegExp-Zeile folgendermaßen: var re = new RegExp (this.term);
David Ryder

1
Die automatische Vervollständigung von JQueryUI führt standardmäßig eine Suche ohne Berücksichtigung der Groß- und Kleinschreibung durch. Daher ist es sinnvoll, das Flag "i" im RegExp-Objekt hinzuzufügen. Es gibt auch keinen Grund, das "^" in der Regex zu verwenden, wie @DavidRyder erwähnt. Gefällt mir: var re = new RegExp(this.term, "i"); Toller Beitrag!
Sam

65

das funktioniert auch:

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

eine Kombination aus den Antworten von @ Jörn Zaefferer und @ Cheeso.


Ich mochte dieses besser, da es dem ganzen Wort entspricht.
atp

3
Das funktioniert gut. Das einzige, worauf Sie achten müssen, ist, dass item.label ersetzt wird. Für mich wurde ich "<stark ..." in meinem Textfeld. Durch einfaches Zuweisen des Ersetzungsergebnisses zu einer anderen Variablen wurde dies behoben. Sie hätten dieses Problem nicht, wenn Ihre Daten eine Werteigenschaft enthalten, die in das Textfeld eingefügt wird.
Kijana Woodard

Dies funktioniert nicht, wenn Sie eine automatische Vervollständigung haben, die mehrere Werte unterstützt. irgendwelche Vorschläge?
Leora

Der einfachste Weg, um Text in Ihren Ergebnissen der automatischen Vervollständigung hervorzuheben. Achten Sie offensichtlich auf die Fehler, auf die Leora und Kijana oben
hingewiesen haben

@ RNKushwaha überall, bevor Sie anrufen$().autocomplete()
Brian Leishman

8

Super hilfreich. Danke dir. +1.

Hier ist eine Light-Version, die nach "String muss mit dem Begriff beginnen" sortiert wird:

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
Dank Orolo habe ich die automatische Vervollständigung an mehreren Stellen verwendet und wollte einen zentralen Ort, an dem ich die Änderung vornehmen kann, um nur Ergebnisse anzuzeigen, die mit den eingegebenen Zeichen beginnen, und dieses ist genau das, was ich brauchte!
Dreamerkumar

Vielen Dank. Dies ist die beste Lösung von allen. Es funktioniert ohne Berücksichtigung der Groß- und Kleinschreibung.
Aniket Kulkarni

7

Hier geht es, ein funktionales vollständiges Beispiel:

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

Hoffe das hilft


6

jQueryUI 1.9.0 ändert die Funktionsweise von _renderItem.

Der folgende Code berücksichtigt diese Änderung und zeigt auch, wie ich den Highlight-Abgleich mit dem jQuery Autocomplete-Plugin von Jörn Zaefferer durchgeführt habe. Es werden alle einzelnen Begriffe im gesamten Suchbegriff hervorgehoben.

Seit ich Knockout und jqAuto verwendet habe, war es für mich viel einfacher, die Ergebnisse zu gestalten.

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

Wenn ich mit Zeichen wie '(' suche, verursacht dies einen Fehler ("Ungefangener Syntaxfehler: Ungültiger regulärer Ausdruck: / (sam | at | () /: Nicht terminierte Gruppe"), um dies zu lösen, indem eine Kollision mit Regex verhindert wird?
Idan Shechter

Super Antwort! Ich liebe es, dass es die Begriffe hervorhebt, unabhängig davon, wo sie erscheinen. Sehr cool. Vielen Dank für die Aktualisierung des Beitrags. Eine Frage, die ich hatte, betrifft die von Ihnen verwendete .ui-Menüelement-Hervorhebungsklasse. Wird dies voraussichtlich von jquery-ui oder von Verbrauchern definiert? Ich habe den Klassennamen geändert, um ihn meinen eigenen Mitteln anzupassen, und einfach die Schriftgröße fett gedruckt. .jqAutocompleteMatch { font-weight: bold; }
Sam

@IdanShechter Großartiger Kommentar. Vor this.termjeder Verarbeitung sollte eine Logik verwendet werden, um dem regulären Ausdruck zu entkommen . Siehe Escape-Zeichenfolge zur Verwendung in Javascript-Regex als eine von vielen Antworten darauf.
Sam

3

Versuchen Sie Folgendes, um es noch einfacher zu machen:

$('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

Hier ist eine Wiederholung der Lösung von Ted de Koning. Es enthält :

  • Suche ohne Berücksichtigung der Groß- und Kleinschreibung
  • Finden vieler Vorkommen der gesuchten Zeichenfolge
$.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
Ich denke, Sie erfinden das Rad neu! Warum verwenden Sie keine regulären Ausdrücke, die schneller, einfacher und kompakter sind als der gesamte Code?
George Mavritsakis

2

Hier ist eine Version, die keine regulären Ausdrücke erfordert und mit mehreren Ergebnissen in der Bezeichnung übereinstimmt.

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

Dies ist wahrscheinlich die beste Lösung, aber string.split kann meiner Meinung nach nur zwischen Groß- und Kleinschreibung unterscheiden.
Noel Abrahams

Haben Sie eine Möglichkeit, Wörter zu finden, bei denen die Groß- und Kleinschreibung nicht berücksichtigt wird? Denn wenn ich eine Suche "alfa" habe, wird "Alfa"
Patrick


1

Hier ist meine Version:

  • Verwendet DOM-Funktionen anstelle von RegEx, um Zeichenfolgen zu unterbrechen / Span-Tags einzufügen
  • Nur die angegebene automatische Vervollständigung ist betroffen, nicht alle
  • Funktioniert mit der UI-Version 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);
};

Markieren Sie das passende Textbeispiel


1

Sie können folgenden Code verwenden:

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

und Logik:

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

Es wird ein benutzerdefiniertes Widget erstellt, das überschrieben _renderItemwerden kann, ohne den _renderItemursprünglichen Plugin-Prototyp zu überschreiben .

In meinem Beispiel wurde auch die ursprüngliche Renderfunktion verwendet, um den Code zu vereinfachen

Es ist wichtig, wenn Sie das Plugin an verschiedenen Stellen mit unterschiedlicher Ansicht der automatischen Vervollständigung verwenden und Ihren Code nicht beschädigen möchten.


Im Allgemeinen ist es besser, Zeit damit zu verbringen, neuere oder nicht beantwortete Fragen zu beantworten, als eine 6 Jahre alte Frage zu beantworten, die bereits beantwortet wurde.
Zchrykng

0

Wenn Sie stattdessen das Plugin eines Drittanbieters verwenden, gibt es eine Hervorhebungsoption: http://docs.jquery.com/Plugins/Autocomplete/autocomplete#url_or_dataoptions

(siehe Registerkarte Optionen)


Ja, mir ist dieses Plug-In bekannt. Wir verwenden jedoch jQueryUI in unserer App. Es wäre also schön, wenn dies mit dem Plug-In für die
automatische Vervollständigung von

1
Ab dem 23.06.2010 ist das jQuery Autocomplete-Plugin zugunsten des jQuery UI Autocomplete-Plugins veraltet. Weitere Informationen finden Sie unter bassistance.de/jquery-plugins/jquery-plugin-autocomplete
shek

0

Um mehrere Werte zu unterstützen, fügen Sie einfach die folgende Funktion hinzu:

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>");
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.