Страницы: 1
Хочу перебрать в цикле все элементы <span>, у которых внутри есть какой-то текст. Первый <span> имеет id="start", остальные его не имеют (т.к. их дофига).
если я обращаюсь к полю id.firstChild.innerHTML, то весь текст доступен, если же пробую сделать перебор с помощью временной переменной node:
var node = start; while (node != null) { var text = node.firstChild.innerHTML; if(text.indexOf(... // то выполняются какие-то действия node = node.nextSibling; }
то начинают ругаться нато, что у node нет поля firstChild.
Что я делаю неправильно? Буду благодарен любым замечаниям.
Отсутствует
O.Nick
если я обращаюсь к полю id.firstChild.innerHTML...
Правильно будет обращаться document.getElementById('start').
начинают ругаться нато, что у node нет поля firstChild
При переборе всех узлов через nextSibling между span'ами вполне могут быть текстовые узлы, у которых само собой нет firstChild. Так что правильно будет проверять, что nodeName у элемента равно SPAN. Также у пустого SPAN может не быть firstChild, так что лучше это проверить с помощью hasChildNodes(). Можно так же еще проверить, что firstChild является текстом через node.firstChild.nodeType==3.
Хочу перебрать в цикле все элементы <span>, у которых внутри есть какой-то текст. Первый <span> имеет id="start", остальные его не имеют (т.к. их дофига).
Не очень понятно, нужно перебрать только "братков" у "start", или все SPAN, начиная со "start"? Если второе, то легче воспользоваться document.getElementsByTagName('SPAN') и при переборе выставить "флаг" при нахождении "start". (Если вообще нужны все SPAN, то можно и без флага)
В общем, на примере понятней:
<html> <body> <script type="text/javascript"> function select_siblings(){ var ar=new Array; var node = document.getElementById('start'); while (node!=null) { if (node.nodeName=='SPAN'&&node.hasChildNodes()&&node.firstChild.nodeType==3) { var text = node.firstChild.nodeValue; ar.push(text); //if(text.indexOf(... // то выполняются какие-то действия } node = node.nextSibling; } alert(ar); } function select_spans_after_start(){ var ar=new Array; var spans = document.getElementsByTagName('SPAN'); var flag=false; for(i=0; i<spans.length; i++) { if (spans[i].getAttribute('id')=='start') flag=true; if (flag==true&&spans[i].hasChildNodes()&&spans[i].firstChild.nodeType==3) { var text = spans[i].firstChild.nodeValue; ar.push(text); } } alert(ar); } function select_all_spans(){ var ar=new Array; var spans = document.getElementsByTagName('SPAN'); for(i=0; i<spans.length; i++) { if (spans[i].hasChildNodes()&&spans[i].firstChild.nodeType==3) { var text = spans[i].firstChild.nodeValue; ar.push(text); } } alert(ar); } </script> <div> <span>1</span> <span>2</span> <span></span> <span>3</span> </div> <div> <span id="start">a</span> <span>b</span> <span></span> <span><span></span></span> <span>c</span> </div> <div> <span>x</span> <span>y</span> <span></span> <span>z</span> </div> <div> <input type="button" onclick="select_siblings();" value="Перебрать всех 'братков' у 'start'"> <br> <input type="button" onclick="select_spans_after_start();" value="Перебрать все SPAN после 'start'"> <br> <input type="button" onclick="select_all_spans();" value="Перебрать все SPAN'ы"> </div> </body> </html>
Отсутствует
p.s.
А ещё есть XPath. Вот html Yan'а, использующий XPath:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <body> <script type="text/javascript"> function resultHandlerFunction (xpathRes) { var ar = new Array (); for (var i = 0; i < xpathRes. snapshotLength; i++) ar. push (xpathRes. snapshotItem (i). textContent); alert (ar); } function do_xpath_query (query, resultHandler) { var elements = document. evaluate ( query, document, null, XPathResult. UNORDERED_NODE_SNAPSHOT_TYPE, null ); resultHandler (elements); } function select_siblings() { do_xpath_query ( /*"//span[@id='start']/following-sibling::span[text()]"*/ // - кроме <span id="start"> "//span[@id='start']/../span[text()]", resultHandlerFunction ); } function select_spans_after_start() { do_xpath_query ( /*"//span[@id='start']/following::span[text()]"*/ // - кроме <span id="start"> "//span[@id='start']|//span[@id='start']/following::span[text()]", resultHandlerFunction ); } function select_all_spans() { do_xpath_query ("//span[text()]", resultHandlerFunction); } </script> <div> <span>1</span> <span>2</span> <span></span> <span>3</span> </div> <div> <span id="start">a</span> <span>b</span> <span></span> <span><span></span></span> <span>c</span> </div> <div> <span>x</span> <span>y</span> <span></span> <span>z</span> </div> <div> <input type="button" onclick="select_siblings();" value="Перебрать всех 'братков' у 'start'"> <br> <input type="button" onclick="select_spans_after_start();" value="XPath: Перебрать все SPAN после 'start'"> <br> <input type="button" onclick="select_all_spans();" value="Перебрать все SPAN'ы"> </div> </body> </html>
Время настанет, время придет...
И лис кОнкурiентов на части порвет !!!
Отсутствует
Снова возвращаюсь в эту старую ветку, т.к. появились некоторые новости. Все по порядку.
Преамбула. За основу взял код, который привел Yan:
var node = document.getElementById('start'); while (node!=null) { if (node.nodeName=='SPAN'&&node.hasChildNodes()&&node.firstChild.nodeType==3) { var text = node.firstChild.nodeValue; ar.push(text); //if(text.indexOf(... // то выполняются какие-то действия } node = node.nextSibling; } }
Но "оптимизировал" т.к. заложился на внутреннюю структуру того, что лежит внутри <span> - а эта структура не будет менятся ни при каких обстоятельствах.
Получилось так:
while (node != null) { if(node.nodeName == "SPAN") { var text = node.firstChild.firstChild.innerHTML; // закладывается на структуру if(filter == "" || text.indexOf(filter) != -1) // оставляем видимыми только те <span>, которые внутри содержат текст из переменной filter node.style.display = "inline"; else node.style.display = "none"; if(gTimeout != 0) // служебная проверка break; } node = node.nextSibling; }
Код реализован на ОЧЕНЬ большой странице (270K) http://lermont.ru/all.php, функция ApplyFilter из filter.js
Амбула. Добавил таймер работы фильтра и прогнал эту страницу в Firefox 1.5, IE6 и Opera 9 - посмотрел на результаты и тихо офигел - Firefox тормозит сильнее всех. Как я проверял - для каждого браузера делал 2 замера, первый, когда в строку фильтра вводится текст, которого заведомо нет ни в одном теге - zzz, в этом случае перебирается около 3000 тегов (узлы <span>) и у них выставляется display = "none". Примерное время по браузерам:
Firefox - 0.922 сек
IE - 15.484 сек
Opera - 0.359 сек
Второе действие - обратное, затираем в строке фильтра zzz, чтобы она стала пустой. При этом вновь перебираются эти же 3000 тегов и у них выставляем display = "inline". Примерное время по браузерам:
Firefox - 6.828 сек
IE - 15.360 сек
Opera - 0.609 сек
Второе время, которое показывает Firefox - не соответствует действительности, после того, как высвечивается надпись 6.828 сек, проходит еще секунд 40, пока появятся теги.
Как-то обидно за любимый браузер. Если кто поможет советом как ускорить скрипт в Firefox и как пофиксить замер времени под Firefox - буду очень благодарен.
Отредактировано O.Nick (12-07-2006 12:04:10)
Отсутствует
Несколько оптимизировал страницу - убрал промежуточные текстовые узлы между <span>, теперь при втором замере Firefox пишет, что отобразил все теги за 0.844 сек, но реально отображает где-то за 40-50 секунд.
Отсутствует
Страницы: 1