Отладка сайтов под IE всегда была для меня пугающим занятием. Причем проблемы с версткой хотя бы можно отслеживать по внешнему виду сайта, а вот ошибки в скриптах IE показывает весьма эзотерически.
Во-первых, где взять нужную версию Internet Explorer? Есть два пути – использовать мутантский набор движков типа IETester или IECollection, или развернуть несколько виртуальных машин под каждую нужную версию Internet Explorer. Первый путь мне никогда не нравился, хотя бы из-за кучи проблем с совместимостью и потенциально неверного отображения сайтов в разных версиях.
Потому будем настраивать виртуалки. К счастью, достаточно настроить только первую – остальные можно наклонировать.
Создаем виртуальную машину IE6. Ей нужен будет диск размером 2G и порядка 512 мегабайт памяти. Еще ей нужны будут два сетевых адаптера – NAT и Host-Only – первый послужит для выхода в интернет, второй – для связи с хостом (и, если сервер на другой виртуальной машине, с сервером).
Находим образ Windows XP Home SP3. Замечу, что SP3 не обновляет IE6 до IE7 самостоятельно.
Убираем все лишнее из установки. Если места на диске не жалко, можно обойтись и без этого шага.
Скачиваем nLite -инструмент для пересборки образов XP.
Скачиваем мой конфиг к nLite – он вырежет из образа все, кроме необходимого.
Прогоняем распакованный образ через nLite, получаем ISO размером порядка 200 мегабайт.
Подключаем образ к виртуалке, устанавливаем Windows – тут ничего особенного.
Подключаем к виртуалке образ VirtualBox Guest Additions, чтоб получить разделенный с хостом буфер обмена, курсор, возможность растягивать окно-экран виртуалки и т.п. удобства.
Ставим Adobe Flash Player, Java Runtime, Notepad++ для просмотра исходников.
По желанию ставим на виртуалку какой-нибудь CCleaner, чтоб поубирать мусор.
Базовая виртуалка готова. Можно ее выключить, а образ диска запаковать в архив и отложить – может, пригодится когда-нибудь.
Клонируем образ (обычным копированием тут не обойтись):
Создаем новую виртуалку, IE7, с теми же настройками, подключаем к ней склонированный образ. Рекомендую указать статический IP для Host-only соединения (в виртуалке это LAN Connection 2) – естественно, на каждой виртуалке разный. Помимо этого я в c:\windows\system32\drivers\etc\hosts указываю домен для сервера.
На виртуалку для IE7 скачиваем и устанавливаем IE7.
Готово!
Инструментарий
Для адекватной отладки яваскрипта нужно установить Script Debugger (ну и пусть говорят, что он устарел – альтернатив нет), а потом CompanionJS. И еще отключаем Disable JS Debugging на вкладке Advanced настроек IE (хитрая такая опция). Получаем некое подобие Firebug.
Можно поставить и другие инструменты, хотя бы IE Developer Toolbar для отладки верстки.
Вот и все – имеем работающий IE, независимый от базовой ОС, с возможностью удобно отлаживать скрипты.
Я последнее время практически не бываю на Хабре, зато часто захожу на Reddit. По-моему на последнем гораздо удобнее читать комментарии, в первую очередь потому, что их можно отсортировать по рейтингу и читать только
наиболее «ценные».
Так вот. Сел и написал юзерскрипт, который делает просмотр комментариев на Хабре более удобным.
Комментарии сортируются по рейтингу (в пределах одного уровня).
Ветки комментариев можно сворачивать и разворачивать нажатием на ссылку [-] в заголовке коммента.
Ник автора подсвечивается синим и отмечается буквой [S].
Из этого следует, что глобальные переменные могут затирать свойства window (я уже молчу о том, что они зло, нарушают инкапсуляцию и все такое).
Объявление переменных
При присвоении значения неопределенной локальной переменной используется или создается глобальная переменная.
function foo(){
a =2;
b =3;return a+b;}alert(a);// undefined
a ='очень важное значение';alert(a);// очень важное значение
foo();alert(a);// 2
Таким образом можно легко затереть лишнего. По-моему такое поведение абсолютно нелогично, но, что ж, это не самое странное место яваскрипта. В любом случае неявного определения переменных стоит избегать.
Явно объявлять переменные можно и нужно ключевым словом var.
var a =2;
Такая строка всегда создает новую локальную переменную. Если объявление происходит вне функций, то она будет глобальной, что вполне логично.
function foo(){var a =2;var b =3;return a+b;}alert(a);// undefinedvar a ='очень важное значение';alert(a);// очень важное значение
foo();alert(a);// очень важное значение
Как объявить глобальную переменную из функции? Как обратиться к глобальной переменной, если есть локальная с таким же именем? Очень просто – нужно обратиться к ней как к свойству window:
function foo(){var location ='location';alert(location);// вернет 'location'alert(window.location);// вернет window.location
window.a='переменная из функции';}alert(a);// undefined
foo();alert(a);// переменная из функции
Наследование области видимости
Меня всегда смущало то, что в Javascript можно определять функции внутри функций, а использовать их потом где угодно. Ну да, если посмотреть, точно то же самое можно делать в Ruby, и, наверное, во многих других языках тоже.
Переменные при этом передаются очень просто: если на момент определения функции переменная существовала, то она будет существовать и внутри функции. Откуда бы ее не вызывали.
function alertOnTimeout(message, timeout){return setTimeout(function(){// message будет доступен в безымянной функции, переданной таймаутуalert(message);}, timeout);}
Передача кода по старинке – строкой, которая прогоняется через eval() – не попадает под это правило, код исполняется в той области видимости, где и определен.
Поскольку объекты в Javascript – это тоже типа функции, то свойство объекта определяется точно так же, как и переменная.
function myObject(){var property =0;// Cамо собой, property будет доступно только внутри объекта.}
А еще в Javascript область видимости переменной ограничивается только функциями, а не блоками типа if (привет, Паскаль). Потому удобнее всего объявлять переменные в начале функции.
this
А что this? А то, что эта переменная автоматически появляется в методах объектов и затирает значение this из предыдущей области видимости. Решение простое – переприсваивать ее значение другой переменной.
$('div.with-links').click(function(){var theDiv =this;//сохраняем значение this
$(this).find('a').click(function(){alert($(this).attr('href'));// this - это ссылка
theDiv.remove();// а theDiv - это все еще дивак});});
Отдельно замечу, что при оборачивании какой-то поведенческой логики в объект надо помнить, что в создаваемых DOM-событиях значение this самого объекта теряется.
function myObject(){var _this =this;// сохраняем ссылку на родительский объектvar linkRemoved =false;
$('a').click(function(){
$(this).remove();// this - это объект ссылки
_this.linkRemoved=true;// _this - это родительский объект});}
Решил опубликовать пару скриптов, написанных для lyrified.com.
Итак, растяжка <TEXTAREA> по вертикали. Вообще-то, растяжка любого блочного элемента по вертикали, но применялась именно для текстовых полей.
Проблема: текстовые поля, как правило, или слишком большие, или слишком маленькие. И то, и другое неудобно. Хорошо бы дать возможность изменить высоту поля
Это выглядит вот так:
Тестировалось в IE 6, 7, Firefox 2, 3, Opera 9, Safari 2. читать дальше →