Skip to content

Instantly share code, notes, and snippets.

@juannorris
Last active November 17, 2016 15:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save juannorris/fa32fb015acd1496c6dfd55b5359a1f9 to your computer and use it in GitHub Desktop.
Save juannorris/fa32fb015acd1496c6dfd55b5359a1f9 to your computer and use it in GitHub Desktop.
Highlight filter with accent support (ui-select).
/**
* Highlights text that matches given query for ui-select directive.
*
* It matches accents and uppercase/lowercase (with support from `normalize` function).
*/
function customHighlight() {
function escapeRegexp(queryToEscape) {
return ('' + queryToEscape).replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
}
return function (matchItem, query) {
if (!matchItem || !query) {
return matchItem;
}
// Get the normalized and escaped version of the search query
query = escapeRegexp(normalize(query));
var startIndex,
endIndex,
toBeReplaced,
highlightedItem = '';
// Find and replace all occurrences of query inside matchItem, while preserving case and accents
while (matchItem.length) {
startIndex = normalize(matchItem).indexOf(query);
if (startIndex !== -1) {
endIndex = startIndex + query.length;
toBeReplaced = matchItem.substring(startIndex, endIndex);
highlightedItem += matchItem.substring(0, startIndex) +
'<span class="ui-select-highlight">' + toBeReplaced + '</span>';
matchItem = matchItem.substring(endIndex, matchItem.length);
} else {
// Add the rest of the string
highlightedItem += matchItem;
matchItem = '';
}
}
return highlightedItem;
};
}
@juannorris
Copy link
Author

juannorris commented Oct 26, 2016

Based on ui-select's highlight filter.

The filter depends on a normalize function (probably not the best name), that takes a string and returns its lowercase non-accented version, see: http://stackoverflow.com/questions/990904/javascript-remove-accents-diacritics-in-strings

normalize('Soporte Académico')
"soporte academico"

I guess the filter should be able to support any other special characters, by updating the normalize function accordingly.

In my case, I just needed Spanish and Portuguese accents support, so here is how normalize code looks like:

        // Portuguese and Spanish accent map
        var accentMap = {
            // acute accent
            'á':'a', 'é':'e', 'í':'i','ó':'o','ú':'u', 'Á':'A', 'É':'E', 'Í':'I','Ó':'O','Ú':'U',
            // ¨
            'Ä': 'a', 'ä': 'a', 'Ë': 'e', 'ë': 'e', 'Ï': 'i', 'ï': 'i', 'Ö': 'o', 'ö': 'o', 'Ü': 'u', 'ü': 'u',
            // circumflex accent
            'â': 'a', 'ê': 'e', 'ô': 'o', 'Â': 'A', 'Ê': 'E', 'Ô': 'O',
            // tilde
            'ã': 'a', 'õ': 'o', 'Ã': 'A', 'Õ': 'O',
            // grave accent
            'à': 'a', 'À': 'A',
            // cedilha
            'Ç': 'c', 'ç': 'c'
        };

        /**
         * Removes accents from the given string.
         * @param s
         * @returns {string}
         */
        function accentFold(s) {
            if (!s) {
                return '';
            }

            var ret = '',
                char;

            for (var i = 0; i < s.length; i++) {
                char = s.charAt(i);
                ret += accentMap[char] || char;
            }

            return ret;
        }

        /**
         * Returns a lowercase version of the string, without accents.
         * @param s
         * @returns {string}
         */
        function normalize(s) {
            if (!s) {
                return '';
            }

            return accentFold(s).toLowerCase();
        }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment