繁体   English   中英

当用户在文本输入字段中输入过滤器文本时,jquery过滤器脚本不会忽略变音符号并且不突出显示字符串匹配项

[英]jquery filter script not ignoring diacritics and not highlighting string matches as user enters filter text into text input field

我在同一个html页面上有多个词汇表。

在每个词汇表上方,我希望用户可以在文本输入字段中键入单词或短语,以仅查看包含键入的字符串(单词或短语)的表行。 例如,如果在文本输入字段中键入“ good”,则不包含字符串“ good”的表行将消失。 如果您访问http://www.amanado.com/idioma-colombiano/ ,单击“ Vocabulario(oficial y de jerga)-palabras y frases comunes”以展开手风琴部分,然后键入“ good “文本输入字段”下方的“ Ingresa palabra o frase en el siguiente campo para filtrar lainformationaciónde la tabla”一词。 在文本输入字段中输入“ good”后,词汇表中除7行外的所有行都应消失(剩余7行)。

我遇到以下3个问题:

1)我无法忽略重音符号(例如é,ñ,ü),就像案件已经被成功忽略一样。 例如,如果用户在输入字段中输入“ que”,则包含“ que”和“qué”的行不应消失。 但是,当您键入“ que”时,包含“qué”的行会错误地消失。 如您所见,如果在输入字段(不包括引号)中键入“ que”,则将保留2条包含“ que”的记录。 并且,如果您在输入字段(不包括引号)中键入或粘贴“ que”,则将保留6条包含“qué”的记录。

2)我试图使用版本的jquery.highlight.js突出显示保留/不消失的行中的字符串匹配。 有关此外观的示例,请在此问题摘要的第二段中指示的输入字段中键入“ que”,然后您会看到字符串“ que”在保持/不消失的2行中突出显示。 请注意,这无法正常工作,因为我通过插入脚本“ $(” table td“)。highlight(” que“);”对“ que”高亮进行了硬编码。 为了证明(a)jquery.highlight.js是活动的/正在运行的,并且(b)提供了一个视觉示例来说明突出显示的文本是如何显示的,将其放入html页面的“ head”部分。

3)除了使用户能够在字段中输入单词或短语以仅查看包含所输入单词或短语的表格行的javascript之外,javascript不能成功忽略重音(例如é,ñ,ü),这是所需要的行为,jquery.highlight.js脚本也无法成功忽略重音符号(例如é,ñ,ü)。 例如,在此问题摘要的第二段中指示的输入字段中输入“ pues”,您将在保留/不消失的行中多次出现未成功突出显示字符串“Qué”和“qué”的情况。 记住,我通过插入脚本“ $(” table td“)。highlight(” que“);”对“ que”突出显示进行了硬编码。 进入html页面的部分,因此字符串“ que”,“qué”,“ Que”和“Qué”都应在表行中突出显示,如果任何字符串“ que”,“如果打算(a)区分大小写和(b)重音(例如é,ñ,ü),则将qué”,“ Que”或“Qué”输入到输入字段中。 有趣的是,我正在使用的jquery.highlight.js版本包含“ ignoreAccents”的功能。

以下是:

(a)输入在我的html中的输入字段;

(b)我用于使用户能够在字段中输入单词或短语以仅查看包含输入的单词或短语的表行的javascript(为简洁起见,在下文中称为“过滤javascript” );

(c)我用来突出显示文本的jquery.highlight.js javascript版本。

请注意:我不是软件工程师,但是如果有人告诉我要具体做什么,我确实会知道如何实施更改(例如,进行此精确更改,然后进行此精确更改,然后进行此精确更改)。 我感谢任何人都可以提供的任何帮助,尤其感谢字面说明。 而且,我总是希望使用最少的代码(例如javascript,css,html)来获得最多的代码。

其他注释/注意事项包含在此问题摘要的底部。

(a)输入字段从此处开始

<form class="live-search" action="" method="post">
<p>Ingresa palabra o frase en el siguiente campo para filtrar la información de la tabla</p>
<input class="input-text-tr" type="text" value="Mostrar sólo filas que contengan..." />
<span class="filter-count-tr"></span>
</form>

(a)输入栏到此结束

(b)过滤javascript从这里开始

