Совпадение всего слова с jQuery и содержит () - PullRequest
0 голосов
/ 12 ноября 2018

Я пишу сценарий Greasemonkey, чтобы выборочно скрывать элементы, содержащие неприятные вещи (персональное веб-средство для очистки, если хотите).

Вот что я получил до сих пор:

//custom contains function which is case-insensitive
$.extend($.expr[":"], {
  "containsNC": function(elem, i, match, array) {
    return (elem.textContent || elem.innerText || "").toLowerCase().indexOf((match[3] || "").toLowerCase()) >= 0;
  }
});

//build array of words to filter
var nope = "long list of horrible words".toLowerCase().split(' ');

//start with an empty jQuery object
var nopeEles = $();

//add elements to filter to it
for (var i = 0; i < nope.length; i++) {
  nopeEles = nopeEles.add( $("a:containsNC('" + nope[i] + "')") );
  nopeEles = nopeEles.add( $("p:containsNC('" + nope[i] + "')") );
}

//hide all applicable elements
nopeEles.css("background-color", "white");
nopeEles.css("color", "white");

Работает прилично, но выполняет частичное сопоставление слов, из-за чего короткие слова не работают.Я хочу отфильтровать элементы, содержащие такие слова, как «die» и «gun», без фильтрации таких слов, как «candied» или «gung-ho».

Чтобы было ясно, я после целого слова,не точный текст.Я хочу, чтобы «пистолет» в списке совпадал не только с «пистолетом», но и с «он выстрелил из пистолета» и «пистолет выстрелил».И не «сержант-ганни».

Каждый ответ, который я видел в этой теме, рекомендует использовать фильтр jQuery ().Я думаю, что я не понимаю это достаточно хорошо.Я попытался использовать эту строку в цикле, но ничего:

nopeEles = nopeEles.add( $("a").filter(function() { return $(this).text() === nope[i]; }) );

Другой угол, на который я думал взглянуть, - это перебираться с containsNC, поэтому он ищет слово, но с пробелом или концом строки налюбая сторона.Хотя я не совсем понимаю, как работает содержащиеся в NC.

Любые указатели были бы очень благодарны!

1 Ответ

0 голосов
/ 12 ноября 2018

То, что containsNC это просто некачественная версия этого p:containsCI() расширения jQuery .
("NC" == "no case" ≈≈ "CI")== "Без учета регистра".)

Вместо этого используйте связанное расширение jQuery, а затем вы можете использовать регулярное выражение для сопоставления целых слов, например:

nopeEles = nopeEles.add( $("a:containsCI('\\b" + nope[i] + "\\b')") );

Однако этоКод вопроса довольно неэффективен, и вы обнаружите, что он замедляет страницу, потому что он сканирует всю страницу 2N раза (где N - количество терминов), умноженное на сканирование J подстрок (где J - число <a> и <p> node).

Более эффективный способ - сканировать каждый узел только один раз, объединяя регулярное выражение.Посмотрите эту демонстрацию:

jQuery.extend (
    jQuery.expr[':'].containsCI = function (a, i, m) {
        var sText   = (a.textContent || a.innerText || "");
        var zRegExp = new RegExp (m[3], 'i');
        return zRegExp.test (sText);
    }
);

//-- Build array of terms to filter:
var badTerms    = ['die', 'guns?', 'agitators?'];
//-- Build ONE regex string for speed and efficiency:
var cnsrRegEx   = `\\b(${badTerms.join ("|")})\\b`;  //  \b is word-break regex.

var nopeEles    = $("a, p").filter (":containsCI('" + cnsrRegEx + "')");

//-- Hide all applicable elements:
nopeEles.css ( {
    "background-color": "white",
    "color": "white"
} );
a, p {border: 1px solid lightgray; padding: 0.3ex 1ex;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<p>All good</p>
<p>All bad agitators</p>
<div>Some bad: <a>die</a> <a>gun</a> <a>candied</a> <a>gung-ho</a> <a>guns</a>
  <a>he fired a gun</a> <a>gunney sergeant</a>
</div>

Примечание:

  1. Регулярное выражение, подобное guns?, позволяет сопоставлять как «пистолет», так и «пистолет».
  2. Поскольку мы создаем строку , которая будет преобразована в регулярное выражение, \ символов необходимо экранировать.То есть используйте "\\b", чтобы получить \b в регулярном выражении.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...