Элементы jQuery не могут выбрать parent () - PullRequest
10 голосов
/ 28 сентября 2010

Кажется, элементы, выбранные с помощью :contains(sub) с sub, содержащим < или >, не могут добраться до своих родителей.

Следующий пример должен проиллюстрировать проблему, с которой я сталкиваюсь как в Safari, так иCamino (Gecko на Mac):

<html>
 <head>
  <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.min.js"></script>
 </head>
 <body>
  <p><strong>bar</strong></p>
  <p><strong>&lt;foo&gt;</strong></p>
  <script type="text/javascript">
alert($('body strong:contains("bar")').length);
alert($('body strong:contains("bar")').parent().length);
alert($('body strong:contains("<foo>")').length);
alert($('body strong:contains("<foo>")').parent().length); // this fails
alert($('body strong').length);
alert($('body strong').parent().length); // two p elements
alert($('body strong').parent().parent().length); // one body
  </script>
 </body>
</html>

Вывод:

1
1
1
0
2
2
1

Любые идеи, почему четвертый - 0 вместо 1, или как я могу обойти это?

На этой странице упоминается экранирование имен в селекторах, но это тоже не сработало (также я не уверен, применимо ли это).

Ответы [ 4 ]

3 голосов
/ 28 сентября 2010

Отказ от ответственности: это не решение / использование обходного пути ответ Тату за это, это просто описание проблемы и того, что вызывает странное поведение у любопытных.

Корень проблемы здесь, регулярное выражение, которое jQuery использует для идентификации фрагмента HTML :

/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/

Что делает соответствует вашему селектору:

body strong:contains("<foo>")

Вы можете попробовать его :

alert(/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/.test('body strong:contains("<foo>")​​​'));​

Так что он думает, что это HTML-фрагмент ... так что в целом это в настоящее времяэквивалент:

$('body strong:contains("<foo>")');
$('<foo>');

Видение второго - более ясная иллюстрация того, что это фрагмент документа ... у которого нет родителя.Он занимает 2-ю позицию в массиве совпадений, который, как вы можете видеть, просто <foo>, , попробуйте снова :

alert(/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/.exec('body strong:contains("<foo>")')[1]);​

В результате вы в конечном итоге окажетесь на этот путь кода в jQuery $(), строящий фрагмент.

Короче говоря да , я бы посчитал это ошибкой jQuery.

2 голосов
/ 28 сентября 2010

Не знаю, что вызывает contains(), но вы можете использовать .filter() в качестве альтернативы:

alert($('body strong').filter(function() {
    return /<foo>/.test( $(this).text() );
}).parent().length);

Возвращает 1, как и ожидалось. Это некрасиво, но работает.

1 голос
/ 28 сентября 2010

Это явно проблема с синтаксическим анализом селектора jQuery. Если в селекторе присутствуют < и >, jQuery идентифицирует аргумент как фрагмент документа вместо селектора. Результатом является элемент с tagName , равным «FOO», и те же селекторы будут иметь ту же проблему:

$('body <foo>')
$('body strong:not(<foo>')

Единственное отличие в вашем случае состоит в том, что вы использовали правильный селектор, а jQuery неправильно его идентифицирует.

Я сделал несколько попыток обходного решения на основе селектора, но Тату Ульманена был единственным, который сработал.

РЕДАКТИРОВАТЬ: кажется, вы также можете использовать .find () :

$(document.body).find('strong:contains("<foo>")')
1 голос
/ 28 сентября 2010

<foo> оценивается как тег, поэтому его родитель не содержит ничего, кроме пустого тега, то есть 0.

РЕДАКТИРОВАТЬ: Чтобы полностью понять, посмотрите на это: $('body strong:contains("foo")').text().length, что приводит5. 1 из $('body strong:contains("<foo>")').length говорит, что внутри сильного есть один текстовый узел, длина которого равна 1, а длина текста равна 5.

Интересным моментом является конечный &gt;, которыйне может быть выбран правильно, так как > и &gt; не работают из-за >, который используется в качестве селектора CSS.Итак, <foo работает, но не <foo>

Вот страница скрипки, с которой можно поиграть: http://jsfiddle.net/2XEUg/1/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...