Поиск фразы по тексту
Привет всем!
Кто может помочь с теорией (или примером), а то я что то уже запутался в край. Итак, есть простой HTML-код: <html> <head> <title>Test Search</title> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <script language="javascript"> //возвращает список textnode заданого node function TNList(node,list){ for(var a=0;a<node.childNodes.length;a++){ if(node.childNodes[a].nodeType==3) list.push(node.childNodes[a]); else TNList(node.childNodes[a],list); } } //поиск и выделение объекта (DOM) function search_and_select(b,str){ var ltn=new Array(); TNList(b,ltn); for(var a=0;a<ltn.length;a++){ if(ltn[a].nodeValue.indexOf(str)!=-1){ var s=window.getSelection(); var r=document.createRange(); r.setStart(ltn[a],ltn[a].nodeValue.indexOf(str)); r.setEnd(ltn[a],ltn[a].nodeValue.indexOf(str)+str.length); s.removeAllRanges(); s.addRange(r); alert('Found!'); }else{ alert('Not Found'); } } } //инициализация var init=function(){ var str='text into'; search_and_select(document.body,str); }; </script> </head> <body onload="init();"> <div id="child1">Any text into div <span id="child11">and text into span</span> tags</div> </body> </html> По коду понятно, что при загрузке страницы будет произведён поиск фразы 'text into' по всем textnod'ам рекурсивно, находящихся в body. Всё бы хорошо, если поиск будет производиться только внутри textnod'ов. Но что, если, например, понадобится найти фразу 'div and text', у которой начало начинается в одной textnod'е, а окончание в другой? В теории всё понятно setStart(document.getElementById('child1').firstChild,14); setEnd(document.getElementById('child11').firstChild,8); А вот как это практически реализовать что то никак сообразить не могу. Есть у кого какие мысли по этому поводу? |
может уже поздно, но... можно получить innerText + внешний список DOM-элементов с указанием к какой его части они относятся
|
Нет, не поздно, вопрос ещё открыт и достаточно актуальный.
Однако innerText разве не присущ только для IE? Вопрос с IE не берётся во внимание вообще, потому что я под него написал класс, с помощью которого IE с Range работает по DOM-стандарту. К тому же, у IE есть свойство range.findText. Вообще, мысли очень "хлипкие" по этому поводу. Например, можно создать range всего документа и сузить его до границ body. Далее через selectNodeContents() и toString() вытащить его текстовое содержимое, где производить поиск фразы. Фразу то он находит, а вот как получить граничные точки найденной фразы (startContainer, startOffset, endContainer, endOffset) пока не могу понять. |
ну я не имел в виду буквально innerText, я имел в виду получить текст содержащийся в элементе и всех его детях
т.е. можно создавать этот "innerText" и параллельно создавать другую структуру, в которой отмечать какой элемент в какой позиции "innerText" начинается и где заканчивается. Потому ищем в полученном "innerText" и по внешней структуре находим нужные элементы |
Всё таки решил я эту задачу, но не полностью. Честно говоря, решение мне то же не очень нравится, очень похоже на "подгонку на ответ", но других мыслей пока не появилось.
В данном решении поиск фразы (например, "body Any text") производится по всему тексту и находит все, кроме 2 мест. В коде так же есть часть закоментированноого кода, которая, если её раскомментировать, находит все вхождения, но выделяет найденный текст со смещением. Как это побороть? <html> <head> <title>Search Text</title> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251" /> <script language="javascript"> function getTextNodeList(parentNode,list){ for(var a=0;a<parentNode.childNodes.length;a++){ if(parentNode.childNodes[a].nodeType==3){ if(parentNode.childNodes[a].nodeValue.length==1&&parentNode.childNodes[a].nodeValue==="\n") continue; else list.push({ n: parentNode.childNodes[a], s: list[list.length-1]?parseInt(list[list.length-1].s)+parseInt(list[list.length-1].l):0, l: parentNode.childNodes[a].length }); }else{ getTextNodeList(parentNode.childNodes[a],list); } } } var storage={ srch: '', lastIdx: -1, result: new Array(), clear: function(){ with(storage){ srch=''; lastIdx=-1; result=new Array(); } }, search: function(){ if(storage.srch!==''){ var b=document.body; var list=new Array(); getTextNodeList(b,list); var r=document.createRange(); r.selectNodeContents(b); var c=''; var v=null; for(var a=0;a<list.length;a++){ v=list[a].n.nodeValue; c+=v.replace(/\n/gim," "); /* * Если раскомментировать этот блок, ищет все фразы * но "со смещением" if(v.charAt(v.length-1)!==" "&&v.charAt(v.length-1)!=="\n"){ console.log('"'+v+'"'); c+=' '; } */ } console.log(c); var p=new RegExp(storage.srch,"ig"); var data=null; var startContainer=null; var startOffset=0; var endContainer=null; var endOffset=0; var start=0; var end=0; var ls=0; var ll=0; while((data=p.exec(c))!=null){ start=p.lastIndex-storage.srch.length; end=p.lastIndex; for(var a=0;a<list.length;a++){ ls=parseInt(list[a].s); ll=ls+parseInt(list[a].l); if(start>=ls&&start<ll){ startContainer=list[a].n; startOffset=start-ls; } if(end>=ls&&end<ll){ endContainer=list[a].n; endOffset=end-ls; } } storage.result.push({ sc: startContainer, so: startOffset, ec: endContainer, eo: endOffset }); } } }, init: function(){ storage.clear(); if(arguments[0]) with(storage){ srch=arguments[0]; search(); } } }; function findNext(){ var i=document.getElementById('srchText'); if(storage.result.length==0 || (storage.srch!==i.value && i.value!=='')){ storage.init(i.value); } if(storage.result.length>0){ var s=null; var r=null; // for Gecko only if(window.getSelection){ var s=window.getSelection(); var r=document.createRange(); storage.lastIdx++; if(storage.lastIdx>storage.result.length-1) storage.lastIdx=0; r.setStart(storage.result[storage.lastIdx].sc,storage.result[storage.lastIdx].so); r.setEnd(storage.result[storage.lastIdx].ec,storage.result[storage.lastIdx].eo); s.removeAllRanges(); s.addRange(r); } }else{ alert('Совпадений не найдено'); } } </script> </head> <body> Any text into body Any text into body <div>Any text into body Any text into body <span>Any text into body Any text into body <span>Any text into body Any text into body</span></span></div> <div>Any text into body Any text into body</div> <span>Any text into body Any text into body</span> Any text into body Any text into body <br /> <input id="srchText" type="text" value="" /><input type="button" value="Search" onclick="findNext()" /> </body> </html> |
Часовой пояс GMT +3, время: 23:07. |