user1762913
user1762913

Reputation: 41

jQuery UI Autocomplete using both categories and accent folding at the same time

I'm using the jQuery UI Autocomplete widget. I want to be able to use two different functionalities at the same time - Categories and Accent folding.

I can get both working independently using the source code from the jQuery UI website (http://jqueryui.com/autocomplete/).

For the categories:

<!doctype html>

<html lang="en">
<head>
<meta charset="utf-8" />
<title>jQuery UI Autocomplete - Categories</title>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.9.0/themes/base/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.8.2.js"></script>
<script src="http://code.jquery.com/ui/1.9.0/jquery-ui.js"></script>
<link rel="stylesheet" href="/resources/demos/style.css" />
<style>
.ui-autocomplete-category {
    font-weight: bold;
    padding: .2em .4em;
    margin: .8em 0 .2em;
    line-height: 1.5;
}
</style>
<script>
$.widget( "custom.catcomplete", $.ui.autocomplete, {
    _renderMenu: function( ul, items ) {
        var that = this,
            currentCategory = "";
        $.each( items, function( index, item ) {
            if ( item.category != currentCategory ) {
                ul.append( "<li class='ui-autocomplete-category'>" + item.category + "</li>" );
                currentCategory = item.category;
            }
            that._renderItemData( ul, item );
        });
    }
});
</script>
<script>
$(function() {
    var data = [
        { label: "anders", category: "" },
        { label: "andreas", category: "" },
        { label: "antal", category: "" },
        { label: "annhhx10", category: "Products" },
        { label: "annk K12", category: "Products" },
        { label: "annttop C13", category: "Products" },
        { label: "anders andersson", category: "People" },
        { label: "andreas andersson", category: "People" },
        { label: "andreas johnson", category: "People" }
    ];

    $( "#search" ).catcomplete({
        delay: 0,
        source: data
    });
});
</script>
</head>
<body>

<label for="search">Search: </label>
<input id="search" />


</body>
</html>

and for the accent folding:

<!doctype html>

<html lang="en">
<head>
<meta charset="utf-8" />
<title>jQuery UI Autocomplete - Accent folding</title>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.9.0/themes/base/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.8.2.js"></script>
<script src="http://code.jquery.com/ui/1.9.0/jquery-ui.js"></script>
<link rel="stylesheet" href="/resources/demos/style.css" />
<script>
$(function() {
    var names = [ "Jörn Zaefferer", "Scott González", "John Resig" ];

    var accentMap = {
        "á": "a",
        "ö": "o"
    };
    var normalize = function( term ) {
        var ret = "";
        for ( var i = 0; i < term.length; i++ ) {
            ret += accentMap[ term.charAt(i) ] || term.charAt(i);
        }
        return ret;
    };

    $( "#developer" ).autocomplete({
        source: function( request, response ) {
            var matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" );
            response( $.grep( names, function( value ) {
                value = value.label || value.value || value;
                return matcher.test( value ) || matcher.test( normalize( value ) );
            }) );
        }
    });
});
</script>
</head>
<body>

<div class="ui-widget">
<form>
<label for="developer">Developer: </label>
<input id="developer" />
</form>
</div>


</body>
</html>

I thought I would be able to replace the 'source' in the categories example (which is source: data) with the 'source' in the accent folding example (which is source: function( request, response )......) but this doesn't seem to work.

So, how can I combine the functionality of the categories and accent-folding into one autocomplete?

Thanks.

Upvotes: 4

Views: 3719

Answers (1)

Lukas Winzenried
Lukas Winzenried

Reputation: 1919

I prefer to integrate the accent folding logic into the filter and not, as in the jquery exsample, to manipulate the source items. this way you can use all features including grouping categories, search term highlighting ....

Step 1: Extend $.ui.autocomplete with accent insensitive (*AI) regex escaping and filter

$.extend($.ui.autocomplete, {
    escapeRegexAI: function (value) {
        return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&")
            .replace("a", "[a|ä|à|â]")
            .replace("c", "[c|ç]")
            .replace("e", "[e|é|è|ê|ë]")
            .replace("i", "[i|î|ï]")
            .replace("o", "[o|ö|ô]")
            .replace("u", "[u|ü|ù|û]")
            .replace("y", "[y|ÿ]");
    },
    filterAI: function (array, term) {
        var matcher = new RegExp($.ui.autocomplete.escapeRegexAI(term), "i");
        return $.grep(array, function (value) {
            return matcher.test(value.label || value.value || value);
        });
    }
});

Step 2: Call autocomplete with accent insensitive filter

$( "#developer" ).autocomplete({
    source: function( request, response ) {
        response($.ui.autocomplete.filterAI(data, request.term));
    }
});

Upvotes: 2

Related Questions