Удаление пустых текстовых нод работает только на верхнем уровне DOM
Имеется вот такая функция:
domNormalize = function ( element ) { var childs = element.childNodes; for ( var i = 0; i < childs.length; i++ ) { if ( childs[i].nodeType != 3 ) { domNormalize( childs[i] ); } else if ( childs[i].nodeType == 3 && /\s*/.test(childs[i].textContent || childs[i].innerText) ) { childs[i].parentNode.removeChild( childs[i] ); } } return element.innerHTML; }; Например, если написать domNormalize( document.body ); то будут удалены только те ноды, которые являются прямыми потомками BODY. Почему так происходит? В 5-й строчке ведь ясно написано, что если текущая нода — не текстовая, продолжать разбор дальше. |
да, не.вроде нормально работает же?
обходит все элементы. по крайней мере в FF |
Проверял только в Opera 10.6, сейчас в других браузерах проверю.
|
childNodes динамическая структура же, когда в цикле удаляешь элементы, length меняется
function normalize(element) { var i, textNodes = []; (function (element) { var i, node, nodes = element.childNodes, length = nodes.length; for (i = 0; i < length; i++) { node = nodes[i]; if (node.nodeType == 3 && !node.nodeValue) { textNodes.push(node); } else if(node.hasChildNodes()) { arguments.callee(node); } } })(element); for (i = 0; i < textNodes.length; i++) { textNodes[i].parentNode.removeChild(textNodes[i]); } } normalize(document.body); И у текстовых узлов нет геттеров innerText и textContent |
ещё вариант ))) ...
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script language="JavaScript" type="text/javascript"> domNormalize = function (c) { var d = c.innerHTML; (function (e) { for (var b = e.childNodes, a = b.length - 1; a >= 0; a--) { b[a].hasChildNodes() && arguments.callee(b[a]); b[a].nodeType == 3 && /^\s+$/.test(b[a].data) && b[a].parentNode.removeChild(b[a]) } })(c); alert(d + "\n" + c.innerHTML) }; window.onload=function(){domNormalize(document.body);}; </script> </head> <body> <div> <div> <p> </p> <p> </p> </div> </div> 123 </body> </html> |
Octane,
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> </head> <body> <div> </div> <p> </p> <p> </p> 123 <script language="JavaScript" type="text/javascript"> alert( document.getElementsByTagName('div')[0].nextSibling ); // object text function normalize(element) { var i, textNodes = []; (function (element) { var i, node, nodes = element.childNodes, length = nodes.length; for (i = 0; i < length; i++) { node = nodes[i]; if (node.nodeType == 3 && !node.nodeValue) { textNodes.push(node); } else if(node.hasChildNodes()) { arguments.callee(node); } } })(element); for (i = 0; i < textNodes.length; i++) { textNodes[i].parentNode.removeChild(textNodes[i]); } } normalize(document.body); alert( document.getElementsByTagName('div')[0].nextSibling ); /// object text </script> </body> </html> Тестил под Opera. |
потому что строка, состоящая из пробелов - это true ;)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> </head> <body> <div> </div> <p> </p> <p> </p> 123 <script language="JavaScript" type="text/javascript"> alert( document.getElementsByTagName('div')[0].nextSibling ); // object text function normalize(element) { var children = element.childNodes; var textNodes = []; for( var i=0, n=children.length; i<n; i++ ){ var child = children[i]; if( isEmptyTextNode(child) ) textNodes.push( child ); else if( child.hasChildNodes() ) normalize(child); } for( var i=0, n=textNodes.length; i<n; i++ ){ var textNode = textNodes[i]; textNode.parentNode.removeChild( textNode ); } function isEmptyTextNode( node ){ return node.nodeType == 3 && ! node.nodeValue.replace(/\s+/, ''); } } normalize(document.body); alert( document.getElementsByTagName('div')[0].nextSibling ); /// object text </script> </body> </html> Octane, зачем цикл в функцию заворачивать? |
Цитата:
|
Как вам нерекурсивный вариант, который базируется на регулярных выражениях?
var normalize=function normalize(htmlRoot){ if(!htmlRoot) htmlRoot=document.documentElement; htmlRoot.innerHTML=(htmlRoot.innerHTML+"").replace(/\b([ \t\n\r]){2,}\b/g,function(x,y){return y[0];}).replace(/[ \t\n\r]{2,}/g,"").replace(/>[ \t\n\r]*\b/g,">").replace(/\b[ \t\n\r]*</g,"<"); }; Первый реплейс делает пробелы между словами одиночными. Второй - удаляет все остальные множественные пробелы. Третий - удаляет пробелы после открытия тега. Четвертый - перед закрытием. Кстати, набор заменяемых символов можно подправить. |
Цитата:
А вы представляете последствия изменения innerHTML? |
Ничего страшного не произойдёт, за исключением того, что обрежется форматированный текст в input. А в остальных случаях, ничего не случится.
Если не согласны - приведите конкретный пример. |
Пересоздадутся все DOM-элементы на странице, на новых элементах уже не будет навешанных обработчиков событий.
|
Предполагается, что данная функция обработает лишь начальный шаблон, т.е. ее необходимо запустить до начала действия скрипта, вешающего все обработчики событий. Возможно также применение не для все страницы, а для отдельного элемента, в чем и есть преимущество.
Как вариант - создание рекурсивной функции, проверяющей наличие ОПРЕДЕЛЕННЫХ символов в TextNode, потому что вышеприведенная версия не удалит текстовые узлы, состоящие из пробельных символов. |
Как вариант:
var normalize=function normalize(htmlRoot){ if(!htmlRoot) htmlRoot=document.documentElement; for(var i=htmlRoot.firstChild;i!=null;) if(i.nodeType==3&&(i.textContent||i.text).search(/\S/)==-1) { var old=i; i=i.previousSibling||i.nextSibling; old.parentNode.removeChild(old); } else { if(i.childNodes.length) arguments.callee(i); i=i.nextSibling; } }; Проверено на [JS]window.onload=recourse[\JS] |
Часовой пояс GMT +3, время: 14:22. |