Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 10.08.2010, 14:43
Профессор
Отправить личное сообщение для exec Посмотреть профиль Найти все сообщения от exec
 
Регистрация: 21.01.2010
Сообщений: 1,022

Удаление пустых текстовых нод работает только на верхнем уровне 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-й строчке ведь ясно написано, что если текущая нода — не текстовая, продолжать разбор дальше.
Ответить с цитированием
  #2 (permalink)  
Старый 10.08.2010, 14:50
Аватар для Gvozd
Матрос
Отправить личное сообщение для Gvozd Посмотреть профиль Найти все сообщения от Gvozd
 
Регистрация: 04.04.2008
Сообщений: 6,246

да, не.вроде нормально работает же?
обходит все элементы.
по крайней мере в FF
Ответить с цитированием
  #3 (permalink)  
Старый 10.08.2010, 15:11
Профессор
Отправить личное сообщение для exec Посмотреть профиль Найти все сообщения от exec
 
Регистрация: 21.01.2010
Сообщений: 1,022

Проверял только в Opera 10.6, сейчас в других браузерах проверю.
Ответить с цитированием
  #4 (permalink)  
Старый 10.08.2010, 15:18
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

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

Последний раз редактировалось Octane, 10.08.2010 в 15:21.
Ответить с цитированием
  #5 (permalink)  
Старый 10.08.2010, 23:00
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,120

ещё вариант ))) ...
<!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>
Ответить с цитированием
  #6 (permalink)  
Старый 11.08.2010, 06:41
Профессор
Отправить личное сообщение для exec Посмотреть профиль Найти все сообщения от exec
 
Регистрация: 21.01.2010
Сообщений: 1,022

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.

Последний раз редактировалось exec, 11.08.2010 в 06:45.
Ответить с цитированием
  #7 (permalink)  
Старый 11.08.2010, 09:17
Аватар для x-yuri
Отправить личное сообщение для x-yuri Посмотреть профиль Найти все сообщения от x-yuri
 
Регистрация: 27.12.2008
Сообщений: 4,201

потому что строка, состоящая из пробелов - это 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, зачем цикл в функцию заворачивать?

Последний раз редактировалось x-yuri, 11.08.2010 в 09:26.
Ответить с цитированием
  #8 (permalink)  
Старый 11.08.2010, 11:10
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Сообщение от x-yuri
зачем цикл в функцию заворачивать?
Чтобы запустить цикл удаления узлов один раз.
Ответить с цитированием
  #9 (permalink)  
Старый 20.09.2010, 18:42
Интересующийся
Отправить личное сообщение для pashak Посмотреть профиль Найти все сообщения от pashak
 
Регистрация: 08.04.2010
Сообщений: 16

Как вам нерекурсивный вариант, который базируется на регулярных выражениях?
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,"<");
};

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

Последний раз редактировалось pashak, 20.09.2010 в 18:51.
Ответить с цитированием
  #10 (permalink)  
Старый 20.09.2010, 18:44
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

Сообщение от pashak
Первый реплейс делает пробелы между словами одиночными.
Второй - удаляет все остальные множественные пробелы.
Третий - удаляет пробелы после открытия тега.
Четвертый - перед закрытием.
Это можно было сделать и одним выражением.

А вы представляете последствия изменения innerHTML?
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск