Выберите элемент по точному совпадению его содержимого

161

Хорошо, мне интересно, есть ли способ сделать :contains()селектор jQuery для выбора элементов только с той строкой, которая набрана в

например -

<p>hello</p>
<p>hello world</p>

$('p:contains("hello")').css('font-weight', 'bold');

Селектор выберет оба pэлемента и выделит их жирным шрифтом, но я хочу, чтобы он выбирал только первый.

юлианский
источник
Ну, вы можете переопределить :containsселектор своим собственным кодом, но я не думаю, что вы это имели в виду?
Blazemonger
Вы можете определить пользовательский селектор: stackoverflow.com/questions/12244929/…
BLSully
Возможные дубликаты: селектор
Jquery

Ответы:

215

Нет, здесь нет селектора jQuery (или CSS), который бы это делал.

Вы можете легко использовать filter:

$("p").filter(function() {
    return $(this).text() === "hello";
}).css("font-weight", "bold");

Это не селектор , но он делает свою работу. :-)

Если вы хотите обработать пробел до или после «привет», вы можете добавить $.trimтуда:

return $.trim($(this).text()) === "hello";

Для недоношенных оптимизаторов, если вам все равно, что они не совпадают <p><span>hello</span></p>и не похожи, вы можете избежать вызовов $и textиспользуя innerHTMLнапрямую:

return this.innerHTML === "hello";

... но у вас должно быть много параграфов, чтобы иметь значение, так много, что у вас, вероятно, возникнут другие проблемы в первую очередь. :-)

TJ Crowder
источник
7
Возможно, вам также захочется $.trimиспользовать любой проблеск перед сравнением.
Blazemonger
По какой-то причине мне пришлось использовать «==» для этого вместо «===».
Стефан
3
@Stephan: Если вы сравниваете с числом, вам придется либо использовать ==( == 2), либо поместить число в строку ( === "2"), потому что значение, которое вы получаете, text()или innerHTMLвсегда является строкой. Если вы сравнивали со строкой, не имеет значения, используете ли вы ==или ===.
TJ Crowder
Жаль, что jQuery реализовал :containsэто более сложно, но не реализовал селектор для точного соответствия текста. = {
Пауло Буэно
54

Попробуйте добавить расширенную псевдо-функцию:

$.expr[':'].textEquals = $.expr.createPseudo(function(arg) {
    return function( elem ) {
        return $(elem).text().match("^" + arg + "$");
    };
});

Тогда вы можете сделать:

$('p:textEquals("Hello World")');
Амаду Бах
источник
2
отличное решение: небольшое дополнение: чтобы убедиться, что вы не перезаписываете существующий expr, я бы сделал:$.expr[':'].textEquals = $.expr[':'].textEquals || $.expr.createPseudo(function(arg) {
Миша Молхук
9

Вы можете использовать функцию filter () jQuery для достижения этой цели.

$("p").filter(function() {
// Matches exact string   
return $(this).text() === "Hello World";
}).css("font-weight", "bold");
dsgriffin
источник
9

Так что ответ Аманду в основном работает. Однако, используя его в дикой природе, я столкнулся с некоторыми проблемами, когда вещи, которые я ожидал найти, не были найдены. Это было потому, что иногда есть случайные пробелы вокруг текста элемента. Я уверен, что если вы ищете «Hello World», вы все равно хотите, чтобы оно совпадало с «Hello World» или даже «Hello World \ n». Таким образом, я просто добавил метод «trim ()» в функцию, которая удаляет окружающие пробелы, и он начал работать лучше.

В частности ...

$.expr[':'].textEquals = function(el, i, m) {
    var searchText = m[3];
    var match = $(el).text().trim().match("^" + searchText + "$")
    return match && match.length > 0;
}

Кроме того, обратите внимание, этот ответ очень похож на Выбор ссылки по тексту (точное совпадение)

И вторичная заметка ... trimудаляет только пробелы до и после искомого текста. Он не удаляет пробелы в середине слов. Я считаю, что это желательное поведение, но вы можете изменить это, если хотите.

bwest87
источник
5

Я нашел способ, который работает для меня. Это не на 100% точно, но исключает все строки, которые содержат больше, чем просто слово, которое я ищу, потому что я проверяю строку, не содержащую также отдельных пробелов. Кстати, вам не нужны эти "". JQuery знает, что вы ищете строку. Убедитесь, что у вас есть только один пробел в части: contains (), иначе он не будет работать.

<p>hello</p>
<p>hello world</p>
$('p:contains(hello):not(:contains( ))').css('font-weight', 'bold');

И да, я знаю, это не сработает, если у вас есть такие вещи, как <p>helloworld</p>

rf1234
источник
1
Умное использование простых совпадений с содержит (..) без использования фильтра или расширения! Не будет работать над чем-либо, требующим пробелов в первом содержит (..), но пытаюсь найти решение для этого. Спасибо!
JoePC
3

Как и TJ Crowder, указанный выше, функция фильтра творит чудеса. Это не работает для меня в моем конкретном случае. Мне нужно было искать несколько таблиц и их соответствующие теги td внутри div (в этом случае диалоговое окно jQuery).

$("#MyJqueryDialog table tr td").filter(function () {
    // The following implies that there is some text inside the td tag.
    if ($.trim($(this).text()) == "Hello World!") {
       // Perform specific task.
    }
});

Надеюсь это кому-нибудь пригодится!

Грег А
источник
Я довольно новичок в jquery, но думаю, что было бы немного лучше использовать each () вместо filter (), поскольку цель filter - вернуть подмассив. Но определенно вдохновил на решение, так как у меня были те же проблемы :)
JeopardyTempest
0

Однострочник, который работает с альтернативными библиотеками jQuery:

$('p').filter((i, p) => $(p).text().trim() === "hello").css('font-weight', 'bold');

И это эквивалентно a:contains("pattern")селектору jQuery :

var res = $('a').filter((i, a) => $(a).text().match(/pattern/));
leogama
источник
-4

.First () поможет здесь

$('p:contains("hello")').first().css('font-weight', 'bold');
tymeJV
источник
Конечно ... в этом конкретном случае. что если порядок не известен во время разработки?
BLSully