Мой текущий проект включает собирающееся текстовое содержание от элемента и всех его потомков, на основе обеспеченного селектора.
Например, при предоставлении селектор #content
и выполненный против этого HTML:
<div id="content">
<p>This is some text.</p>
<script type="text/javascript">
var test = true;
</script>
<p>This is some more text.</p>
</div>
мой сценарий возвратился бы (после небольшой пробельной очистки):
Это - некоторый текст. тест var = верный; Это - еще некоторый текст.
Однако я должен игнорировать текстовые узлы, которые происходят в <script>
элементы.
Это - выборка моего текущего кода (технически, он соответствует на основе одного или нескольких предоставленного селекторам):
// get text content of all matching elements
for (x = 0; x < selectors.length; x++) { // 'selectors' is an array of CSS selectors from which to gather text content
matches = Sizzle(selectors[x], document);
for (y = 0; y < matches.length; y++) {
match = matches[y];
if (match.innerText) { // IE
content += match.innerText + ' ';
} else if (match.textContent) { // other browsers
content += match.textContent + ' ';
}
}
}
Это немного чрезмерно упрощенно в этом, это просто возвращает все текстовые узлы в элементе (и его потомки), который соответствует обеспеченному селектору. Решение, которое я ищу, возвратило бы все текстовые узлы за исключением тех, которые находятся в пределах <script>
элементы. Это не должно быть особенно высокоэффективно, но мне действительно нужен он, чтобы в конечном счете быть совместимым перекрестным браузером.
Я предполагаю, что должен буду так или иначе циклично выполниться через всех детей элемента, который соответствует селектору, и накопите все текстовые узлы кроме в <script>
элементы; не похоже, что существует любой способ определить JavaScript, после того как это уже прокручивается в строку, накопленную от всех текстовых узлов.
Я не могу использовать jQuery (по причинам производительности/пропускной способности), хотя Вы, возможно, заметили, что я действительно использую его механизм селектора Шипения, таким образом, селекторная логика jQuery доступна.
Заранее спасибо за любую справку!
function getTextContentExceptScript(element) {
var text= [];
for (var i= 0, n= element.childNodes.length; i<n; i++) {
var child= element.childNodes[i];
if (child.nodeType===1 && child.tagName.toLowerCase()!=='script')
text.push(getTextContentExceptScript(child));
else if (child.nodeType===3)
text.push(child.data);
}
return text.join('');
}
Или, если вы можете изменить DOM, чтобы удалить элементы (что обычно не будет иметь заметных побочных эффектов), быстрее:
var scripts= element.getElementsByTagName('script');
while (scripts.length!==0)
scripts[0].parentNode.removeChild(scripts[0]);
return 'textContent' in element? element.textContent : element.innerText;
РЕДАКТИРОВАТЬ :
Ну, сначала позвольте мне сказать, что я не слишком знаком с Sizzle в его одинокой, но в библиотеках, которые используют это ... Тем не менее ...
если бы мне пришлось это сделать, я бы сделал что-то вроде:
var selectors = new Array('#main-content', '#side-bar');
function findText(selectors) {
var rText = '';
sNodes = typeof selectors = 'array' ? $(selectors.join(',')) : $(selectors);
for(var i = 0; i < sNodes.length; i++) {
var nodes = $(':not(script)', sNodes[i]);
for(var j=0; j < nodes.length; j++) {
if(nodes[j].nodeType != 1 && node[j].childNodes.length) {
/* recursion - this would work in jQ not sure if
* Sizzle takes a node as a selector you may need
* to tweak.
*/
rText += findText(node[j]);
}
}
}
return rText;
}
Я не тестировал ничего из этого, но это должно дать вам представление. Надеюсь, кто-то другой подскажет больше направлений: -)
Не можете просто взять родительский узел и проверить nodeName
в своем цикле ... например:
if(match.parentNode.nodeName.toLowerCase() != 'script' && match.nodeName.toLowerCase() != 'script' ) {
match = matches[y];
if (match.innerText) { // IE
content += match.innerText + ' ';
} else if (match.textContent) { // other browsers
content += match.textContent + ' ';
}
}
, конечно, jquery поддерживает not ()
синтаксис в селекторах, так что не могли бы вы просто сделать $ (': not (script)')
?