From 22ac0fd670d56bb88753c49b52031050181a0b98 Mon Sep 17 00:00:00 2001 From: Cedric Gatay Date: Mon, 20 Jun 2011 02:47:35 -0700 Subject: [PATCH] Added hability to ignore accent while highlighting --- jquery.highlight.js | 140 +++++++++++++++++++++++++++++++------------- 1 file changed, 100 insertions(+), 40 deletions(-) diff --git a/jquery.highlight.js b/jquery.highlight.js index 9dcf3c7..bda1441 100644 --- a/jquery.highlight.js +++ b/jquery.highlight.js @@ -4,11 +4,16 @@ * Based on highlight v3 by Johann Burkard * http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html * + * Highlighting with accents ignoring based on + * http://stackoverflow.com/questions/6092516/highlight-accented-characters, + * implemented in node and highlight term by Cedric Gatay + * * Code a little bit refactored and cleaned (in my humble opinion). * Most important changes: * - has an option to highlight only entire words (wordsOnly - false by default), - * - has an option to be case sensitive (caseSensitive - false by default) - * - highlight element tag and class names can be specified in options + * - has an option to be case sensitive (caseSensitive - false by default), + * - highlight element tag and class names can be specified in options, + * - has an option to ignore accents in words (ignoreAccents - true by default) * * Usage: * // wrap every occurrance of text 'lorem' in content @@ -36,6 +41,9 @@ * // remove custom highlight * $('#content').unhighlight({ element: 'em', className: 'important' }); * + * //disable accents ignore (cafe will not highlight café) + * $('#content').highlight("cafe", {ignoreAccents : false}); + * * * Copyright (c) 2009 Bartek Szopka * @@ -44,65 +52,117 @@ */ jQuery.extend({ - highlight: function (node, re, nodeName, className) { - if (node.nodeType === 3) { - var match = node.data.match(re); - if (match) { - var highlight = document.createElement(nodeName || 'span'); - highlight.className = className || 'highlight'; - var wordNode = node.splitText(match.index); - wordNode.splitText(match[0].length); - var wordClone = wordNode.cloneNode(true); - highlight.appendChild(wordClone); - wordNode.parentNode.replaceChild(highlight, wordNode); - return 1; //skip added node in parent - } - } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children - !/(script|style)/i.test(node.tagName) && // ignore script and style nodes - !(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted - for (var i = 0; i < node.childNodes.length; i++) { - i += jQuery.highlight(node.childNodes[i], re, nodeName, className); - } - } - return 0; - } -}); + highlight: function (node, re, nodeName, className, ignoreAccents) { + if (node.nodeType === 3) { + + var nodeData = node.data; + if (ignoreAccents) { + nodeData = jQuery.removeDiacratics(nodeData); + } + var match = nodeData.match(re); + if (match) { + var highlight = document.createElement(nodeName || 'span'); + highlight.className = className || 'highlight'; + var wordNode = node.splitText(match.index); + wordNode.splitText(match[0].length); + var wordClone = wordNode.cloneNode(true); + highlight.appendChild(wordClone); + wordNode.parentNode.replaceChild(highlight, wordNode); + return 1; //skip added node in parent + } + } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children + !/(script|style)/i.test(node.tagName) && // ignore script and style nodes + !(node.tagName === nodeName.toUpperCase() && + node.className === className)) { // skip if already highlighted + for (var i = 0; i < node.childNodes.length; i++) { + i += jQuery.highlight(node.childNodes[i], re, nodeName, className, ignoreAccents); + } + } + return 0; + }, + + removeDiacratics : function(str) { + var rExps = [ + {re:/[\xC0-\xC6]/g, ch:'A'}, + {re:/[\xE0-\xE6]/g, ch:'a'}, + {re:/[\xC8-\xCB]/g, ch:'E'}, + {re:/[\xE8-\xEB]/g, ch:'e'}, + {re:/[\xCC-\xCF]/g, ch:'I'}, + {re:/[\xEC-\xEF]/g, ch:'i'}, + {re:/[\xD2-\xD6]/g, ch:'O'}, + {re:/[\xF2-\xF6]/g, ch:'o'}, + {re:/[\xD9-\xDC]/g, ch:'U'}, + {re:/[\xF9-\xFC]/g, ch:'u'}, + {re:/[\xD1]/g, ch:'N'}, + {re:/[\xF1]/g, ch:'n'} + ]; + for (var i = 0, len = rExps.length; i < len; i++) { + str = str.replace(rExps[i].re, rExps[i].ch); + } + return str; + } + + }); jQuery.fn.unhighlight = function (options) { var settings = { className: 'highlight', element: 'span' }; jQuery.extend(settings, options); - return this.find(settings.element + "." + settings.className).each(function () { - var parent = this.parentNode; - parent.replaceChild(this.firstChild, this); - parent.normalize(); - }).end(); + return this.find(settings.element + "." + settings.className).each( + function () { + var parent = this.parentNode; + parent.replaceChild(this.firstChild, this); + parent.normalize(); + }).end(); }; jQuery.fn.highlight = function (words, options) { - var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false }; + var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false, ignoreAccents : true }; jQuery.extend(settings, options); - + if (words.constructor === String) { words = [words]; } - words = jQuery.grep(words, function(word, i){ - return word != ''; + words = jQuery.grep(words, function(word, i) { + return word != ''; }); words = jQuery.map(words, function(word, i) { - return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); }); - if (words.length == 0) { return this; }; + if (words.length == 0) { + return this; + } + var flag = settings.caseSensitive ? "" : "i"; var pattern = "(" + words.join("|") + ")"; if (settings.wordsOnly) { pattern = "\\b" + pattern + "\\b"; } - var re = new RegExp(pattern, flag); - + + var re = []; + re.push(new RegExp(pattern, flag)); + + if (settings.ignoreAccents) { + var wordsNoAccents = jQuery.map(words, function(word, i) { + return jQuery.removeDiacratics(word); + }); + var patternNoAccents; + if (settings.wordsOnly) { + // workaround for word separation using \\b + patternNoAccents = "( " + wordsNoAccents.join("|") + " )"; + patternNoAccents = "\\b" + patternNoAccents + "\\b"; + } else { + patternNoAccents = "(" + wordsNoAccents.join("|") + ")"; + } + if (patternNoAccents!=pattern) { + re.push(new RegExp(patternNoAccents, flag)); + } + } + return this.each(function () { - jQuery.highlight(this, re, settings.element, settings.className); + for (var i in re) { + jQuery.highlight(this, re[i], settings.element, settings.className, settings.ignoreAccents); + } }); }; -