29.12.2008

JS: image.onload

Делал прелоадилку картинок и столкнулся с проблемой — в Опере у картинки иногда не срабатывал обработчик события onload.

Оказалось, проблема была в том, что я сначала задавал src и потом навешивал обработчик onload, а нужно делать наоборот. Причина проста: если картинка находится в кэше, то в Опере после задания src она загружается мгновенно, и событие onload срабатывает еще до того, как мы навесили обработчик onload.

Я наблюдал этот эффект только в Опере, хотя не исключаю, что может проявиться и в других браузерах.

Правильный код:

var image = document.createElement('img');
image.onload = function () {
    // вызывается всегда
    alert('image loaded');
};
image.src = 'test.jpg';

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

11.11.2008

Книги по JavaScript

За последние пару лет появилось много хороших книг по яваскрипту, что не может не радовать. Еще совсем недавно можно было посоветовать только «наименее плохую» книгу (Флэнагана). Сегодня же я могу порекомендовать вам три отличные книги.

John Resig
Pro JavaScript Techniques
Книга недавно вышла на русском языке

Джон Ресиг (JavaScript-евангелист в Mozilla Corporation и автор библиотеки jQuery) в своей книге рассказывает об объектно-ориентированном JavaScript, написании кода для повторного использования, тестировании и отладке, DOM, Events, Ajax.

К сожалению, в книге невероятно много опечаток, в том числе в примерах кода, что особенно неприятно. Также не понравилось, что иногда вместо подробного объяснения какой-либо темы, Ресиг приводит ссылки на статьи в интернете (на того же Крокфорда) где эта тема раскрыта. Я люблю уютно устроиться долгим зимним вечером в обнимку с книгой, и хочу чтобы книга была самодостаточна, чтобы не нужно было ползти за ноутбуком.

Оценка: 4

Не смотря на эти недостатки, я собираюсь заказать следующую книгу Ресига — Secrets of the JavaScript Ninja, выход которой запланирован на конец 2008 года. Оглавление выглядит впечатляюще и многообещающе.

Douglas Crockford
JavaScript: The Good Parts

Дуглас Крокфорд (главный по JavaScript в Yahoo!) хорошо известен как один из самых крутых специалистов по JavaScript. Дуглас — автор формата обмена данными JSON и сервиса по проверке корректности кода JSLint. Надо сказать, что его мегамощные лекции и статьи меня реально торкнули, поэтому его книгу я ждал с особым нетерпением.

Книга невелика по объему (всего 145 страниц), но насыщена информацией. Крокфорд пишет просто и понятно, без многословных и замысловатых выражений. Я не всегда стопроцентно с ним согласен, тем не менее, его аргументы весьма разумны, а его мнение стоит того, чтобы к нему прислушаться.

Что мне особенно понравилось в книге Крокфорда (а также в JSLint) — это внимание к стилю написания кода, как сделать код максимально ясным, кратким, однозначным, как уменьшить шанс возникновения ошибок.

Оценка: 5, must read

Ross Harmes, Dustin Diaz
Pro JavaScript Design Patterns

Супермегаохуенная книга о применении паттернов проектирования в JavaScript. Я давно мечтал прочитать такую. Организация кода, уменьшение зависимостей компонентов, как сделать код более гибким — вот главные темы книги.

Очень понравилось как авторы четко расставляют все по полочкам — для каждого паттерна приведены за и против его использования, какой выигрыш паттерн может дать, и в чем при этом можно потерять.

Оценка: 5+, must read

01.11.2008

Типовой лейаут страницы

Особенности:

  • Standards mode
  • Минимальная и максимальная ширина
  • При растяжении больше максимальной ширины макет центрируется
  • Футер всегда прибит к низу страницы

Тестовая страница

Простой пример использования

index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
    <head>
        <title>Sample layout</title>
        <link rel="stylesheet" type="text/css" href="main.css"/>
        <!--[if lte IE 6]><link rel="stylesheet" type="text/css" href="main-ie6.css"/><![endif]-->
    </head>
    <body>
        <div id="outer">
            <div id="header">header</div>
            <div id="content">content</div>
        </div>
        <div id="footer">footer</div>
    </body>
</html>

main.css

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
}

body {
    color: #000;
    background-color: #fff;
    font-family: Arial, sans-serif;
    font-size: 0.8em;
    line-height: 1.4;
    text-align: center;
}

#outer {
    min-height: 100%;
}

#outer,
#footer {
    min-width: 700px;
    max-width: 1400px;
    margin: auto; /* center it */
    text-align: left;
}

#header {
    background-color: #66cc66;
}

#content {
    padding-bottom: 3.2em;
}

#footer {
    height: 2.6em;
    margin-top: -2.6em;
    background-color: #ff8080;
}

main-ie6.css

#outer {
    height: 100%;
}

#outer,
#footer {
    width: expression(document.documentElement.clientWidth < 700 ? '700px' : document.documentElement.clientWidth < 1400 ? '100%' : '1400px');
}

19.10.2008

Новый iepngfix.htc

Наверняка многие из вас пользовались популярным скриптом iepngfix.htc, который исправляет полупрозрачные PNG в IE 6. Скрипт умеет фиксить как PNG-изображения <img>, так и PNG заданные бекграундом. Основным недостатком этого инструмента было отсутствие поддержки background-position и background-repeat — эти параметры игнорировались. К счастью, Angus Turnbull, автор iepngfix, недавно выпустил новую версию v2.0 Alpha 3, лишенную этого недостатка. В новой версии добавился еще один файл iepngfix_tilebg.js, в котором находится метод IEPNGFix.tileBG.

UPD. Коллега наткнулся на еще одну JS-библиотеку для исправления полупрозрачных PNG в IE 6 — DD_belatedPNG. Также есть поддержка background-position и background-repeat, но подход принципиально другой: вообще отказ от AlphaImageLoader и вместо этого использование VML.

12.10.2008

XSL: применение шаблона с «внутренним» условием

Часто бывает нужно применить шаблон для элемента только если этот элемент (или его содержимое) удовлетворяет некоторому условию. Простой пример: применить шаблон для элемента <Brands> если внутри есть хотя бы один элемент <Brand>. Рассмотрим несколько вариантов как можно сделать эту проверку.

Вариант 1

<xsl:template match="Something">
    <xsl:if test="Brands/Brand">
        <xsl:apply-templates select="Brands"/>
    </xsl:if>
</xsl:template>

<xsl:template match="Brands">
    <h2>Производители</h2>
    <ul>
        <xsl:apply-templates select="Brand"/>
    </ul>
</xsl:template>

Неудачное решение, поскольку, написав проверку в шаблоне для <Something>, мы поместили в этот шаблон знание об особенности трансформации <Brands>.

Вариант 2

<xsl:template match="Something">
    <xsl:apply-templates select="Brands[Brand]"/>
</xsl:template>

<xsl:template match="Brands">
    <h2>Производители</h2>
    <ul>
        <xsl:apply-templates select="Brand"/>
    </ul>
</xsl:template>

Немного компактнее, но проблема первого варианта осталась.

Вариант 3

<xsl:template match="Something">
    <xsl:apply-templates select="Brands"/>
</xsl:template>

<xsl:template match="Brands">
    <xsl:if test="Brand">
        <h2>Производители</h2>
        <ul>
            <xsl:apply-templates select="Brand"/>
        </ul>
    </xsl:if>
</xsl:template>

Гораздо лучше. Шаблон для <Something> просто вызывает шаблон для <Brands>, не заморачиваясь о внутреннем устройстве <Brands>. Шаблон для <Brands> сам разбирается как трансформировать <Brands>.

Вариант 4

<xsl:template match="Something">
    <xsl:apply-templates select="Brands"/>
</xsl:template>

<xsl:template match="Brands"/>
<xsl:template match="Brands[Brand]">
    <h2>Производители</h2>
    <ul>
        <xsl:apply-templates select="Brand"/>
    </ul>
</xsl:template>

Я предпочитаю этот вариант. Он также хорошо работает и в случае с несколькими условиями — вместо громоздкого <xsl:choose> мы получаем компактные шаблончики.

<xsl:template match="Brands"/>

<xsl:template match="Brands[Brand]">
    <h2>Производители</h2>
    <ul>
        <xsl:apply-templates select="Brand"/>
    </ul>
</xsl:template>

<xsl:template match="Brands[count(Brand) > 10]">
    <h2>Много производителей</h2>
    <!-- Выводим бренды в три колонки -->
</xsl:template>

24.09.2008

Ссылка цветом текста

Задача: сделать ссылки цветом текста. При этом в разных блоках на странице цвет текста может меняться.

Сначала я указал цвет ссылки отдельно для каждого блока.

body {color: black;}
a.glossary {color: black;}
#shurum, #shurum a.glossary {color: red;}
#burum, #burum a.glossary {color: green;}

Потом я подумал, что ведь цвет ссылки можно наследовать от блока.

body {color: black;}
a.glossary {color: inherit;}
#shurum {color: red;}
#burum {color: green;}

Радости моей не было предела, пока я не открыл страницу в IE. Фак! Оба осла (6 и 7) не поддержали мою гениальную задумку и ни хрена не пронаследовали цвет. Тогда я достал большую базуку и замочил IE вдребезги пополам написал маленький экспрешн.

a.glossary {color: expression(this.parentNode.currentStyle.color);}

Лучше, конечно, написать одноразовый экспрешн (не стал здесь так делать для наглядности).

15.09.2008

IE 6 занял место Netscape 4

Лет 6—7 назад все ненавидели Netscape 4. Чтобы добиться нормального отображения страницы в Netscape 4, верстали исключительно таблицами, делали распорки, а о семантической верстке не шло и речи. Как только его не обзывали — Нетшкаф, Нетглюк, Нафигатор. Но постепенно сайты отказывались от A-grade поддержки Netscape 4. Я помню этот радостный момент, когда Студия объявила о прекращении полноценной поддержки Netscape 4 — все технологи со слезами на глазах обнялись и поздравили друг друга.

Сейчас место «браузера-изгоя тормозящего развитие веба» занял IE 6. Хотя говорить о прекращении A-grade поддержки IE 6 еще рано (думаю, придется еще пару лет с шестым ослом помучиться), тенденция к этому уже наметилась — все чаще встречаются сайты где что-то отвалилось или разъехалось в IE 6.

Ссылка по теме: Graded Browser Support

01.09.2008

JavaScript: область видимости переменных

В JavaScript область видимости переменных не ограничивается блоком {}, а ограничивается только функцией. Например, переменные объявленные внутри for или if продолжают жить после того, как эти for и if отработали.

for (var i = 0; i < 10; i += 1) {
    var a = i * i;
    // do something
}
document.writeln(i);    // 10
document.writeln(a);    // 81

if (true) {
    var b = "test";
    // do something
}
document.writeln(b);    // test


Поэтому, лучше явно обозначить это в коде.

var i, a;
for (i = 0; i < 10; i += 1) {
    a = i * i;
    // do something
}

var b;
if (true) {
    b = "test";
    // do something
}


Во многих языках программирования рекомендуется объявлять переменные как можно ближе к месту первого использования. В JavaScript все используемые в функции локальные переменные лучше объявлять в самом начале функции.

var myFunction = function () {
    // Объявление всех локальных переменных, включая переменные циклов
    // Код функции
}

04.08.2008

Простое правило для маргинов

При задании отступов у блоков я придерживаюсь простого правила — задаю отступы справа и снизу.

Если первый блок будет вдруг отсутствовать, второй блок прижмется к левой/верхней границе.

Если задавать отступы наоборот, слева и сверху, тогда второй блок не прижмется к границе как хотелось бы.

Это правило позволяет уменьшить зависимость блоков от окружения, то есть повышает универсальность верстки.

02.08.2008

Элементы с id порождают глобальные переменные в JS

Для всех элементов с атрибутом id в джавасрипте создается глобальная переменная. Следующий пример во всех браузерах выдаст алерт с "DIV".

<html>
<head>
    <script>
        window.onload = function () {
            alert(myDiv.tagName);
        };
    </script>
</head>
<body>
    <div id="myDiv">test</div>
</body>
</html>

Это плохо, но в принципе не страшно, если вы:

  • Избегаете создавать свои глобальные переменные.
  • Не забываете объявлять свои переменные. Если вы забыли объявить переменную (var myVar), то джавасрипт считает, что это глобальная переменная (implied global variable).

04.07.2008

Названия картинок

Советую не использовать в названии обычных картинок слова banner, promo и ad. У многих пользователей стоят блокировщики рекламы (например Adblock), которые не показывают такие картинки. Кстати, веб-разработчику не помешает проверять свои сайты в браузере с установленным блокировщиком рекламы.

Названия баннеров, наоборот, нужно честно начинать со слова banner, чтобы их не видели те, кто не хочет их видеть.

30.06.2008

JavaScript + CSS

Задача: Подружить JavaScript и CSS, чтобы при отсутствии JavaScript применялись немного другие стили.

Предположим, что у нас есть блок <div id="block">блок</div>, который изначально должен быть скрыт и появляться по нажатию на псевдоссылку <span id="link">псевдоссылка</span>. Если же джаваскрипта нет, то блок должен показаться сразу, а псевдоссылка спрятаться с глаз долой.

Вариант 1. С использованием тега <noscript> (олд скул)

<style type="text/css">
    #block {display: none;}
</style>

<noscript>
    <style type="text/css">
        #block {display: block;}
        #link {display: none;}
    </style>
</noscript>

Это работает, но приходится создавать отдельный кусок стилей. К тому же валидатор ругается что есть сил, поскольку <style> запрещен внутри <noscript>, а <noscript> запрещен внутри <head>. Плохой способ, не рекомендую так делать.

Вариант 2.

Гораздо лучше пойти по пути последовательного улучшения (progressive enhancement), суть которого заключается в том, что сначала мы добиваемся корректной работы в самом простом, доступном окружении (в данном случае — в браузере с неработающим джаваскриптом), а затем постепенно улучшаем наше решение, добавляя функционал для повышения удобства пользователей в браузерах поддерживающих этот функционал.

Это означает, что стили изначально должны быть настроены для случая отсутствия джаваскрипта. Далее загружается джаваскрипт, находит наш блок и скрывает его, находит псевдоссылку и показывает ее. Недостаток такого решения в том, что блок может «моргать» — пользователь может увидеть его на какое-то короткое время (пока загружается и выполняется джаваскрипт).

Вариант 3.

Как можно побороть моргание блока? Я использую такое решение. В теге <head> добавляем простую строчку:

<script type="text/javascript">document.documentElement.className = "js";</script>

Если джаваскрипт включен, элементу <html> присвоится класс js. Что важно, это произойдет до загрузки контента. Теперь можно написать такие стили:

#link {display: none;}

.js #link {display: inline;}
.js #block {display: none;}

16.06.2008

Ретрахинг кода (refucktoring)

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

Keyboard navigation

Некоторым людям (особенно с двигательными расстройствами) сложно пользоваться мышью для просмотра веб-страниц. Вместо мыши они используют предоставляемую браузерами клавиатурную навигацию при помощи клавиши Tab. Добавляя на страницу JavaScript, нужно подумать об этих людях и предусмотреть навигацию с помощью клавиатуры.

По-хорошему, для каждого обработчика действия мышью должен быть соответствующий обработчик для клавиатуры. Например, если есть обработчик события onclick, по идее, нужен и обработчик для onkeydown.

Код на jQuery:

$("#test").click(function () {
    doSomething();
});
$("#test").keydown(function (event) {
    // Allow the Enter key to activate that element
    return event.keyCode != 13 || doSomething();
});

Далее, хорошо бы прописать стили для псевдокласса :focus. Хотя бы такие же, как и для :hover.

#test:hover,
#test:focus {color: #cc0000;}

Чтобы также ховерилось и фокусировалось в IE, нужно навесить обработчики для событий onmouseover/onfocus и onmouseout/onblur в которых, соответственно, нужно добавлять и убирать какой-нибудь класс.

Все круто, но с помощью таба можно пройтись только по ссылкам и элементам форм. Другие элементы по умолчанию не получают фокус. Что делать, если активный элемент, на который мы навесили onclick и onkeydown, не ссылка, а <span>?

Для этого существует атрибут tabindex.

tabindex="0" — разрешает элементу получать фокус в порядке в котором он идет в документе.

tabindex="5" — положительное значение позволяет изменить порядок получения фокуса элементом при навигации табом.

tabindex="-1" — отрицательное значение исключает элемент из навигации табом.

Проверил, работает в IE и Firefox. Опера и Сафари, к сожалению, вообще пока не поддерживают навигацию табом.

Пример клавиатурной навигации: ездилка на сайте вакансий Евросети.

P. S. Кстати, а знаете ли вы, что Shift + Tab перемещает фокус в обратном порядке?

15.06.2008

Резюме в виде облака

Наткнулся на забавный онлайн-сервис: Wordle — генератор красивых облаков из слов. Запостил в эту штуку свое резюме:

07.06.2008

Крокфорд жжет

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

Другое дело — книга Дугласа Крокфорда «JavaScript: The Good Parts». Душа радуется!

Пример вложенного объекта:

var flight = {
    airline: "Oceanic",
    number: 815,
    departure: {
        IATA: "SYD",
        time: "2004-09-22 14:55",
        city: "Sydney"
    },
    arrival: {
        IATA: "LAX",
        time: "2004-09-23 10:42",
        city: "Los Angeles"
    }
};

Пример добавления метода у массива:

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};

Array.method('reduce', function (f, value) {
    var i;
    for (i = 0; i < this.length; i += 1) {
        value = f(this[i], value);
    }
    return value;
});

...

// Create an array of numbers.

var data = [4, 8, 15, 16, 23, 42];

// Define two simple functions. One will add two
// numbers. The other will multiply two numbers.

var add = function (a, b) {
    return a + b;
};

var mult = function (a, b) {
    return a * b;
};

// Invoke the data's reduce method, passing in the
// add function.

var sum = data.reduce(add, 0); // sum is 108

// Invoke the reduce method again, this time passing
// in the multiply function.

var product = data.reduce(mult, 1); // product is 7418880

Только недавно досмотрел второй сезон. Я не тормоз, просто смакую :)

06.06.2008

Developers, developers, developers!

В IEBlog проскочило упоминание, что, начиная с момента выпуска IE8 Beta 1, было сделано более двух миллионов скачиваний. Первая бета была адресована разработчикам и, я уверен, что большинство скачавших так или иначе занимаются сайтостроением. То есть можно прикинуть, что в мире порядка двух миллионов веб-разработчиков!

31.05.2008

Браузеры на моем десктопе

Еще в виртуальной машине есть IE 8 Beta 1 и Firefox 2, плюс в стареньком G4 Cube живут маковские Safari и Firefox.

Третий Firefox пока не ставил и не щупал (что-то я туплю на самом деле, надо поставить). И для полного счастья еще не хватает Konqueror (надо бы тоже на досуге поставить).

Вообще я стараюсь повседневно использовать более старые браузеры и не ставить последние версии как основные. Например, я был последним из могикан в Студии у которого дефолтный IE был версии 5.5.

29.05.2008

Скажи мне, какой у тебя браузер

Изучал тут статистику использования браузеров за май 2008 года...

Сайт нашей Студии

Firefox 43,58% тыдыщ
IE 6.0 17,56%
IE 7.0 14,37%
Opera 9.x 18,36%
...
IE 5.0 0,55%
IE 5.5 0,07%

Сайт банка

IE 6.0 47,37% тыдыщ
IE 7.0 30,72%
Firefox 10,64%
Opera 9.x 8,45%
...
IE 5.0 0,33%
IE 5.5 0,12%
IE 4.0 0,09% фигасе

Интернет-магазин

IE 6.0 30,89%
IE 7.0 25,61%
Opera 9.x 25,46% тыдыщ
Firefox 14,91%
...
IE 5.5 0,07%

Можно сделать несколько интересных выводов. Во-первых, видно, что статистика использования браузеров сильно зависит от сайта. Статистику, которую обычно предлагают нам всякие «исследования аудитории Рунета» можно назвать средней температурой по палате.

На сайте Студии зашкаливает Firefox. Ну оно и понятно. Кто ходит на сайт Студии? Веб-дизайнеры, веб-разработчики и прочие веб-интересующиеся — «продвинутые» ребята, использующие «правильный» браузер.

Банковский сайт — засилье Internet Explorer, причем с уклоном в сторону более старых версий. Кто ходит? Офисные работники на старых, давно не апгрейженных компах.

25% Оперы в интернет-магазине? Моя теория такая. Добросовестный человек занимается интернет-шоппингом в свободное от работы время с домашнего компьютера. По всей видимости, Опера — выбор многих рядовых пользователей для серфинга из дома.

Примерно от трети до половины пользователей IE проапгрейдились до IE 7.0. И это хорошо. Признаюсь, я стал уже немного забивать на IE 6.0. Скажем, на неработающий в IE 6.0 псевдокласс hover не у ссылок. Раньше писал джаваскриптик, который ловил onmouseover/onmouseout и навешивал/убирал класс hover. А сейчас забил.

Тем не менее, еще около полпроцента пользуются IE 5.0 и IE 5.5. И это до хрена! При посещаемости 50 000 в день, это 250 человек. Обязательно нужно проверять сайт в этих браузерах. Контент должен читаться, навигация должна работать, человек должен мочь выполнить свою задачу с которой он пришел на сайт.

23.05.2008

JavaScript: контекст для вложенных функций

that и this сидели на трубе…

Как известно, this внутри вложенных функций (inner functions) равен глобальному объекту (global object). Из-за этого приходится писать нелепую конструкцию var that = this; (господи, сколько же раз я написал эту строчку!)

Пример:

var test = {
   init: function () {
      this.txt = 'Test!';
      var that = this;
      window.setTimeout(function() {
         alert(that.txt);
      }, 1000);
   }
};

Как же избавиться от ненавистного that?

Для этого попробуем воспользоваться методом apply, который позволяет задать контекст (чему будет равен this) у функции. Однако, применить apply к callback-функции передаваемой в setTimeout нельзя, поскольку apply сразу выполняет функцию к которой он применен. Поэтому напишем вспомогательный метод scope.

Function.prototype.scope = function (o) {
   var fn = this;
   return function () {
      return fn.apply(o, arguments);
   };
};

Теперь перепишем наш пример, используя метод scope.

var test = {
   init: function () {
      this.txt = 'Test!';
      window.setTimeout(function () {
         alert(this.txt);
      }.scope(this), 1000);
   }
};

Ура, мы избавились от that!

Плюсы:

  • Выкинули var that = this;
  • В inner function используем «родную» переменную this вместо трижды злоебучей that
  • Мне кажется, код стал выглядеть элегантнее

Спорные моменты:

  • Экономии объема кода нет, может быть даже небольшое увеличение
  • Возможно, ухудшилась читаемость кода, поскольку, не дочитав до конца определения функции, непонятно, на что же ссылается this

Изначально хотел опубликовать эту заметку в Техногрете, но передумал — не могу с высокой трибуны рекомендовать решение, которым, возможно, сам не буду пользоваться :)

20.05.2008

Nightmare.xsl

Вчера ночью, засыпая, подумал: «Так, по какому XSL-шаблону сон выводить будем?» Крыша поехала, ага :)

19.05.2008

Про ошибки

Tell me about your worst professional mistake you’ve made and what you learned from it.

Tough Interview Questions and How to Handle Them

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

Передо мной стояла задача: добавить на сайт еще одну модель автомобиля — описание, технические характеристики, фотогалерею, короче говоря, несколько страниц с картинками.

Сайт был устроен таким образом, что все картинки заливались через систему администрирования (сделанную не мной), которая присваивала каждой картинке id-шник, переименовывала их по этому id-шнику (получалось, например, 157.jpg) и складывала в папку /images/.

У нас была копия сайта на локальном сервере, где я и выполнил задачу. Настало время переноса на рабочий сайт. Вот тут-то и пробил роковой час — не долго думая, я скопировал все содержимое папки /images/ с локального сервера на живой. Набрав в браузере адрес сайта, чтобы проверить все ли хорошо после переноса, я потерял дар речи и замер в ужасе. Сайт выглядел просто феерически. Все картинки перепутались: на месте логотипа было колесо, вместо слогана — кусок бампера, вместо изображений автомобилей вылезли навигационные плашки, одним словом, наступил пиздец.

Как позже выяснилось, локальная копия сайта на самом деле, сука, не была «копией» в прямом смысле этого слова. Локальная и живая версии сайта уже давно разошлись. Что самое западло, названия картинок не совпадали. Чтобы перенести картинки на живой сайт, нужно было залить их через админку живого сайта.

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

Чему же научила меня эта ошибка? Самое главное, всегда подвергать сомнению и проверять все свои предположения. В данном случае я не проверил свое предположение об идентичности локальной и живой версий сайта, за что и поплатился.

А еще, я стал бекапить файлы, которые собираюсь перезаписать на живом сайте. Дамп админов — хорошо, а свой бекап тоже не помешает :)

17.05.2008

Ресайз окна браузера

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

