Blog

JQuery Autocomplete labels escape HTML tags

Jonathon Horsman Nov 17 8 comments

We just upgraded JQuery UI to version 1.8.6 (from 1.8.2) and found some previously working Autocomplete code is now broken.

Specifically we had some cleverness which shows the matching text in the results in bold.

The source function of the autocomplete looks like this:

@ javascript
source: function(request, response) {
var matcher = new RegExp(request.term, “i”);
$.ajax({
url: “/suggest_contact”,
dataType: “jsonp”,
data: { search: request.term },
success: function(data) {
var results = $.map(data, function(item) {
var contact = item.contact;
return {
label: contact.name.replace(new RegExp(“(?![^&;]+;)(?!<[^<>]*)(” + $.ui.autocomplete.escapeRegex(request.term) + “)(?![^<>]*>)(?![^&;]+;)”, “gi”), “$1”),
value: contact.name,
id: contact.id
}
});
results.push({id: 0, label: "New contact: " + request.term, value: request.term});
response(results);
}
})
}
@

So the returned JSON data label gets set with the contact name. Where the text matches the search for term we wrap in a <strong> tag.

Now it seems the <strong> tag gets escaped and appears in the search results:

JQuery Autocomplete showing the escaped HTML strong tag
JQuery UI now escapes the Autocomplete results

Sure enough the code which used to render the item has been updated to use the JQuery text() method, which escapes the HTML.

So to prevent that, I replace the /_renderItem/ method on autocomplete and use the JQuery html() method instead.

Just add this code to your Javascript somewhere and your HTML tags won’t be escaped anymore in Autocomplete:

@ javascript
/* this allows us to pass in HTML tags to autocomplete. Without this they get escaped */
$[ “ui” ][ “autocomplete” ].prototype[“_renderItem”] = function( ul, item) {
return $( “

  • ” )
    .data( “item.autocomplete”, item )
    .append( $( “” ).html( item.label ) )
    .appendTo( ul );
    };
    @

    Comments //

    Matthew Marksbury

    Matthew Marksbury Jan 10

    You can also do this on-the-fly to specific autocomplete usages, rather than changing the default behavior of all autocompletes.

    $('#myTextBox').autocomplete(
    {
         minLength: 2,
         source: 'http://www.arctickiwi.com/go'
    }).data("autocomplete")._renderItem = function (ul, item)
    {
         return $j("<li></li>")
              .data("item.autocomplete", item)
              .append($j("<a></a>").html(item.label))
              .appendTo(ul);
    };

    Jen

    Jen Mar 03

    Or, you can do the replace in the 'open' event of the jquery autocomplete:
    http://wp.me/pBHhc-eY

    Marlou

    Marlou Jun 15

    thanks for sharing your solution!!! Your solution even works with more than one autocomplete on the page whereas the solution Matthew Marksbury posted only works for the first autocomplete

    Stanley Kwok

    Stanley Kwok Jul 05

    Thanks! It works beautifully!

    Nick Olsen

    Nick Olsen Aug 19

    Thanks! It worked fantastically.

    Rafael

    Rafael Sep 08

    Thanks so much, works like a charm!

    Kiran

    Kiran Oct 31

    Thanks a lot Jonathon. This is the perfect solution to my problem. I want this behavior in all of my suggest boxes.

    Dario

    Dario Nov 13

    This works... but the HTML tags I was trying to un-escape are anchor/hyperlinks. I would like to make some results clickable in the suggest list. However the way it is now, when you click a link, you just get the HTML populating the text field. Any ideas?

    Post a comment

    1. optional

    Recent Tweets

    Blog: The monumental Myspace cock-up: http://bit.ly/emgRKV
    Tweeted on Friday at 09:43

    Awww railsapi, delete some logs: http://bit.ly/htBNDH
    Tweeted on Wednesday at 16:15