Пользовательский селектор jQuery для текстовых узлов - PullRequest
2 голосов
/ 03 мая 2011

Я хотел бы извлечь текст из элемента DOM, используя пользовательский селектор jQuery. Он должен выбирать только текстовый узел без его родных тегов (очень похоже на / text () в XPath).

Справочная информация. Я работаю над расширением Firefox, которое извлекает некоторую конкретную информацию (например, имя пользователя) на самых разных веб-сайтах. Теперь я хочу, чтобы мои пользователи могли динамически добавлять определения путей для новых веб-сайтов в максимально простой форме:

Добавить новый сайт:

URL: _ __ _ __ _ __ _ __ _ ___ (например, "http://stackoverflow.com/questions/")

Путь: _ __ _ __ _ __ _ __ _ ___ (например, ".user-details> a: eq (0)" для имени пользователя, задающего вопрос)

Например, в stackoverflow $ (path) .text () вернет имя пользователя в виде текста. Но на некоторых других сайтах имя пользователя доступно только как текстовый узел с помеченными родными братьями, как в этом примере:

<div id="person">
    johndoe <span id="age">(57)</span>
    <span id="description">Lorem ipsum dolor sit amet…</span>
</div>

Поскольку jQuery не предоставляет селектор для текстовых узлов (например, / text () в XPath), я надеялся найти решение, создающее пользовательский селектор.

Я знаю, как получить текстовый узел способом без выбора:

var textNode = $('#person').contents().filter(function(){
    return this.nodeType == 3;
}).text();

alert(textNode); // gives me "johndoe"

Как бы я перевел это в пользовательский селектор? Очевидно, что следующее не работает, поскольку оно всегда возвращает полный элемент, как только одна его часть является текстовым узлом (как объясняет @VinayC в своем ответе):

$.extend($.expr[':'],{
    getText: function(element){
        return $(element).contents().filter(function() {return this.nodeType == 3;}).text();
    }
});

alert($('#person:getText')); //returns the whole DIV element

см. Мой jsfiddle

Возможно, это невозможно сделать с помощью пользовательских селекторов jQuery. Вот почему я думаю вернуться к XPath, который кажется более универсальным.

Спасибо за вашу помощь.

1 Ответ

2 голосов
/ 03 мая 2011

Что вы делаете, это создаете селектор jquery, и функция селектора должна возвращать логическое значение, чтобы указать, соответствовал ли переданный узел или нет. Таким образом, ваша текущая функция возвращает «true» для «#person» div ((фактическое возвращаемое значение - это текст внутри div, который не пуст и, следовательно, рассматривается как true), и, следовательно, вы получаете элемент div в качестве результата.

Вы можете попробовать getText: function(node){ return node.nodeType == 3;}, но это сработает, только движок jquery пропускает все узлы документа, включая текстовые узлы, с помощью функций селектора (я не знаю, если это так или нет). Альтернативой является создание вспомогательной функции вместо пользовательского селектора.

РЕДАКТИРОВАТЬ: как насчет расширения объекта jquery? Например,

$.fn.extend({
    getText: function() {
        return this.contents().filter(function() {return this.nodeType == 3;}).text();
    }
});

alert($('#person').getText());
...