$(function() {
$(".input-text-tr").on('keyup', function(e) {
var disallow = [37, 38, 39, 40];//ignore arrow keys    
if($.inArray(e.which, disallow) > -1) {
return true;
}
var inputField = this,
val = this.value,
pattern = new RegExp(val, "i"),
$group = $(this).closest(".group"),
$trs = $group.find(".myTable tbody tr"),
$s;
if(val === '') {
$s = $trs;
}
else {
$s = $();
$trs.stop(true,true).each(function(i, tr) {
if(val !== inputField.value) {//if user has made another     keystroke
return false;//break out of .each() and     hence out of the     event handler
}
$tr = $(tr);
if ($tr.text().match(pattern)) {
$s = $s.add(tr);
}
});
//$trs.not($s).fadeOut();
$trs.not($s).hide();
}
$group.find(".filter-count-tr").text("(" + $s.show        ().length + ")");
}).on('focus blur', function() {
if (this.defaultValue == this.value) this.value = '';
else if (this.value == '') this.value = this.defaultValue;
});

$(".group").each(function() {
$this = $(this);
$this.find(".filter-count-tr").text("(" + $this.find("tbody     tr").length + ")");
});
});

(b)过滤javascript到此结束

(c)jquery.highlight.js javascript从这里开始

jQuery.extend({
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();
};

jQuery.fn.highlight = function (words, options) {
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.map(words, function(word, i) {
return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
});
if (words.length == 0) {
return this;
}

var flag = settings.caseSensitive ? "" : "i";
var pattern = "(" + words.join("|") + ")";
if (settings.wordsOnly) {
pattern = "\\b" + pattern + "\\b";
}

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 () {
for (var i in re) {
jQuery.highlight(this, re[i], settings.element,     settings.className, settings.ignoreAccents);
}
});
};

(c)jquery.highlight.js javascript到此结束

其他说明/注意事项从这里开始

1)我的目的是增强(而不是偏离)我已经在使用的javascript,以使用户能够在字段中输入单词或短语以仅查看包含输入的单词或短语的表行,因为我已经在使用javascript除上述问题外,using的工作方式是有效的(感谢Beetroot对我之前发表的问题的出色贡献)。