Уже очень давно для ресайза окна браузера я пользуюсь закладками в самом браузере — удобно, всегда под рукой и не нужно держать постороннюю приблуду для этого. Решение работает в Firefox, IE, Safari. Не работает в Opera. Вот пошаговая инструкция.

1. Поставьте закладку на любую страницу, хотя бы на страницу, которую вы сейчас читаете.

2. Откройте свойства новой закладки.

3. В поле Name напишите 1024x768. В поле Location введите javascript:window.resizeTo(1024,768);

Готово! Нажмите на получившуюся закладку и окно браузера изменит свой размер на 1024×768.

Аналогично можно сделать закладки для остальных разрешений.

У меня в Firefox и IE настроено так: для самого популярного разрешения 1024×768 закладка находится в тулбаре, для остальных разрешений закладки в меню.

Кроме того, в Firefox для закладки можно задать ключевое слово. Если потом набрать это слово в адресной строке браузера и нажать Enter, то сработает соответствующая закладка. Например, для 1024×768 я задал ключевое слово «1». Удобно для любителей работать с клавиатурой: F6 (фокус в адресную строку), 1, Enter. Вуаля! Ресайз менее чем за 1 секунду!

На десерт:

  • развернуть окно на всю ширину экрана (maximize): Alt + Space, X
  • вернуть прежний размер окна (restore): Alt + Space, R или Alt + Space, Enter

14.05.2008

Модель времени

Когда-то читал интервью с каким-то монстром программирования, где он упомянул, что проводя собеседования с устраивающимися на работу программистами, всегда просит их описать свою модель времени, как они видят себе год, неделю, день. По его мнению (с которым я согласен), в голове у каждого программиста обязательно должна быть четкая модель времени. Это такой своеобразный индикатор, что человек умеет структурировать окружающую его информацию — совершенно необходимый навык для программиста.

Год представляется мне в виде таблицы из трех строк с четырьмя месяцами в каждой строке.

Важны переходы на новую строку, особенно переход декабрь—январь, очевидно, связанный с Новым годом, и переход август—сентябрь — начало учебного года. Переход апрель—май явно не выражен и размыт. Ощущение такое, что как будто апрель иногда хочет перелезть на вторую строку или, наоборот, май пытается запрыгнуть на первую. Апрель вообще какой-то особенно безликий месяц, при мысли о нем он не сразу визуализируется на схеме. Вероятно, это от того, что в моей жизни не было важных событий в апреле.

Дни недели устроены в моей голове точно также, как они были устроены в школьном дневнике. Подозреваю, что большинство жителей нашей страны представляют себе именно такую схему недели. Неделя четко поделена пополам. В первом столбце — понедельник, вторник, среда. Во втором — четверг, пятница, суббота. Воскресенье — в уме. Я использую адресацию слева/справа, сверху/снизу/посередине. Скажем, планируя что-то на четверг, я мысленно помещаю событие в ячейку «справа, сверху».

Со временем суток дела обстоят сложнее — четкой и однозначной модели у меня нет. Есть довольно туманная схема, в которой день поделен на неравные плавающие уровни.

А как устроено ваше время?

13.05.2008

Если контент говеный, никакая разметка его не спасет

Для рядового читателя все эти рассуждения о «семантической верстке» по большому счету до лампочки. Они приходят за контентом, а не для того, чтобы проверить правильность верстки. Какие в исходном коде теги и классы их абсолютно не волнует. Если сайт интересный, его прочтут при любой разметке. Если товар охуенный, его закажут не смотря на отсутствие семантики в верстке. Информация, которую создатели сайта хотят донести до людей, гораздо важнее и требует большего внимания, чем верстка этой информации.

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

Разумеется, хорошая «семантическая верстка» повышает доступность сайта и видимость поисковыми системами. Конечно, правильная разметка выгодна самим разработчикам, т. к. облегчается поддержка проекта — новому кодеру легче вникнуть и найти место где нужно поправить.

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

05.05.2008

Дробный рейтинг

Задача. Сделать для интернет-магазина Евросети средний рейтинг товара в виде звездочек с дробными значениями. Например, средний рейтинг = 3,6. Четвертая звездочка должна быть закрашена на 60%.

Очевидно, что нагенерить картинок для всех значений рейтинга невозможно. Поэтому, будем химичить в HTML и CSS.

Для начала нам потребуются две картинки: пустая звездочка и закрашенная .

Делаем дивчик высотой в одну звездочку, шириной в пять звездочек и бекграундом у него пускаем пустую звездочку. Внутрь кладем еще один дивчик такой же высоты с закрашенной звездочкой бекграундом. А вот ширину внутреннего дивчика высчитываем по формуле: rating * 100 / 5 (я сделал это XSL-ем на сервере, но можно и яваскриптом сделать). Получилось:

<div class="rating">
   <div style="width: 72%;"></div>
</div>

Для версии без стилей внутрь наших дивчиков добавим текст «Оценка: 3,6». В обычной версии со стилями этот текст скроем.

Последний штрих — добавим тайтл, чтобы можно было посмотреть точное значение рейтинга.

Итого:

<div class="rating" title="3,6">
   <div style="width: 72%;">Оценка: 3,6</div>
</div>

CSS:

div.rating {
   width: 85px;
   background: url('star-0-big.gif') repeat-x 0 0;
}
div.rating div {
   height: 17px;
   background: url('star-1-big.gif') repeat-x 0 0;
   font-size: 1px;
   text-indent: -9999px;
}

Оценка: 3,6

Элементарно просто можно адаптировать для:

  • звездочек большего размера, сердечек, кружек пива и других форм;
  • рейтингов по 6-ти, 10-ти или сколько угодно бальной системе.

Рейтинг этой заметки:

Оценка: 5,0

;-)

26.04.2008

Вращение автомобиля на сайте ZAZ Sens

Не вдаваясь в подробности реализации, хочу поделиться парой идей, лежащих в основе вращения автомобиля на сайте ZAZ Sens.

1. Для каждого цвета все восемь ракурсов автомобиля собраны в одном файле JPG. Вот, например, файл для цвета «Зеленый мох»:

Почему я решил объединить все ракурсы в один общий файл? Во-первых, размер общего файла получается меньше. Во-вторых, меньше обращений на сервер. И, наконец, JavaScript-код для прелоада и управления одним файлом проще, чем для прелоада и управления восемью.

