07.04.2009, 18:22
|
|
Рассеянный профессор
|
|
Регистрация: 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.
|
|
07.04.2009, 18:33
|
|
Рассеянный профессор
|
|
Регистрация: 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);
});
};
|
|
07.04.2009, 19:55
|
|
Матрос
|
|
Регистрация: 04.04.2008
Сообщений: 6,246
|
|
Сообщение от Riim
|
Про весь документ я и не спорю, а про указанное место ты сам начал.
|
я подразумевал, что задачу наиболее правильно с моей точки зрения решать перебором всех элементов, и замены его непосредственных текстовых потомков.
я не уверен, насчет replaceChild и его кросбраузерности.
не проверял.
я лично в таком случае использовал insertBefore и removeChild
текстовые ноды могут быть не только у body-элемента.
они могут быть потомками любого тега, поэтому надо получить всю коллекцию, и для всех тегов перебрать, например
|
|
07.04.2009, 23:08
|
|
|
|
Регистрация: 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);
а еще, может, регулярное выражение можно проще сделать, но это зависит от наличия других ссылок в тексте
|
|
08.04.2009, 05:53
|
|
Рассеянный профессор
|
|
Регистрация: 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.
|
|
08.04.2009, 08:24
|
|
Рассеянный профессор
|
|
Регистрация: 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);
}
});
};
Теперь нет никаких лишних тегов.
|
|
08.04.2009, 08:29
|
|
Матрос
|
|
Регистрация: 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.
|
вы лучше в процентах посчитайте насколько код увеличивается от использования нормальных условий.
ИМХО, незначительно.
более того это можно было бы назвать преждевременной оптимизацией, и потому подход этот вреден.
вам тернарный оператор нормально читается, а большинству нет.
то есть ваш подход приемлим, только если вы в одиночку пишите жестко инкапсулированый код, которй предполагаете никто кроме вас дорабатывать не должен.
|
|
08.04.2009, 10:33
|
|
Рассеянный профессор
|
|
Регистрация: 06.04.2009
Сообщений: 2,379
|
|
Можно аргументировать. Возможно, у innerHTML действительно есть какие-то минусы, о которых я не знаю. И еще, в последнем, приведенном мною, коде (12:24) innerHTML тоже используется. Может, перепишете его без innerHTML. Интересно как это у вас получится. То есть я не говорю, что этого нельзя сделать, только вот кода на первый взгляд должно получиться раза в 3 больше, а о его производительности вообще лучше не думать.
Сообщение от Gvozd
|
вы лучше в процентах посчитайте насколько код увеличивается от использования нормальных условий.
|
Я считал. И не раз. Уменьшать код можно не только за счет тернарного оператора. Есть множество других способов.
У меня код уменьшается минимум на 15%. Думаете, я преувеличиваю? Нет, потому что на результат можно по-разному смотреть. Я, например, смотрю на него после работы YUICompressor-а. Считайте сами, каждая локальная переменная, например "parentNode", становиться одной буквой, то есть "parentNode" уменьшиться в 10 раз. В результате объем операторов в коде, в процентах, становиться довольно значительным и экономить на них уже довольно выгодно.
Сообщение от Gvozd
|
вам тернарный оператор нормально читается, а большинству нет
|
С одной стороны на вкус и цвет....
С другой, вот, попадется вам какой ни будь плагин к Jquery (а большинство из них пишутся примерно в этом же стиле) и будите с ним мучиться. У меня с этим проблем нет т. к. свободно воспринимаю самые разные стили.
Сообщение от Gvozd
|
если вы в одиночку пишите
|
Сообщение от Gvozd
|
никто кроме вас дорабатывать не должен
|
Смотря, что за код. Если это одноразовый код для одной странички, то мне все равно как он будет написан, я даже не думаю об этом, и в результате получается смесь разных стилей. Если мне скажут писать в таком то определенном стиле, то я и спорить не буду. А вот универсальный код, который выносится в отдельный файл, должен изначально писаться максимально качественно, так чтобы его доработка в идеале не потребовалась. И писаться он должен именно одним человеком. А остальные на его основе пишут одноразовые коды, и им должно быть все равно как написана основа, главное, что бы документация обновлялась вовремя.
|
|
08.04.2009, 13:02
|
|
|
|
Регистрация: 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 );
});
};
|
|
08.04.2009, 13:32
|
|
Рассеянный профессор
|
|
Регистрация: 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.
|
|
|
|