2) javascript,我发现要实现的功能涉及以下4个示例(请注意,因为stackoverflow不允许我在一个问题中使用多个链接,所以我将“ http://”替换为在以下示例中为“ [http://这里]”:

a) [http://此处] demopill.com/jquery-onpage-text-highlighter-and-filter.html [最接近我尝试实现的功能; 当用户在输入字段中输入文本时,似乎已成功过滤并突出显示; 成功忽略大小写,但没有成功忽略重音符号(例如é,ñ,ü)];

b) [http://此处] stackoverflow.com/search?q=jquery.highlight.js(关于stackoverflow的对话:忽略重音字符)

c) [http://此处] www.jquery.info/The-plugin-SearchHighlight(包括突出显示功能);

d) [http:// here] docs.jquery.com/UI/Effects/Highlight(包括突出显示功能;请注意,我已经在此问题摘要第2段引用的网站上使用“ jquery ui”)。

其他说明/注意事项在这里结束

突出显示

jquery.highlight.js安装了jquery.highlight.js ...

变化:

$group.find(".filter-count-tr").text("(" + $s.show().length + ")");

至 :

$group.find(".filter-count-tr").text("(" + $s.show().unhighlight().highlight(val).length + ")");

但是,下面的重音不敏感代码对此进行了修改。

口音不敏感

这似乎几乎是不可能的,但是我在发现这一点上取得了突破,这表明可以如何修改hightlight插件以提供对重音不敏感的突出显示。

为了更好地理解代码,我将其重构为更好的插件(无论如何对我来说都是更好的)。 现在,它不将任何成员放入jQuery命名空间(以前是一个),而将一个成员放入jQuery.fn (以前是两个)。 使用新的插件,可以按照以下步骤设置和取消设置突出显示:

$(selector).highlight('set', words, options);
$(selector).highlight('unset', options);

该代码提供了解释和更多示例(请参见下文)。

“设置”设置包括“ .accentInsensitive”选项,该选项可对有限数量的硬编码(西班牙语)重音字符组进行操作(我很遗憾),实现的效率与我使用插件中的私有成员来管理缓存一样有效可重用的RegExps和替换字符串,以供以后通过'set'方法使用。 拥有通用的“ Unicode规范化”解决方案会好得多,但这又是另一回事了。

新插件还提供了机会,可以将代码的一部分作为单独的方法.makepattern ,其优势在于,可以在插件外部使用RegExp-ready模式,并可以重新注入它们。 此功能使我们可以将插件用作实现另一个目标的资源-即不区分重音的过滤-可以绝对确定使用的RegExp模式(用于突出显示和过滤)是相同的。

这是插件代码:

/*
 * jQuery highlightIt plugin
 * by Beetroot-Beetroot
 * https://stackoverflow.com/users/1142252/beetroot-beetroot
 *
 * based on Highlight by Bartek Szopka, 2009
 * http://bartaz.github.com/sandbox.js/jquery.highlight.html,
 * based on highlight v3 by Johann Burkard
 * http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
 *
 * Most important changes:
 * - Code refactored into jQuery preferred plugin pattern.
 * - Now called with : 
 *    - $(slector).highlight('set', words, options); previously $(slector).highlight(words, options);
 *    - $(slector).highlight('unset', options); previously $(slector).unhighlight(options);
 *    - $().highlight('makePattern', words, options); This new option returns a RegExp-ready pattern that can be used externally and/or re-injected for reuse (see .isPattern option below), thus avoiding remaking the pattern as might otherwise happen.
 *  - 'set' .isPattern option; When true, this new option indicates that the 'words' parameter is a prepared RegExp-ready pattern.
 *  - 'set' .accentInsensitive option; This new option is limited to operating on hard-coded character groups (eg, Spanish accented chars), not Unicode normalized (which would be a better approach but much harder to achieve and probably slower).
 *
 * Usage:
 *   // wrap every occurrance of text 'lorem' in content
 *   // with <span class='highlight'> (default options)
 *   $('#content').highlight('set', 'lorem');
 *
 *   // search for and highlight more terms at once
 *   // so you can save some time on traversing DOM
 *   $('#content').highlight(['set', 'lorem', 'ipsum']);
 *   $('#content').highlight('set', 'lorem ipsum');
 *
 *   // search only for entire word 'lorem'
 *   $('#content').highlight('set', 'lorem', { wordsOnly: true });
 *
 *   // don't ignore case during search of term 'lorem'
 *   $('#content').highlight('set', 'lorem', { caseSensitive: true });
 *
 *   // wrap every occurrance of term 'ipsum' in content
 *   // with <em class='important'>
 *   $('#content').highlight('set', 'ipsum', { element: 'em', className: 'important' });
 *
 *   // remove default highlight
 *   $('#content').highlight('unset');
 *
 *   // remove custom highlight
 *   $('#content').highlight('unset', { element: 'em', className: 'important' });
 *
 *   // get accent-insensitive pattern
 *   $().highlight('makePattern', { element: 'lorem', {'accentInsensitive':true});
 *
 *
 * Copyright (c) 2009 Bartek Szopka
 *
 * Licensed under MIT license.
 *
 */

(function($) {
    // **********************************
    // ***** Start: Private Members *****
    var pluginName = 'highlight';
    var accentedForms = [//Spanish accednted chars
        //Prototype ...
        //['(c|ç)', '[cç]', '[CÇ]', new RegExp('(c|ç)','g'), new RegExp('(C|Ç)','g')],
        ['(a|á)', '[aá]'],
        ['(e|é)', '[eé]'],
        ['(i|í)', '[ií]'],
        ['(n|ñ)', '[nñ]'],
        ['(o|ó)', '[oó]'],
        ['(u|ú|ü)', '[uúü]']
    ];
    //To save a lot of hard-coding and a lot of unnecessary repetition every time the "set" method is called, each row of accentedForms is now converted to the format of the prototype row, thus providing reusable RegExps and corresponding replacement strings.
    //Note that case-sensitivity is established later in the 'set' settings so we prepare separate RegExps for upper and lower case here.
    $.each(accentedForms, function(i, af) {
        af[2] = af[1].toUpperCase();
        af[3] = new RegExp(af[0], 'g');
        af[4] = new RegExp(af[0].toUpperCase(), 'g');
    });
    var h = function(node, re, settings) {
        if (node.nodeType === 3) {//text node
            var match = node.data.match(re);
            if (match) {
                var wordNode = node.splitText(match.index);
                wordNode.splitText(match[0].length);
                $(wordNode).wrap($("<" + settings.element + ">").addClass(settings.className));
                return 1;
           }
        } 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 === settings.element.toUpperCase() && node.className === settings.className)) { // skip if already highlighted
            for (var i = 0; i < node.childNodes.length; i++) {
                i += h(node.childNodes[i], re, settings);
            }
        }
        return 0;
    };
    // ***** Fin: Private Members *****
    // ********************************

    // *********************************
    // ***** Start: Public Methods *****
    var methods = {
        //This is a utility method. It returns a string, not jQuery.
        makePattern: function (words, options) {
            var settings = {
                'accentInsensitive': false
            };
            $.extend(settings, options || {});
            if (words.constructor === String) {
                words = [words];
            }
            words = $.grep(words, function(word, i) {
              return word != '';
            });
            words = $.map(words, function(word, i) {
              return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
            });
            if (words.length == 0) { return ''; };
            var pattern = "(" + words.join("|") + ")";
            if (settings.accentInsensitive) {
                $.each(accentedForms, function(i, af) {
                    pattern = pattern.replace(af[3], af[1]).replace(af[4], af[2]);
                });
            }
            return pattern;
        },
        set: function (words, options) {
            var settings = {
                'className': 'highlight',
                'element': 'span',
                'caseSensitive': false,
                'wordsOnly': false,
                'accentInsensitive': false,
                'isPattern': false
            };
            $.extend(settings, options || {});

            var pattern = settings.isPattern ? words : methods.makePattern(words, settings);
            if (pattern === '') { return this; };
            if (settings.wordsOnly) {
                pattern = "\\b" + pattern + "\\b";
            }
            var flag = settings.caseSensitive ? "" : "i";
            var re = new RegExp(pattern, flag);
            return this.each(function () {
                h(this, re, settings);
            });
        },
        unset: function (options) {
            var settings = {
                className: 'highlight',
                element: 'span'
            }, parent;
            $.extend(settings, options || {});
            return this.find(settings.element + "." + settings.className).each(function () {
                parent = this.parentNode;
                parent.replaceChild(this.firstChild, this);
                parent.normalize();
            }).end();
        }
    };
    // ***** Fin: Public Methods *****
    // *******************************

    // *****************************
    // ***** Start: Supervisor *****
    $.fn[pluginName] = function( method ) {
        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || !method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' + method + ' does not exist in jQuery.' + pluginName );
        }
    };
    // ***** Fin: Supervisor *****
    // ***************************
})( jQuery );