Эта картинка стоит бэкграундом у дивчика размером с один ракурс автомобиля. При вращении меняется background-position у дивчика и показывается соответствующий ракурс:

2. Очевидно, что прежде чем давать пользователю вращать автомобиль определенного цвета, нужно дождаться полной загрузки файла, иначе во время вращения будут неприятные эффекты в виде обрезанного автомобиля или пустоты на месте недогруженных ракурсов.

Поэтому изначально все цвета задизейблены, а в JavaScript я ставлю картинки с собранными ракурсами на загрузку (для всех цветов). По событию onload соответствующий цвет энейблится (код упрощен для наглядности):

var oImage = document.createElement('img');
oImage.onload = function(){ /* включаем зеленый цвет */ });
oImage.src = '/f/1/car-sea-green.jpg';

Таким образом цвета включаются по мере загрузки цветовых файлов.

Моей ошибкой стало то, что я ставлю на загрузку все цветовые файлы сразу, в результате чего они грузятся браузером параллельно. Получилось, что браузер долго грузит, потом почти одновременно включаются все цвета.

Если бы я сделал последовательную загрузку, то есть чтобы следующий цветовой файл начинал загружаться только по завершению загрузки предыдущего, для пользователя это было бы лучше — он быстро бы получил возможность вращать один цвет, а пока он его вращает, догрузились бы остальные. К сожалению, руки так и не дошли переделать.

25.04.2008

Три составляюшие веба

В порядке важности:

  1. Доступность (accessibility)
  2. Удобство (usability)
  3. Дизайн (design and aesthetics)

Именно в таком порядке. Каждая последующая составляющая основывается на предыдущей.

Имея недоступный контент (например, текст захерачили картинкой или без яваскрипта не показывается какая-то часть информации), нет смысла говорить об удобстве пользования сайтом. Какое удобство, если некоторые люди вообще не могут воспользоваться сайтом?

Также бессмысленно рисовать красивые иконки и кнопки, делать закругления и прочие модные дизайнерские штуки, если сайт недоступный и/или неудобный. Алан Купер в своей книге The Inmates Are Running the Asylum очень метко назвал это painting the corpse.

22.04.2008

Government web standards

Очень надеюсь, что и российское правительство когда-нибудь дорастет до того, чтобы всерьез заняться составлением стандартов для сайтов правительственных организаций.

Амазон каюк

Американский Амазон отменил дешевые доставки (Standard Shipping и Expedited Shipping) для России. В списке европейских стран напротив России появилась надпись Priority Only. Даже в Албанию отправляют обычной почтой, а в Россию теперь только самой дорогой курьерской доставкой.

Если раньше за доставку трех книг суммарной стоимостью 60 $ нужно было заплатить примерно 20 $ (Expedited Shipping), то теперь извольте отвалить все 50 $.

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

Решил попробовать британский Амазон. Они пока еще доставляют обычной почтой (Air Mail), но сами книги стоят дороже. Те самые три книги стоят 40 £ + доставка 14 £ = 54 £ = 107 $. Те же яйца.

13.04.2008

Скоро рассвет, выхода нет

Зашел я как-то в Одноклассники, поотвечал на сообщения, собрался выйти и привычным жестом потянулся в правую верхнюю часть окна чтобы нажать на ссылку «Выход». У меня уже отложилось где-то в голове, что для того, чтобы выйти, нужно нажать на последнюю ссылку на оранжевой плашке вверху.

Нажимаю и попадаю в раздел «Помощь». Что за черт? Какая еще помощь? Вчитываюсь в названия ссылок.

Хм, последняя ссылка в меню — «Помощь», а «Выхода» вообще нет. Туда, сюда — нет выхода. Что за ерунда?

Через какое-то время до меня доходит, что виной всему увеличенный размер шрифта в моем Фаерфоксе. Это меню сверстано таким «удивительным» образом, что при увеличении размера шрифта невлезающие пункты меню (им сказано float: left;) переносятся на вторую строчку и сливаются с фоном (ссылкам задан белый цвет).

При выделении ссылка проявляется.

При дальнейшем увеличении размера шрифта пропадают и остальные ссылки — «Помощь» и так далее.

В IE размер шрифта, конечно, зафиксировали.

Позор джунглей.

03.04.2008

Виза ВТБ24



Я уже давно забил читать книги по веб-разработке на русском языке. Хороших книг просто нет. Скажем по яваскрипту я знаю только одну более-менее нормальную книгу на русском — Флэнагана, да и та больше как справочник. Всем советую — если не хотите читать говеный перевод прошлогодних западных книг или дристню отечественных авторов, короче, если хотите быть на передовой — делайте карточку Визу и заказывайте книги на Амазоне.

Я много раз заказывал на Амазоне и все мои карточки работали безотказно. Однако, недавно Амазон отказался проглотить платеж по карте Виза банка ВТБ24. Пробую второй раз, третий — хуй вам.

Стал гуглить на тему возможных проблем. Выснилось, что с недавнего времени ВТБ24 стал требовать передачу CVC (CVV) кода. Позвонил в ВТБ24, спросил, дескать, что за нахрен. Мне ответили, что запрос CVV кода увеличивает секьюрность карты, и что об этом было уведомление на сайте банка. Видимо сотрудники ВТБ24 считают, что все владельцы карт прямо каждое утро начинают с чтения новостей ВТБ24, настолько они важные и интересные.

Написал в Амазон. Ответили:

I’m sorry, but our ordering system is not set up to accept the CVV2 security code associated with credit cards. I hope this will not prevent you from receiving your order. Some issuing banks do have stricter requirements for internet purchases. If your bank requires that the CVV2 code be submitted, unfortunately we can’t accommodate that request and you will need to use a different credit card or payment method.

Блять, придется переделывать карточку в другом банке — она мне по сути в данный момент только для заказов на Амазоне и нужна.

02.04.2008

PSD2HTML

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

Вот, например, PSD2HTML. Особенно у них порадовала форма заказа с кучей опций.

И что поразительно: делают быстро и за какие-то копейки. PSD2HTML обещает порезать макет в течении 1 рабочего дня примерно за 150 долл. Поискал в блогах и на форумах — кто пользовался их услугами пишут, что на выходе качественный xhtml/css-код. Блять, уволить надо половину наших кодеров и пользовать PSD2HTML :-)

Вообще интересно было бы скормить в такую контору макет от нашего студийного дизайнера и посмотреть не подавятся ли :-)

