Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #11 (permalink)  
Старый 07.04.2009, 18:22
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Попробовал nodeValue. Он тоже не подходит т. к. экранирует теги как innerText. Вот:
var TextNode = {
	each: function(callback, parent) {
		for (var childNodes = (parent || document.body).childNodes, i = 0, length = childNodes.length; i < length; i++) {
			var I = childNodes[i];
			I.nodeType == 1
				? arguments.callee(callback, I)
				: I.nodeType == 3 && callback(I, i);
		}
	}
};

window.onload = function() {
	TextNode.each(function(noda) {
		noda.nodeValue = noda.nodeValue.replace(/(http\:\/\/www\.youtube\.com\/watch\?v\=[0-9a-z]{11})/gi, '<a href="$1">$1</a>');
	});
};

Или я что то не так делаю?

Последний раз редактировалось Riim, 07.04.2009 в 18:31.
Ответить с цитированием
  #12 (permalink)  
Старый 07.04.2009, 18:33
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Получилось через replaceChild:

var TextNode = {
	each: function(callback, parent) {
		for (var childNodes = (parent || document.body).childNodes, i = 0, length = childNodes.length; i < length; i++) {
			var I = childNodes[i];
			I.nodeType == 1
				? arguments.callee(callback, I)
				: I.nodeType == 3 && callback(I, i);
		}
	}
};

window.onload = function() {
	TextNode.each(function(noda) {
		var elem = document.createElement('div');
		elem.innerHTML = noda.nodeValue.replace(/(http\:\/\/www\.youtube\.com\/watch\?v\=[0-9a-z]{11})/gi, '<a href="$1">$1</a>');
		noda.parentNode.replaceChild(elem, noda);
	});
};
Ответить с цитированием
  #13 (permalink)  
Старый 07.04.2009, 19:55
Аватар для Gvozd
Матрос
Отправить личное сообщение для Gvozd Посмотреть профиль Найти все сообщения от Gvozd
 
Регистрация: 04.04.2008
Сообщений: 6,246

Сообщение от Riim
Про весь документ я и не спорю, а про указанное место ты сам начал.
я подразумевал, что задачу наиболее правильно с моей точки зрения решать перебором всех элементов, и замены его непосредственных текстовых потомков.

я не уверен, насчет replaceChild и его кросбраузерности.
не проверял.
я лично в таком случае использовал insertBefore и removeChild
текстовые ноды могут быть не только у body-элемента.
они могут быть потомками любого тега, поэтому надо получить всю коллекцию, и для всех тегов перебрать, например
Ответить с цитированием
  #14 (permalink)  
Старый 07.04.2009, 23:08
Аватар для x-yuri
Отправить личное сообщение для x-yuri Посмотреть профиль Найти все сообщения от x-yuri
 
Регистрация: 27.12.2008
Сообщений: 4,201

Riim, а зачем ты div создаешь? Во-первых, ты добавляешь div'ы, которых изначально не было, а во-вторых может поменяться внешний вид
кроме того, я бы не записывал столько всего в for:
var childNodes = (parent || document.body).childNodes;
length = childNodes.length;
for (i = 0; i < length; i++) {

и использовал бы if'ы вместо тернарного оператора
if( I.nodeType == 1 )
    arguments.callee(callback, I);
elseif( I.nodeType == 3 ) 
    callback(I, i);

а еще, может, регулярное выражение можно проще сделать, но это зависит от наличия других ссылок в тексте
Ответить с цитированием
  #15 (permalink)  
Старый 08.04.2009, 05:53
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Сообщение от Gvozd
я подразумевал, что задачу наиболее правильно с моей точки зрения решать перебором ...
подразумевал это, говоря фразу:
Сообщение от Gvozd
для любой модификации в указанном месте, он уже не подходит
именно ее я процитировал в посте выше, и, по-моему, она больше подразумевает то, что innerHTML плох для всех случаев (для любой модификации).

Сообщение от Gvozd
я не уверен, насчет replaceChild и его кроссбраузерности.
replaceChild описан в стандарте и есть даже в самых древних справочниках по dom. Если и будут какие-то проблемы, то они будут в каком-нибудь IE5.5, про который давно пора забыть.

Сообщение от Gvozd
я лично в таком случае использовал insertBefore и removeChild
Это и так вероятно далеко не самый быстрый вариант, а ты его еще замедлить хочешь (вызов двух методов вместо одного). Ну, станет он работать под каким-нибудь IE5.5 и 0,000....00.1 % пользователей будут рады, а вот остальные наоборот.

Сообщение от Gvozd
текстовые ноды могут быть не только у body-элемента
Как я понял не нравиться эта: (parent || document.body).childNodes строчка и ты предлагаешь пройтись еще и по meta-тегам.

Сообщение от Gvozd
они могут быть потомками любого тега, поэтому надо получить всю коллекцию
Рекурсивно обходиться ВСЯ коллекция.

Сообщение от x-yuri
а зачем ты div создаешь
С блочным элементом я поспешил, лучше span или font какой-нибудь, но элемент создавать все равно надо т. к. при создании текстового узла через createTextNode теги опять, же будут экранироваться. Если я что-то напутал, предлагай свой вариант.

Сообщение от x-yuri
я бы не записывал столько всего в for:
var childNodes = (parent || document.body).childNodes;
length = childNodes.length;
for (i = 0; i < length; i++) {
Теперь "i" будет в window. Еще пара таких функций и начнутся проблемы.

Сообщение от x-yuri
и использовал бы if'ы вместо тернарного оператора
Производительность от этого никак не измениться, зато добавится несколько байт кода. Если таких функций много, то эти несколько байт становятся несколькими Кб, и это уже неприятно.
Что касается читаемости, то, на мой взгляд, при нормальном оформлении тернарного оператора, он читается лучше, чем if-else.
Ответить с цитированием
  #16 (permalink)  
Старый 08.04.2009, 08:24
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Сообщение от Riim
Если я что-то напутал, предлагай свой вариант.
Сам предлагаю:
window.onload = function() {
	TextNode.each(function(noda) {
		var div = document.createElement('div');
		div.innerHTML = noda.nodeValue.replace(/(http\:\/\/www\.youtube\.com\/watch\?v\=[0-9a-z]{11})/gi, '<a href="$1">$1</a>');
		if (div.firstChild && div.innerHTML != noda.nodeValue) {
			var n = noda.nextSibling, p = noda.parentNode;
			do p.insertBefore(div.firstChild, n);
			while (div.firstChild);
			p.removeChild(noda);
		}
	});
};


Теперь нет никаких лишних тегов.
Ответить с цитированием
  #17 (permalink)  
Старый 08.04.2009, 08:29
Аватар для Gvozd
Матрос
Отправить личное сообщение для Gvozd Посмотреть профиль Найти все сообщения от Gvozd
 
Регистрация: 04.04.2008
Сообщений: 6,246

Сообщение от Riim
именно ее я процитировал в посте выше, и, по-моему, она больше подразумевает то, что innerHTML плох для всех случаев (для любой модификации).
да.
Сообщение от Riim
Это и так вероятно далеко не самый быстрый вариант, а ты его еще замедлить хочешь (вызов двух методов вместо одного). Ну, станет он работать под каким-нибудь IE5.5 и 0,000....00.1 % пользователей будут рады, а вот остальные наоборот.
я хотел сказать, лишь о моем конкретном незнании реализованных в DOM JS-а методах.теперь буду знать, что этот метод достаточно кросбраузерен для его использования.
Сообщение от Riim
Как я понял не нравиться эта: (parent || document.body).childNodes строчка и ты предлагаешь пройтись еще и по meta-тегам.
Сообщение от Riim
Рекурсивно обходиться ВСЯ коллекция.
пардон, тупанул.не увидел рекурсии потому что поверхностно осмотрел код.обхода body и его потомков считаю достаточным

Сообщение от Riim
Производительность от этого никак не измениться, зато добавится несколько байт кода. Если таких функций много, то эти несколько байт становятся несколькими Кб, и это уже неприятно.
Что касается читаемости, то, на мой взгляд, при нормальном оформлении тернарного оператора, он читается лучше, чем if-else.
вы лучше в процентах посчитайте насколько код увеличивается от использования нормальных условий.
ИМХО, незначительно.
более того это можно было бы назвать преждевременной оптимизацией, и потому подход этот вреден.
вам тернарный оператор нормально читается, а большинству нет.
то есть ваш подход приемлим, только если вы в одиночку пишите жестко инкапсулированый код, которй предполагаете никто кроме вас дорабатывать не должен.
Ответить с цитированием
  #18 (permalink)  
Старый 08.04.2009, 10:33
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Сообщение от Gvozd
да.
Можно аргументировать. Возможно, у innerHTML действительно есть какие-то минусы, о которых я не знаю. И еще, в последнем, приведенном мною, коде (12:24) innerHTML тоже используется. Может, перепишете его без innerHTML. Интересно как это у вас получится. То есть я не говорю, что этого нельзя сделать, только вот кода на первый взгляд должно получиться раза в 3 больше, а о его производительности вообще лучше не думать.

Сообщение от Gvozd
вы лучше в процентах посчитайте насколько код увеличивается от использования нормальных условий.
Я считал. И не раз. Уменьшать код можно не только за счет тернарного оператора. Есть множество других способов.
У меня код уменьшается минимум на 15%. Думаете, я преувеличиваю? Нет, потому что на результат можно по-разному смотреть. Я, например, смотрю на него после работы YUICompressor-а. Считайте сами, каждая локальная переменная, например "parentNode", становиться одной буквой, то есть "parentNode" уменьшиться в 10 раз. В результате объем операторов в коде, в процентах, становиться довольно значительным и экономить на них уже довольно выгодно.

Сообщение от Gvozd
вам тернарный оператор нормально читается, а большинству нет
С одной стороны на вкус и цвет....
С другой, вот, попадется вам какой ни будь плагин к Jquery (а большинство из них пишутся примерно в этом же стиле) и будите с ним мучиться. У меня с этим проблем нет т. к. свободно воспринимаю самые разные стили.

Сообщение от Gvozd
если вы в одиночку пишите
Сообщение от Gvozd
никто кроме вас дорабатывать не должен
Смотря, что за код. Если это одноразовый код для одной странички, то мне все равно как он будет написан, я даже не думаю об этом, и в результате получается смесь разных стилей. Если мне скажут писать в таком то определенном стиле, то я и спорить не буду. А вот универсальный код, который выносится в отдельный файл, должен изначально писаться максимально качественно, так чтобы его доработка в идеале не потребовалась. И писаться он должен именно одним человеком. А остальные на его основе пишут одноразовые коды, и им должно быть все равно как написана основа, главное, что бы документация обновлялась вовремя.
Ответить с цитированием
  #19 (permalink)  
Старый 08.04.2009, 13:02
Аватар для x-yuri
Отправить личное сообщение для x-yuri Посмотреть профиль Найти все сообщения от x-yuri
 
Регистрация: 27.12.2008
Сообщений: 4,201

Цитата:
С блочным элементом я поспешил, лучше span или font какой-нибудь, но элемент создавать все равно надо т. к. при создании текстового узла через createTextNode теги опять, же будут экранироваться. Если я что-то напутал, предлагай свой вариант
не подумал
Цитата:
Теперь "i" будет в window. Еще пара таких функций и начнутся проблемы
пропустил
Цитата:
Производительность от этого никак не измениться, зато добавится несколько байт кода. Если таких функций много, то эти несколько байт становятся несколькими Кб, и это уже неприятно.
Что касается читаемости, то, на мой взгляд, при нормальном оформлении тернарного оператора, он читается лучше, чем if-else
мои соображения: читабельность; я считаю if'ы читабельнее в данном случае, а тернарный оператор, имхо, хорошо подходит для присваивания значений при не очень сложной логике, а не для вызова функций
Цитата:
С другой, вот, попадется вам какой ни будь плагин к Jquery (а большинство из них пишутся примерно в этом же стиле) и будите с ним мучиться
мучиться никто не будет
Цитата:
Смотря, что за код. Если это одноразовый код для одной странички, то мне все равно как он будет написан, я даже не думаю об этом, и в результате получается смесь разных стилей
а ТС не просил библиотеку/framework писать

мой вариант:
window.onload = function() {
    TextNode.each(function(noda) {
		var div = document.createElement( 'div' );
		div.innerHTML = noda.nodeValue.replace(/(http\:\/\/www\.youtube\.com\/watch\?v\=[0-9a-z]{11})/gi, '<a href="$1">$1</a>');
		var f = document.createDocumentFragment();
		while( div.childNodes.length )
			f.appendChild( div.childNodes[0] );
        noda.parentNode.replaceChild( f, noda );
    });
};
Ответить с цитированием
  #20 (permalink)  
Старый 08.04.2009, 13:32
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Сообщение от x-yuri
а тернарный оператор, имхо, хорошо подходит для присваивания значений при не очень сложной логике
Это не мешает ему применяться в других ситуациях.

Сообщение от x-yuri
мои соображения: читабельность
У каждого свои приоритеты.

Сообщение от x-yuri
мучиться никто не будет
Не зарекайтесь.

Сообщение от x-yuri
а ТС не просил библиотеку/framework писать
Разговор немного в сторону от темы ушел. И вы что-то друг за друга отвечаете. Прям наехали тут на меня вдвоем

Сообщение от x-yuri
мой вариант:
createDocumentFragment - классная штука. Не знал о ней.
В IE ваш вариант выдал ошибку, т. к. коллекция .childNodes, почему то стала содержать undefined элементы. Можно исправить, подправив TextNode.each.
Думаю, получается уже довольно продуманный вариант:
var TextNode = {
	each: function(callback, parent) {
		for (var childNodes = (parent || document.body).childNodes, i = 0, length = childNodes.length; i < length; i++) {
			var I = childNodes[i];
			if (I) I.nodeType == 1
				? arguments.callee(callback, I)
				: I.nodeType == 3 && callback(I, i);
		}
	}
};

window.onload = function() {
	TextNode.each(function(noda) {
		var div = document.createElement('div');
		div.innerHTML = noda.nodeValue.replace(/(http\:\/\/www\.youtube\.com\/watch\?v\=[0-9a-z]{11})/gi, '<a href="$1">$1</a>');
		if (div.firstChild && div.innerHTML != noda.nodeValue) {
			var f = document.createDocumentFragment();
			do f.appendChild(div.firstChild);
			while (div.firstChild);
			noda.parentNode.replaceChild(f, noda);
		}
	});
};


Вместо .childNodes[0] можно использовать .firstChild
Проверка if (div.firstChild && div.innerHTML != noda.nodeValue) {
очень не лишняя, т. к. без нее будут перезаписываться и те ноды, что перезаписывать не надо, ну и как следствие while меняем на do-while, чтоб не было лишней проверки в цикле.

Последний раз редактировалось Riim, 08.04.2009 в 13:50.
Ответить с цитированием
Ответ


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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Поиск в строке другой подстроки средствами JS YAN Общие вопросы Javascript 13 23.07.2013 09:41
Поиск на странице no_name jQuery 4 07.09.2010 13:26
построение XPath выражения endryha Общие вопросы Javascript 5 11.03.2009 17:00
Для чего ограничен поиск? ZoNT Сайт Javascript.ru 4 01.10.2008 15:55
Поиск в массиве через JavaScript Noran Общие вопросы Javascript 0 10.08.2008 17:31