这是语言站点的应用程序代码:

$(function() {
    $(".text-input").on('keyup', function(e) {
        var disallow = [37, 38, 39, 40];//ignore arrow keys
        if($.inArray(e.which, disallow) > -1) {
            return true;
        }
        var $group = $(this).closest(".group"),
            accent_sensitive = false,
            case_sensitive = false,
            val = this.value,
            pattern = $().highlight('makePattern', val, {
                'accentInsensitive': !accent_sensitive,
                'caseSensitive': case_sensitive
            }),
            $trs = $group.find(".myTable tbody tr"),
            $s;
        if(val === '') {
            $s = $trs;
        }
        else {
            $s = $();
            $trs.stop(true,true).each(function(i, tr) {
                $tr = $(tr);
                //if ($tr.text().match(new RegExp(pattern, "i"))) {
                if ($tr.text().match(new RegExp(pattern, case_sensitive ? '' : "i"))) {
                    $s = $s.add(tr);
                }
            });
            $trs.not($s).hide();
        }
        $group.find(".filter-count-tr").text("(" + $s.show().highlight('unset').highlight('set', pattern, {
            'isPattern':true,
            'caseSensitive':case_sensitive
        }).length + ")");
    }).on('focus blur', function() {
        if (this.defaultValue == this.value) this.value = '';
        else if (this.value == '') this.value = this.defaultValue;
    });

    $(".group").each(function() {
        $this = $(this);
        $this.find(".filter-count-tr").text("(" + $this.find("tbody tr").length + ")");
    });
});

所有测试,因此,如果正确地安装应该运作。

顺便说一句,我使用此页面作为西班牙语口音字符的来源。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM