JavaScript Typeahead Autocomplete match accents an

2019-05-22 18:02发布

问题:

I'm using Typeahead jQuery library, but when a user types a vocal like e it should match foreign vocals too, like é, ë, è.

Match n with ñ too.

This is my code:

<html>
<head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="typeahead.css">
    <script src="jquery-1.11.0.min.js"></script>
    <script src="typeahead.bundle.min.js"></script>
</head>
<body>
    <center>
        <div id="nombre">
            <input class="typeahead" type="text" placeholder="Nombre">
        </div>
    </center>
    <script>
        var charMap = {
            "à": "a", 
            "á": "a", 
            "ä": "a", 
            "è": "e", 
            "é": "e", 
            "ë": "e", 
            "ì": "i", 
            "í": "i",
            "ï": "i",
            "ò": "o",
            "ó": "o",
            "ö": "o",
            "ù": "u",
            "ú": "u",
            "ü": "u",
            "ñ": "n"};
        var normalize = function (input) {
            $.each(charMap, function (unnormalizedChar, normalizedChar) {
                var regex = new RegExp(unnormalizedChar, 'gi');
                input = input.replace(regex, normalizedChar);
            });
            return input;
        }
        var substringMatcher = function(strs) {
        return function findMatches(q, cb) {
            var matches, substringRegex;
            matches = [];
            substrRegex = new RegExp(q, "i");
            $.each(strs, function(i, str) {
              if (substrRegex.test(str)) {
                matches.push({ value: str });
              }
            });
            cb(matches);
          };
        };
        var nombres = ["Sánchez", "Árbol", "Müller", "Ératio", "Niño"];
        $("#nombre .typeahead").typeahead({
          hint: true,
          highlight: true,
          minLength: 1
        },
        {
          name: "nombres",
          displayKey: "value",
          source: substringMatcher(nombres)
        });
    </script>
</body>

How can I achieve this?

Thanks!

回答1:

I've written a solution in the jsFiddle below:

http://jsfiddle.net/Fresh/F3hG9/

The key part of the solution is to normalize the name used for searching and to also include the original name which will be used for display purposes; you can see this in the definition of "local" below:

var nombres = new Bloodhound({
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
    queryTokenizer: queryTokenizer,
    local: $.map(names, function (name) {
        // Normalize the name - use this for searching
        var normalized = normalize(name);
        return {
            value: normalized,
            // Include the original name - use this for display purposes
            displayValue: name
        };
    })
});

It is the normailze function (shown below) which replaces with "foreign" characters with Western alternatives:

var normalize = function (input) {
    $.each(charMap, function (unnormalizedChar, normalizedChar) {
        var regex = new RegExp(unnormalizedChar, 'gi');
        input = input.replace(regex, normalizedChar);
    });
    return input;
};

I have omitted charMap (which determines what western character the foreign character maps to) for brevity; you can find the list in the Fiddle.