Меня, признаться, самого посещали мысли о создании подобной компании, которая бы занималась преимущественно front-end веб-разработкой, ну может изредка и back-end. Крупнейшими клиентами такой компании могли бы стать студии дизайна и рекламные агентства не специализирующиеся на веб-дизайне, но тем не менее получающие время от времени заказы на сайты. Они в состоянии нарисовать макет сайта (есть дизайнеры с веб-дизайнерским прошлым), но держать команду веб-технологов для них невыгодно и бессмысленно.

30.03.2008

5 копеек

Гуляя сегодня по набережной Москвы-реки в Марьино, обнаружил престранное сооружение. В центре этой мраморной конструкции находится пятикопеечная монета. Вокруг монеты написаны названия московских вузов.

Что бы это значило? Мое предположение, что это сродни носу у собаки на станции метро «Площадь Революции» за который нужно подержаться перед сдачей экзамена. Здесь же, видимо, нужно встать в центр на пятикопеечную монету и мысленно сказать «халява на экзамене, приди!»

Второй вариант использования — для выбора вуза куда поступать. Становишься в центр, закрываешь глаза и бросаешь монетку вверх. На какой вуз попала — туда и пошел :-)

27.03.2008

JavaScript: Closure

На русский closure обычно переводят как «замыкание».

John Resig в своей книге Pro JavaScript Techniques, которую я сейчас читаю, привел ссылку на статью JavaScript Closures. Это очень мощная, пожалуй, самая глубокая и фундаментальная статья по JavaScript, которую я когда-либо читал. Респект автору, Ричарду Корнфорду.

Стал копать дальше, нашел еще замечательную статью: JavaScript Closures for Dummies. Написано очень понятно, с хорошими примерами. Рекомендую начать с этой статьи, если вы только осваиваете closure. Отдельно отметим оригинальную находку автора поместить кусочек JavaScript-кода на кнопку, который этот код запускает.

Также достойны вашего внимания еще две статьи о closure: на Википедии и Мартина Фаулера. В этих статьях речь идет о closure вообще как о концепции программирования, безотносительно к JavaScript.

Что касается книги Ресига, то я несколько разочарован. Материал изложен поверхностно, не хватает глубины как в статье Корнфорда. Много опечаток и ошибок. Как раз в одном из примеров на closure есть концептуальная ошибка, пример не работает. Не понятно как так можно, что он, не оттестировал примеры перед публикацией что-ли?

UPD: Ошибка в примере на closure (листинг 2-16) есть только в исходном коде, который можно скачать с сайта книги. В самой книге этой ошибки нет.

Жду книгу Дугласа Крокфорда. Надеюсь, старина Крокфорд не подведет :-)

26.03.2008

XSLT: сборная солянка

Несколько неочевидных моментов по XSLT.

1. avg, min, max

В XSLT нет агрегатных функций avg(), min(), max(). Есть только count() и sum().

Предположим, у нас есть такой XML:

<list>
   <item>10</item>
   <item>5</item>
   <item>25</item>
</list>

Среднее значение можно посчитать так:

<xsl:variable name="avg" select="sum(/list/item) div count(/list/item)"/>

Минимум и максимум чуть сложнее. Бежим по отсортированным по возрастанию/убыванию нодам и берем первую:

<xsl:variable name="min">
   <xsl:for-each select="/list/item">
      <xsl:sort data-type="number" order="ascending"/>
      <xsl:if test="position() = 1"><xsl:value-of select="."/></xsl:if>
   </xsl:for-each>
</xsl:variable>

<xsl:variable name="max">
   <xsl:for-each select="/list/item">
      <xsl:sort data-type="number" order="descending"/>
      <xsl:if test="position() = 1"><xsl:value-of select="."/></xsl:if>
   </xsl:for-each>
</xsl:variable>

2. current()

current() внутри квадратных скобок позволяет выйти из контекста ноды к которой применены эти скобки и вернуться к контексту текущей ноды (которая была заматчена шаблоном или заселекчена <xsl:for-each>).

То есть вместо того, чтобы создавать переменную:

<xsl:template match="navigation">
   <xsl:variable name="status" select="@status"/>
   <xsl:value-of select="/captions/caption[@status = $status]"/>
</xsl:template>

можно написать так:

<xsl:template match="navigation">
   <xsl:value-of select="/captions/caption[@status = current()/@status]"/>
</xsl:template>

3. concat()

Работает быстрее:

<xsl:value-of select="concat(@Name, ' ', @Surname)"/>

чем:

<xsl:value-of select="@Name"/>
<xsl:value-of select="' '"/>
<xsl:value-of select="@Surname"/>

Потому что в первом случае происходит только одна операция вставки в результирующее XML-дерево.

Не говоря уже о том, что первый вариант компактнее.

4. not() vs. !=

В некоторых версиях XSLT-процессоров есть разница:

not(@name = 'Stepan')

<a name="Stepan"/> => false
<a name="Leechy"/> => true
<a/> => true

@name != 'Stepan'

<a name="Stepan"/> => false
<a name="Leechy"/> => true
<a/> => false

Пару раз когда использовал != сталкивался с тем, что вылезала бага при переносе кода с разработческого сервера на хостинг, где стоял другой XSLT-процессор. Поэтому рекомендую всегда использовать not().

5. Глобальные переменные → ускорение

Переменная Regions вычисляется каждый раз при вызове шаблона для <MuscatRow>:

<xsl:template match="MuscatRow">
   <xsl:variable name="Regions" select="/Imprimatur/Element[@Name = 'Regions']/Document"/>
   <xsl:value-of select="$Regions[@Name = current()/@Name]/content"/>
</xsl:template>

Используя глобальную переменную можно добиться некоторого ускорения. Переменная Regions вычисляется один раз:

<xsl:variable name="Regions" select="/Imprimatur/Element[@Name = 'Regions']/Document"/>
<xsl:template match="MuscatRow">
   <xsl:value-of select="$Regions[@Name = current()/@Name]/content"/>
</xsl:template>

Актуально при большом количестве <MuscatRow>.

6. Отсчет preceding-sibling-ов

preceding-sibling[1] — это ближайший предыдущий элемент.

Получается вот что:

preceding-sibling[last()]
...
preceding-sibling[2]
preceding-sibling[1]
current item
following-sibling[1]
following-sibling[2]
...
following-sibling[last()]

HTML: контейнеры

