Теперь для этого есть модуль npm
: https://github.com/erictrinh/safe-access
Пример использования:
var access = require('safe-access');
access(very, 'nested.property.and.array[0]');
jQuery для этого не имеет удобной функции. Вам нужно объединить contents()
, который даст только дочерние узлы, но включает в себя текстовые узлы, с find()
, который дает все элементы-потомки, но не текстовые узлы. Вот что я придумал:
var getTextNodesIn = function(el) {
return $(el).find(":not(iframe)").addBack().contents().filter(function() {
return this.nodeType == 3;
});
};
getTextNodesIn(el);
Примечание. Если вы используете jQuery 1.7 или ранее, код выше не будет работать. Чтобы исправить это, замените addBack()
на andSelf()
. andSelf()
устарел в пользу addBack()
начиная с 1.8.
Это несколько неэффективно по сравнению с чистыми методами DOM и должно включать угадающее обходное решение для перегрузки jQuery его функции contents()
(спасибо @rabidsnail в комментариях за указание этого), так что вот решение не-jQuery с использованием простой рекурсивной функции. Параметр includeWhitespaceNodes
определяет, включены ли в выходные текстовые узлы (в jQuery они автоматически отфильтровываются).
Обновление: Исправлена ошибка, когда includeWhitespaceNodes является ложью.
function getTextNodesIn(node, includeWhitespaceNodes) {
var textNodes = [], nonWhitespaceMatcher = /\S/;
function getTextNodes(node) {
if (node.nodeType == 3) {
if (includeWhitespaceNodes || nonWhitespaceMatcher.test(node.nodeValue)) {
textNodes.push(node);
}
} else {
for (var i = 0, len = node.childNodes.length; i < len; ++i) {
getTextNodes(node.childNodes[i]);
}
}
}
getTextNodes(node);
return textNodes;
}
getTextNodesIn(el);
Я получал много пустых текстовых узлов с принятой функцией фильтра. Если вы заинтересованы только в выборе текстовых узлов, которые содержат не-пробелы, попробуйте добавить nodeValue
к вашей функции filter
, как простой $.trim(this.nodevalue) !== ''
:
$('element')
.contents()
.filter(function(){
return this.nodeType === 3 && $.trim(this.nodeValue) !== '';
});
Или во избежание странных ситуаций, когда содержимое выглядит как пробелы, но не является (например, символ мягкого дефиса ­
, строки новой строки \n
, вкладки и т. д.), вы можете попробовать использовать регулярное выражение. Например, \S
будет соответствовать любым символам без пробелов:
$('element')
.contents()
.filter(function(){
return this.nodeType === 3 && /\S/.test(this.nodeValue);
});
Если вы можете сделать предположение, что все дети являются либо узлами элементов, либо текстовыми узлами, то это одно из решений.
Чтобы все дочерние текстовые узлы представляли собой набор jquery:
$('selector').clone().children().remove().end().contents();
Чтобы получить копию исходного элемента с удаленными дочерними элементами:
$('selector').clone().children().remove().end();
Для меня, казалось, что старый старый .contents()
работал, чтобы возвращать текстовые узлы, просто нужно быть осторожным с вашими селекторами, чтобы вы знали, что они будут текстовыми узлами.
Например, это завернутое все текстовое содержимое TDs в моей таблице с тегами pre
и не было проблем.
jQuery("#resultTable td").content().wrap("<pre/>")
$('body').find('*').contents().filter(function () { return this.nodeType === 3; });
У меня была та же проблема и я решил:
Код:
$.fn.nextNode = function(){
var contents = $(this).parent().contents();
return contents.get(contents.index(this)+1);
}
Использование:
$('#my_id').nextNode();
Как next()
, но также возвращает текстовые узлы.
Jauco опубликовал хорошее решение в комментарии, поэтому я копирую его здесь:
$(elem)
.contents()
.filter(function() {
return this.nodeType === 3; //Node.TEXT_NODE
});
Можно также сделать так:
var textContents = $(document.getElementById("ElementId").childNodes).filter(function(){
return this.nodeType == 3;
});
Вышеупомянутый код фильтрует текстовые узлы из дочерних дочерних узлов дочерних узлов данного элемента.
, если вы хотите удалить все теги, попробуйте эту функцию
:
String.prototype.stripTags=function(){
var rtag=/<.*?[^>]>/g;
return this.replace(rtag,'');
}
use:
var newText=$('selector').html().stripTags();
jQuery.contents()
можно использовать с jQuery.filter
, чтобы найти все дочерние текстовые узлы. С небольшим завихрением вы также можете найти текстовые узлы внуков. Не требуется рекурсия:
$(function() {
var $textNodes = $("#test, #test *").contents().filter(function() {
return this.nodeType === Node.TEXT_NODE;
});
/*
* for testing
*/
$textNodes.each(function() {
console.log(this);
});
});
div { margin-left: 1em; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="test">
child text 1<br>
child text 2
<div>
grandchild text 1
<div>grand-grandchild text 1</div>
grandchild text 2
</div>
child text 3<br>
child text 4
</div>
document.getElementById()
, если это то, что вы имеете в виду:var div = document.getElementById("foo"); var textNodes = getTextNodesIn(div);
– Tim Down 10 February 2011 в 17:43.contents()
в любом случае подразумевает, что он будет искать ифрагмент. Я не понимаю, как это может быть ошибка. – Robin Maben 6 February 2012 в 13:52