суббота, 30 июня 2007 г.

Знакомство с JavaScript

Недавно, в моей практике, случилось мне писать небольшой сайтик... Писал я его на ASP.NET, но это не важно... т.к. проблемы начались, когда дело дошло до JavaScript...
Перво наперво, пришлось долго искать описание объектной модели документа, благо в MSDN она описана... Ух ты, как хорошо все написано... было подумал я... и быстренько набросал метод (еще и при дополнительной помощи моего знакомого), суть которого заключалась в следующем: есть табличка, в этой табличке есть строчки, в каждой строчке есть несколько столбцов, в одном из которых есть поле ввода textarea, а в другом есть checkbox... А надо сделать следующее: если в textarea набрали текст длинее 5 символов, то соответствующая строчка начинает подсвечиваться желтеньким цветом, а на checkbox ставится галочка, если меньше 5 символом, то подсвечивается другим цветом, и галочка на checkbox снимается...
В итоге получилось, что то вроде:

if (obj.innerText.length < 5)
{
obj.parentNode.parentNode.parentNode.
style.backgroundColor = 'AliceBlue';
obj.parentNode.parentNode.parentNode.
childNodes[2].childNodes[0].childNodes[0].chaecked = false;
}
else
{
obj.parentNode.parentNode.parentNode.
style.backgroundColor = 'LemonChiffon';
obj.parentNode.parentNode.parentNode.
childNodes[2].childNodes[0].childNodes[0].chaecked = true;
}

Где obj - это наш textarea, obj.parentNode.parentNode.parentNode - это наша строчка, ну а obj.parentNode.parentNode.parentNode. childNodes[2].childNodes[0].childNodes[0] - это наш checkbox..., который на самом деле находится просто в span, а до этого еще и во второй колонке. Запускаем, все работает, отлично! Запускаем в Firefox... не работает... На помощь приходит плагин firebug... Ставим, начинаем дебажить... Перво наперво, выясняется, что textarea в firefox java не содержит поля innerText, зато у него есть поле value, которого нет в IE... дык... надо найти что то общее... обращаем внимание на поле textLength, которое сразу же указывает нам на длину текста... есть ли оно в IE? Наверное нам это было уже не интересно, главное, что не value... Переправили, запускаем... работает, но не полностью, цвет меняет, а галочку не ставит... Почему?... дебажим...
obj.parentNode.parentNode.parentNode.childNodes[2] - колонка, так и должно быть... а obj.parentNode.parentNode.parentNode. childNodes[2].childNodes[0] это не span... странно... ага, индексы в firefox почему то другие... и их больше:) Ах, так она еще и переводы строки считает... Подгоняем индексы, что бы проверить - будет ли вообще это работать? Получаем:

obj.parentNode.parentNode.parentNode.
childNodes[3].childNodes[1].childNodes[0]

заместо

obj.parentNode.parentNode.parentNode.
childNodes[2].childNodes[0].childNodes[0]

самое плачевное... что где то индексы совпадают, а где то нет... Но! Русские не сдаются:)
Было решено писать супер пупер мега метод, который в потомках рекурсивно будет искать определенный объект, в нашем случае это input с типом checkbox, благо во всей строчке он такой один (почему именно этот путь? Ну что первое в голову пришло...)
В итоге получаем метод:

function GetCheck(Obj)
{
for (i=0;i < Obj.childNodes.length; i++)
{
if (Obj.childNodes[i].tagName == 'INPUT' &&
Obj.childNodes[i].type == 'checkbox')
return Obj.childNodes[i];
else
{
Res = GetCheck(Obj.childNodes[i]);
if (Res != null)
return Res;
}
}
}

Круто! Запускаем... зациклились... Рекурсия - смотри рекурсия... Почему это функция бегает все время по одним и тем же нодам... нам понять удалось не сразу... по всей видимости сказалось то, что перейти на javascript сразу после кода на C# не так легко... а ведь ошибка крылась в какой то переменой, коей оказалась i... Ну да... локальные, глобальные... в общем, она была одна на все рекурсивные функции... проблема была решена добавлением следующей строчки:
var i = 0;

Круто! Запускаем, работает... галку мы нашли... теперь осталось ее проставить или убрать, в итоге получаем следующий метод:


function TextChange(obj)
{
var SranaGalka;
function GetCheck(Obj)
{
var i = 0;
for (;i < Obj.childNodes.length; i++)
{
if (Obj.childNodes[i].tagName == 'INPUT' &&
Obj.childNodes[i].type == 'checkbox')
return Obj.childNodes[i];
else
{
Res = GetCheck(Obj.childNodes[i]);
if (Res != null)
return Res;
}
}
}
SranaGalka = GetCheck(obj.parentNode.parentNode.parentNode);
if (obj.textLength < 5)
{
obj.parentNode.parentNode.parentNode.
style.backgroundColor = 'AliceBlue';
SranaGalka.checked=false;
}
else
{
obj.parentNode.parentNode.parentNode.
style.backgroundColor = 'LemonChiffon';
SranaGalka.checked=true;
}
}

Который, кстати, работает в Firefox! Запускаем Opera... не работает, даже цвет не меняет... обидно... ладно, отдебажить в опере нечем, переходим к IE - запускаем... цвет меняется, галка ставится... но когда надо снять выделение... цвет не меняется, галка не ставится... неужели код, который в else не работает?? он же такой же... вроде как... дебажим, уже в студии (кстати, отдельная история)... obj.textLength - undefined... а как ни странно, но undefined > 5 равно истине... да... но зато мы знаем, что в IE точно работает obj.innerText.length, который не работает в firefox - как быть? Как, как... танцевать с бубном и придумывать следующую строчку:


Length = obj.textLength==null?
obj.innerText.length : obj.textLength;

и неужели эта строчка определяет, какой у вас браузер, и вызывает соответствующее свойство? Конечно, а вы как думали...
В итоге получаем:

function TextChange(obj)
{
var SranaGalka;
function GetCheck(Obj)
{
var i = 0;
for (;i < Obj.childNodes.length; i++)
{
if (Obj.childNodes[i].tagName == 'INPUT' &&
Obj.childNodes[i].type == 'checkbox')
return Obj.childNodes[i];
else
{
Res = GetCheck(Obj.childNodes[i]);
if (Res != null)
return Res;
}
}
}
SranaGalka = GetCheck(obj.parentNode.parentNode.parentNode);
Length = obj.textLength==null?
obj.innerText.length:obj.textLength;
if (Length < 5)
{
obj.parentNode.parentNode.parentNode.
style.backgroundColor = 'AliceBlue';
SranaGalka.checked=false;
}
else
{
obj.parentNode.parentNode.parentNode.
style.backgroundColor = 'LemonChiffon';
SranaGalka.checked=true;
}
}

Запускаем... IE - работает... Firefox - работает... осталось самое страшное - Opera, ведь в ней мы никак не сможем отдебажить... но... о чудо! и там работает:) По всей видимости, в Opera null не может сравниваться с числом, в связи с чем скрипт просто переставал выполняться.... Ну да ладно, самое главное, что все работает, и на все это ушло всего навсего часа 4 с небольшим... Зато какой супер пупер мега метод то получился, и никакая SranaGalka нам теперь не помеха:) И даже не напоминайте нам про Safari и что то другое;)
P.S. Да, быть может, можно легче... но уже проехали;)

суббота, 23 июня 2007 г.

Ддввооййнныыее ррууссккииее ббууккввыы

Недавно обнаружился странный глюк в любимой мной лесичке (Firefox aka FF)... Странность его заключалось в неожиданности появления (может появиться через 2 часа работы), а так же в его непостоянстве. Ну а заключался он в том, что при наборе русского текста, каждая набранная буква повторялась дважды (английским как всегда по барабану)... иногда проблеме помогал перезапуск браузера... не иногда не помогал :(
После недолгих поисков выяснилось, что сие чудо случается далеко не у всех, но если начинает появляться... то делает это внезапно! и непредсказуемо, а самое главное, после появления не уходит... Суппорт любимого браузера разводит руками и с сожалением говорит, что как он ни старается, никак не может повторить этот забавный глюк на своих машинах...
Тем временем похожие симптомы начинают проявляться и в других приложениях пользователей... Например, некоторые пользователи ноутбуков жалуются на то, что в их Open Office так же иногда проявляется симптом двойных русских букв... Позже к ним присоединились и пользователи обычных ПК ;)
Есть ли связь между этими событиями, или это разные глюки в разных программах?... Единственным нюансом во всей этой истории оказалось то, что страдают от этого только пользователи ОС Windows... В подозрение попал сам Билл Гейтс :-x
Тем не менее, некоторые пользователи начали находить решение из сложившейся ситуации... Пользователи Open Office дружно переустанавливали драйвера на свою клавиатуру... жаль это помогало не всем... в том числе это не помогало пользователям FF...
Но, как выяснилось позже, пользователи FF обладают большим потенциалом в решении проблемы, ведь их любимый FF поддерживает плагины... Если быть точнее, то спасением для них оказался плагин "IETab" (опять чувствуется причастность мелкомягких)... После установки этого плагина, симптомы двойных русских букв могли исчезнуть... если же глюк пытался проявиться снова, то достаточно было открыть еще одну вкладку, но в режиме IETab... "Суппорт" FF в недоумении разводит руками, и до сих пор считает, что пользователи сами выдумали проблему...