2014-01-17 4 views
1

Возьмите этот HTML:Проверка того, содержит ли элемент HTML примитивный текст?

<div id="el1"> 
    <div id="el2"> 
    <div id="el3"> 
     Hello 
     <div id="el4"> 
     World 
     </div> 
    </div> 
    </div> 
</div> 

Обратите внимание, что el3 и el4 содержат примитивный текст; а именно «Hello» и «World». Другие элементы (el1 и el2) содержат только другие элементы.

И все же, используя чистый JavaScript, все их свойства innerHTML указывают, что они содержат некоторую форму текста.

Как можно использовать чистый JavaScript для проверки того, содержит ли конкретный элемент примитивный текст в качестве дочернего. В этом случае метод также распознает el3 как содержащий примитивный текст (хотя он также содержит и следующий элемент).

Что-то вроде этого:

var els = getElementByTagName("*"); 

for(var i = 0; i < els.length; i++){ 

    if(/* element contains text */){ 

    // do something 

    } 
} 

Является ли это на самом деле просто работа для регулярных выражений? Со всеми свойствами HTMLElement вы бы подумали, что будет лучший способ.

Нет jQuery, спасибо.

+0

Определите «примитивный текст». Все элементы в этом примере содержат текстовые узлы. Вместо использования изобретенного выражения, такого как «примитивный текст» без определения, вы должны определить тест, который хотите выполнить. Возможно, вы хотите проверить, содержит ли элемент текстовые узлы, у которых есть контент, отличный от пробельных символов? Тогда вам просто нужно определить, какие символы следует рассматривать как символы пробелов, а остальное - простое кодирование. –

+0

Вы немного опоздали на вечеринку. Учитывая три ответа, все компетентные, были выдвинуты, что большинство людей понимают мое «выдуманное выражение». Если бы я знал входы и выходы DOM, то, возможно, я мог бы сформулировать «текстовые узлы с содержанием, отличным от пробелов». Но я решил попытаться описать то, что было после, и надеюсь, что кто-то более творческий, возможно, сможет понять, что я имел в виду. К счастью, они это сделали. – shennan

ответ

1

innerHTML получает HTML, и все элементы, кроме последнего, содержат HTML, поскольку они вложены.

Например, innerHTML из #el2 будет

<div id="el3"> 
     Hello 
     <div id="el4"> 
      World 
     </div> 
    </div> 

Чтобы получить только текст, современные браузеры поддерживают либо innerText или textContent (светлячок).
Тогда есть пробелы, так что вы, вероятно, следует обрезать() текст, а также, так что-то вроде этого

var els = document.querySelectorAll("#wrapper *"); 

for(var i = 0; i < els.length; i++){ 
    var el = els[i].cloneNode(true); 
    var children = el.children; 

    for (var j=children.length; j--;) el.removeChild(children[j]); 
    var content = el.innerText ? el.innerText : el.textContent; 

    if(content.trim().length){ 
     // do something 
     console.log(els[i].getAttribute('id') + ' has text'); 
    } 
} 

FIDDLE

или контроль NODETYPE и nodeValue текстовых узлов

var els = document.querySelectorAll("#wrapper *"); 

for(var i = 0; i < els.length; i++){ 
    var el = els[i]; 
    var children = el.childNodes; 

    for (var j=children.length; j--;) { 
     if(children[j].nodeType === 3 && children[j].nodeValue.trim().length) { 
      // do something 
      console.log(els[i].getAttribute('id') + ' has text'); 
     } 
    } 
} 

FIDDLE

+0

Это не сработает. Я знаю, что 'innerHTML' содержит все под выбранным элементом, но' innerText' и 'textContent' не являются заменой, поскольку они все еще указывают на то, что текст еще ниже по дереву DOM, даже если сам элемент не содержит текста. – shennan

+0

Вот доказательство: http://jsfiddle.net/jXL7H/ – shennan

+0

Затем просто удалите дочерние элементы, а затем проверьте, содержит ли элемент текст. – adeneo

1

Вы указываете разницу между узлами элементов и текстом n odes через свойство nodeType. myelementnode.nodeType вернет 1, mytextnode.nodeType вернет 3.

как следует из названия, getElementsByTagName даст вам только узлы элемента. то, что вы хотите сделать, это использовать свойство childNodes вашего корневого узла, которое вы получите всех непосредственных детей этого узла как нодлиста. поэтому для el1 вы получите только один дочерний узел el2.

Вам необходимо рекурсивно пройти через каждый дочерний узел, чтобы получить его дочерние объекты, пока вы не нажмете узел с типом 3 - текст.

поэтому для el3 он вернет 2 дочерних узла. Первый будет вашим текстом, вторым будет ваш элемент el4. Затем вам нужно войти в el4, чтобы получить его дочерний узел.

внутреннийHTML возвращает строку (фрагмента html, преобразованного в строку), а не узлов.вы можете использовать это и регулярное выражение, чтобы отбросить все, что находится в пределах < и>, но это немного грубо, а с большими кусками html будет дорогостоящий процесс.

+0

Да, пытался избежать сложного регулярного выражения. У меня + 1'd, но я дам вам ответ, если вы можете дать мне пример, способный прояснить ситуацию? Что-то, что связано с HTML, изложенным в вопросе. :-) – shennan

1

Вот пример того, как можно использовать nodeType, чтобы помочь вам получить ваш ответ:

var els = document.getElementsByTagName("*"); 

for (var i = 0; i < els.length; i++) { 
    var hasTextNode = false; 
    var currChildren = els[i].childNodes; 

    for (var j = 0; j < currChildren.length; j++) { 
     if ((currChildren[j].nodeType === Node.TEXT_NODE) && 
      (!(/^\s*$/.test(currChildren[j].textContent)))) { 
       hasTextNode = true; 
       break; 
     } 
    } 

    window.console.log(els[i].id + ((hasTextNode) ? " has" : " does not have") + " a Text Node"); 
} 

Применяя это к HTML, который вы предоставили результаты в этом в консоли:

el1 does not have a Text Node 
el2 does not have a Text Node 
el3 has a Text Node 
el4 has a Text Node 

Примечание: важно проверить найденные текстовые узлы для содержимого «только пространство», поскольку DOM рассмотрит все отступы и отступы в исходном коде как «текстовый узел». Очевидно, вы хотели бы игнорировать их.

+0

Мне нравится ваше сравнение с константой 'Node.TEXT_NODE' и вашей фразой' break' для эффективности. Не могли бы вы описать использование регулярного выражения? – shennan

+1

Несомненно. , , шаблон регулярного выражения в основном выглядит от начала до конца текста в узле ('^' - begin, '$' - end) и проверяет, содержит ли весь текст 0 или более ('*' - 0 или более) пробельные символы ('\ s' - пробельные символы). Если это все пробелы, то предполагается, что текстовый узел является просто результатом форматирования исходного кода. Если это ** не ** все пробельные символы, то предполагается, что он содержит преднамеренное текстовое содержимое. – talemyn

+0

Fab, еще раз спасибо. + +1. Я дам ответ @adeneo, поскольку он первым дал рабочий пример. Но я также применим некоторые из ваших приемов. Приветствия. – shennan

Смежные вопросы