Как бы вы заверстали копирайт? Варианты ответов:

<p id="copyright">(с) 2005 Company Inc.</p>

<div id="copyright">(с) 2005 Company Inc.</div>

<div id="copyright">
   <p>(с) 2008 Company Inc.</p>
</div>

Первый вариант ограничивает нас только одним абзацем. Если со временем потребуется добавить второй абзац копирайта, то верстку придется переделать. Кроме того, представим, что вдруг потребовалось вставить в копирайт блок с какой-то сложной версткой (очередное дизайнерское извращение). Тег <p> не может содержать блоковых элементов, поэтому опять-таки придется переделать.

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

Однако, я выбираю третий вариант, не смотря на то, что он самый длинный. Тег <p> добавляет еще немного семантики — получается «параграф текста внутри блока копирайта».

Еще один плюс: в версии без стилей блоки текста не слипнутся.

Простой пример.

В версии без стилей текст слипнется:

<div id="some_additional_info">Some additional info.</div>

<div id="copyright">(с) 2008 Company Inc.</div>

А так не слипнется:

<div id="some_additional_info">
   <p>Some additional info.</p>
</div>

<div id="copyright">
   <p>(с) 2008 Company Inc.</p>
</div>

Кстати, проверять верстку с отключенными стилями вообще очень полезно. Если сайтом по-прежнему можно пользоваться, значит сверстано семантически грамотно.

21.03.2008

Про компромиссы

Важно уметь найти компромисс.

— Делать работу с учетом возможных будущих изменений, но с другой стороны не ковыряться слишком долго, делая универсальный вариант, который потом никому не понадобится.

— Найти приемлимый баланс между семантически идеальным кодом, сверстанным по стандартам, и тем, как это отображается в различных браузерах.

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

— Знать грань, когда лучше пойти договориться с дизайнером, чтобы он немного перерисовал, вместо того чтобы умирать, верстая ебанистический макет.

XSLT: sort

Используя <xsl:sort> нужно иметь в виду два момента.

— При хождении от текущего элемента по осям preceding-sibling и following-sibling, мы ходим по исходному дереву.

<xsl:for-each select="item">
   <xsl:sort select="name" />
   <!-- preceding-sibling и following-sibling работают по исходным,
        не отсортированным данным -->
</xsl:for-each>

position() после <xsl:sort> возвращает позицию в отсортированном дереве.

CSS: line-height

Как-то я долго мучился с line-height.

Задавал его в em и процентах у body и были жуткие глюки с наследованием.

Я уже было отчаялся и решил жахнуть стиль для звездочки:
* {line-height: 1.4em;}

Но тут, коллега подсказал мне, что line-height нужно указывать без единиц измерения.

Оказывается, если указывать line-height в em или %, то при наследовании браузеры не пересчитывают line-height в зависимости от размера шрифта текущего элемента. Из-за этого у меня в <h1> слипались строчки.

А если указывать просто число без единиц измерения, то пересчитывают. То есть берут размер шрифта текущего элемента, умножают на это число и получается высота строки текущего элемента.

Правки в чужом коде

Когда меня просят помочь по какому-либо проекту, я всегда сначала потрачу 15 минут на изучение особенностей написания кода в данном проекте. Как именуются классы и айдишники в CSS, переменные и методы в JavaScript, шаблоны и моды в XSL. Как отбиваются блоки кода пустыми строками, где стоят пробелы, а где нет. И постараюсь сделать в этом же стиле, как бы он не был мне противен.

Никто не любит править чужой код. Но также неприятно открыть свой код и увидеть, что кто-то нагадил там в другом стиле :-) Это все равно как если бы Зюсмайер, дописывая «Реквием» Моцарта, вставил бы туда какую-нибудь отсебятину, пусть и хорошую. Хорошо, но не в кассу. Нужно уважать автора и его стиль программирования.

JavaScript: return this;

Если в методе не нужно возвращать некое значение, то лучше сделать чтобы этот метод возвращал this. Это позволяет программировать в каскадном стиле:

myObj.prepare().activate();

Напомню, что если метод явно ничего не возвращает, то он возвращает undefined. Исключение составляют конструкторы, которые по умолчанию и так возвращают this, то есть указатель на новый созданный объект. Поэтому в конструкторах не нужно писать return.

20.03.2008

Смотреть в будущее

Хороший технолог всегда закладывается на то, чего по утверждению дизайнера или менеджера на сайте никогда не будет. Потому что знает — скоро все именно так и будет.

27 июня 2005 года эта фраза висела на главной странице Студии.

19.03.2008

Мысли по поводу организации работы

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

Я за такую схему работы: более опытный технолог начинает проект, задает направление, закладывает фундамент, создает базовые шаблоны, основные механизмы и прочее. Менее опытный технолог затем продолжает, а более опытный присматривает и корректирует («ведет») менее опытного.

Нельзя давать человеку одному делать новый проект на незнакомой для него системе (CMS). Человеку сложно сходу придумать хорошую архитектуру решения в новой для него среде разработки. Вопросов которые нужно решить много: где как что хранить, как структурировать шаблоны и прочее. Дай мне сейчас новую систему, отличную от Имприматур I или II, и если мне никто не поможет, я скорее всего тоже сначала сделаю не лучшим образом.

Можно проводить семинары, это, конечно, дает какой-то результат. Однако после семинара человек остается один на один с системой и начинает «ваять».

У менее опытных технологов возможно поначалу будет «ломка». Привыкать к чужому стилю программирования и структурирования информации не просто. Зато они чему-то научатся и не сделают проект, который потом придется переделывать.

Переключение режимов в IE8

Кстати, если кто еще не знает. Микрософт передумали и теперь IE8 по умолчанию будет рендерить в режиме IE8 Standards. Но с помощью <meta> ему можно будет сказать «рендери как IE7». Ранее анонсировалось обратное поведение.

Итого в IE8 будет 3 режима: Quirks, IE7 Standards и IE8 Standards.

Поведение такое:

1. Задан DOCTYPE для стандартного режима или неизвестный DOCTYPE — включается IE8 Standards mode

2. Задан DOCTYPE для режима Quirks или DOCTYPE отсутствует — Quirks mode

3. Есть <meta equiv="X-UA-Compatible" content="IE=7"> — вне зависимости от DOCTYPE, включается IE7 Standards mode

Ссылки по теме:
Microsoft's Interoperability Principles and IE8
The Default Layout Mode