21.12.2009

input type="file" multiple

Оказывается, Safari 4, Chrome 3 и Firefox 3.6 Beta 4 поддерживают выбор сразу нескольких файлов с помощью атрибута multiple.

<input name="att" type="file" multiple="true"/>

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

Еще более удивительно то, что Opera уже давно поддерживает multiple-файлы с помощью атрибутов min и max.

<input name="att" type="file" min="1" max="99"/>

При этом в Опере меняется название кнопки.

Обычный инпут:

С атрибутами min и max:

Очень хочется верить, что multiple заимплементируют в IE 9. Тогда можно будет, наконец, полностью отказаться от дурацкой флешки.

02.11.2009

Результаты домашки №1

Ну что же, давайте подведем итоги первой домашки :)

Задача 1

Эта задача вызвала некоторые затруднения почти у всех принявших участие. Я заметил несколько типичных проблем:

1. Велосипедизм. Как верно заметил nop, задача сводится к классической задаче поиска подстроки в строке. Многие это почувствовали, однако поленились погуглить и решили изобрести свой велосипед. Существует огромное количество алгоритмов поиска подстроки, самый простейший (brute force algorithm) можно закодить так:

var subArrayIndex = function(haystack, needle) {
   var i, j;
   var m = haystack.length;
   var n = needle.length;

   for (i = 0; i <= m - n; i += 1) {
      for (j = 0; j < n && needle[j] === haystack[i + j]; j += 1);
      if (j >= n) {
          return i;
      }
   }

   return -1;
};

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

3. Сравнение с приведением типов. Практически все для сравнения элементов массивов использовали == и !=. Ребята, если вы еще не знаете, знайте: в яваскрипте == и != делает приведение типов. Это означает, например, что 1 == '1' выдаст true. Для сравнения без приведения типов используйте === и !==.

Задача 2

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

var toArrayOfFunctions = function(array) {
    var makeFunction = function(item) {
        return function() {
            return item;
        };
    };
    var i;
    var len = array.length;
    var functions = [];
    for (i = 0; i < len; i += 1) {
        functions[i] = makeFunction(array[i]);
    }
    return functions;
};

UPD: В одном из решений второй задачи заметил еще проблему, которую назовем «порча входных данных». Нужно помнить, что объекты (массивы в том числе) передаются по ссылке, а не по значению. Если в функции вы делаете какие-то хирургические операции с принятым в аргументах объектом, то вы меняете непосредственно переданный объект.

Пример:

var add1 = function(array) {
    for (var i = 0; i < array.length; i += 1) {
        // Трах-бабах-хуяк - портим переданный массив
        array[i] = array[i] + 1;
    }
    return array;
};

var a = [1, 2, 3];
var b = add1(a); // a и b теперь один и тот же массив [2, 3, 4]

23.10.2009

Домашка №2

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

20.10.2009

Нет отрицательной логике

Что общего у этого кусочка яваскрипта (время от времени встречаю такое в чужом коде):

function init(noLoginForm) {
    if (!noLoginForm) {
        ...
    }
}

и этого фрагмента формы (постоянно сталкиваюсь на сайтах):

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

function init(showLoginForm) {
    if (showLoginForm) {
        ...
    }
}

(Не вижу ничего плохого в том, чтобы по умолчанию чекбокс был зажженным.)

Кстати, думаю, именно по этой причине в Гугл Ридире чекбокс Mark as unread переделали в Mark as read.

15.10.2009

Домашка №1

По примеру Сергея тоже хочу загрузить вас домашкой :) Не пугайтесь, задания не сложные (пока). Итак, сегодня две задачки по яваскрипту.

Задача 1

Написать метод, который принимает два массива в качестве параметров и возвращает позицию, начиная с которой второй параметр входит как подмассив в первый параметр.

Пример. Первый массив: [4, 8, 15, 16, 23, 42], второй массив: [15, 16], результат: 2

Задача 2

Есть массив с числами. Нужно написать метод, который трансформирует исходный массив в массив функций, которые возвращают исходные числа.

Пример. На входе: [4, 8, 15], на выходе: [function() {return 4;}, function() {return 8;}, function() {return 15;}]

10.10.2009

Откуда берутся веб-разработчики?

Думаете это обычный гимнастический мяч валяется возле моего рабочего стола? А вот и нет! Это яйцо, из которого скоро вылупится новый веб-разработчик.

10.09.2009

Ajax со вкусом апельсина

Купил на днях в калифорнийском магазине вот такое средство для мытья посуды :)

28.08.2009

Улыбаемся и машем

На мотив Yellow Submarine: «Запустили мы видеописьмо, видеописьмо, видеописьмо. Вместе дружно пробуем его, тестируем его, о-го-го-го-го!»

Теперь прямо в Яндекс.Почте можно записать видеоролик, который выложится на Яндекс.Видео, а секретная ссылка на этот ролик вставится в письмо. Все вместе это называется «видеописьмо».

06.08.2009

Однопиксельные прозрачные уголки

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

Есть более крутой способ, суть его в следующем:

Упрощенный код для понимания идеи:

.corners {
    background-color: #80aaff;
    margin: 0 1px;
    padding: 1px 0;
}

.corners-i {
    background-color: #80aaff;
    margin: 0 -1px;
}

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

Достоинства способа:

  • Всего лишь один доп. элемент.
  • Уголки получаются прозрачные, а значит не нужно их «красить» в цвет фона.
  • Нет JS, экспрешенов, спрайтов.

Недостатком, конечно, является ограничение радиуса скругления в 1 пиксель :)

Рассмотренный способ отлично сочетается с бордер-радиусом, то есть, в браузерах поддерживающих border-radius используем border-radius, в остальных браузерах задействуем доп. элемент .corners-i и делаем однопиксельные уголки.

24.06.2009

border-radius спешит на помощь

В соавторстве с Вадимом Макишвили

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

Идея была в том, чтобы использовать CSS-свойство border-radius, которое поддерживают некоторые прогрессивные браузеры:

  • Firefox начиная с версии 1.0 (~24% пользователей)
  • Safari начиная с 3.0 + Chrome (~2%)
  • Konquerer (~0,05%)

Итого, для ~25% пользователей уголки можно рисовать средствами браузера — уже неплохо.

Смешно, но свойство border-radius, которое есть в CSS3, пока не поддерживается ни одним браузером. Однако, некоторые браузеры поддерживают аналогичные проприетарные свойства, например, -moz-border-radius в Firefox.

.corners {
    /* Возможно какой-нибудь браузер в будущем, будем надеяться IE */
    border-radius: 4px;
    /* WebKit (Safari/Chrome) */
    -webkit-border-radius: 4px;
    /* KHTML (Konquerer) */
    -khtml-border-radius: 4px;
    /* Возможно Opera в будущем */
    -opera-border-radius: 4px;
    /* Gecko (Firefox) */
    -moz-border-radius: 4px;
}

Для остальных браузеров, не поддерживающих border-radius, будем яваскриптом вставлять доп. элементы для реализации уголков.


// Проверяет, поддерживает ли элемент elem CSS-свойство border-radius.
var isBorderRadiusSupported = function (elem) {
    var s = elem.style;
    return typeof s.borderRadius === "string" ||
           typeof s.WebkitBorderRadius === "string" ||
           typeof s.KhtmlBorderRadius === "string" ||
           typeof s.OperaBorderRadius === "string" ||
           typeof s.MozBorderRadius === "string";
};

// Добавляет внутрь элемента elem доп. элементы реализующие уголки.
var wrapInCorners = function (elem) {
    // Реализуем уголки любым известным способом
    $(elem).prepend('<i class="lt"/><i class="rt"/><i class="lb"/><i class="rb"/>');
};

// Реализует закругленные уголки с помощью доп. элементов
// для браузеров не поддерживающих CSS-свойство border-radius.
var checkCorners = function () {
    // Ищем все элементы с классом corners
    $('.corners').each(function () {
        // Если для данного элемента браузер не поддерживает border-radius
        if (!isBorderRadiusSupported(this)) {
            // Добавляем внутрь элемента доп. элементы реализующие уголки
            wrapInCorners(this);
        }
    });
};

// DOM загрузился и готов к обходу и манипуляциям
$(function () {
    checkCorners();
});

Плюсы решения:

  • HTML льется чистый, без доп. элементов, и, соответственно, лишняя разметка не мозолит глаз ни в статической верстке, ни в XSL-шаблонах.
  • В прогрессивных браузерах (примерно у четверти пользователей) уголки рисуются средствами браузера (максимально быстро).
  • Есть задел на будущее — если IE или Opera надумают реализовать border-radius, то наше решение готово к этому радостному событию.

UPD: В комментариях указали на слабые стороны этого решения. Также откликнулись мои коллеги и помогли улучшить решение по производительности. Спасибо всем! Для этого мне и нужен блог — поделиться решением, собрать фидбек и найти более удачный вариант.

1. Не нужно проверять поддержку border-radius для каждого элемента. Сделаем эту проверку один раз в теге <head> до загрузки контента и добавим соответствующий класс у элемента <html>.

// Проверяет, поддерживает ли браузер CSS-свойство border-radius.
var isBorderRadiusSupported = function () {
    var s = document.documentElement.style;
    return typeof s.borderRadius === "string" ||
           typeof s.WebkitBorderRadius === "string" ||
           typeof s.KhtmlBorderRadius === "string" ||
           typeof s.MozBorderRadius === "string";
};

document.documentElement.className += isBorderRadiusSupported() ?
        " border-radius" : " no-border-radius";

2. Создавать из строки ноды под каждый уголок недешево, а зааппендить их в DOM еще дороже. Вставка каждого уголка это рефлоу блока, в который он вставляется. Выгоднее просто отдавать доп. разметку сразу в HTML. Задействовать доп. разметку будем в зависимости от класса, который мы выставили у элемента <html>.

.no-border-radius .corners .lt {
    // Стили для уголков
}

3. На текущий момент в Опере нет поддержки border-radius. Не стоит гонять балластный код ради неизвестного будущего. Поэтому отрываем -opera-border-radius: 4px; и соответствующую проверку в JS.

UPD2: Opera 10.50 pre-alpha поддерживает border-radius, причем без префикса. Ура!

16.06.2009

Не хватает слов? Нарисуй письмо!

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

Подробности в блоге новой Яндекс.Почты.

P.S. Кстати, по-украински «Рисовалка» будет «Малювалка» :) Можете включить украинский язык интерфейса и проверить :)

11.06.2009

Комментарии

/**
 * По-хорошему, объем комментариев должен быть не меньше
 * объема самого кода или даже больше. Я вообще стараюсь
 * сначала комментарий написать, а потом уже кусок кода.
 * Если русским языком не можешь сформулировать, что хочешь
 * чтобы код делал, значит рано еще сам код писать. Скажу
 * больше, акт написания комментария заставляет мозг
 * напрячься и обрести ясность мысли, что способствует
 * написанию стройного и четкого кода. Вы не замечали
 * за собой такого?
 */

03.06.2009

Сайт «Музея советских игровых автоматов»

http://www.artlebedev.ru/everything/15kop/

Уже три с половиной месяца не работаю в Студии, а проекты с моим участием продолжают выходить :)

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

В процессе работы над сайтом особый кайф я получил от создания страницы «Ночной рейс». Мега-крутая фишка получилась!

28.05.2009

Новая Яндекс.Почта

Та-дам! Дорогие друзья, свершилось знаменательное событие! Команда Яндекс.Почты запустила новый интерфейс (Нео). Всем срочно бежать смотреть и тестировать.

Обо всех проблемах сообщайте нам через форму обратной связи, а также не забудьте отправить нам бочку меда или ложку дегтя. Спасибо :)

Поздравляю вас/нас с этим волнующим событием! Ура!

22.05.2009

Будущее яваскрипта: ECMAScript 5

Очень впечатлился выступлением товарищей из ECMAScript о грядущих изменениях в языке. Рекомендую посмотреть всем яваскриптерам.

Слайды презентации

20.05.2009

Гигапедия

Открыл для себя Гигапедию — сайт, где можно найти любую книгу в электронном виде и бесплатно ее скачать. Есть всё — техническая литература, художественная, аудиокниги, даже ноты. Это просто счастье какое-то! Нужно зарегистрироваться, тогда у вас появится поиск по Гигапедии.

Накачал новых книг по яваскрипту (Стефанова, Закаса), Набокова на английском, нот для бас-гитары. Где бы теперь еще время взять, чтобы всем этим насладиться? :)

15.05.2009

Трабл с попапом с закругленными уголками поверх селекта в IE6

Уважаемые читатели, помогите кто чем может. (Сами мы не местные.)

Как известно, в IE6 селекты (однострочные и многострочные) всегда поверх любых других элементов на странице. Чтобы это побороть, нужно в вытаскиваемый наверх попап положить iframe, который в IE6 как бы «убивает» под собой селект.

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

Выглядит это так:

Что происходит:

  • iframe полностью прозрачный {filter: alpha(opacity=0);}
  • он «убивает» под собой селект
  • и начинает просвечивать бекграунд (черный)

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

Кто найдет решение, тому респект и уважуха :)

UPD: в каментах есть решение.

12.05.2009

Gmail: Двоеточие в id-шнике

Продолжение статьи «Особенности верстки Gmail».

Мой коллега Иван Широков заметил, что все id-шники в верстке Gmail начинаются с двоеточия.

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

Во-первых, чтобы нельзя было (даже по ошибке) навесить стили для такого id-шника, потому что #:my {color: red;} не работает. Своеобразная защита, которая как бы подчеркивает, что id-шник используется только в яваскрипте.

Во-вторых, и в главных, чтобы элемент не был доступен по идентификатору в глобальной области видимости (global namespace). Когда мы пишем <div id="my">test</div>, этот дивчик становится доступен через идентификатор my в глобальной области видимости. То есть alert(my.tagName) выдаст «DIV» (сюрприз, сюрприз!). А если писать с двоеточием <div id=":my">test</div>, то уже хренушки — нет такого идентификатора в глобальной области видимости. При этом элемент по-прежнему можно достать через document.getElementById(':my'). На самом деле это очень круто, так как уменьшается вероятность коллизии в глобальной области видимости.

Все это лишь мои догадки. А вы что думаете?

08.04.2009

Дилемма о загрузке JS-файлов

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

<div id="something">
    ...
</div>
<script>
    Something.init();
</script>

Понятно зачем — чтобы свести к минимуму задержку между двумя событиями: 1) HTML компонента отобразился и 2) JS компонента загрузился и инициализировался.

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

Разумеется, для этого нужно грузить JS-код компонента вперед HTML-кода (обычно это делают в <head>).

***

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

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

Однако, минус очевиден — увеличивается задержка между рассмотренными выше событиями 1) и 2). То есть мы получаем, что пользователь дольше видит HTML с еще не наложенным яваскриптом.

***

Что делать? Я думаю, что правильный путь — это все-таки вынести загрузку всех JS-файлов в конец страницы, при этом в <head> грузить один маленький легковесный скрипт, который при попытке пользователя взаимодействовать с компонентом при еще не наложенном JS, будет сигнализировать ему, что, мол, все окей, подожди чуть-чуть, JS грузится и скоро наступит счастье.

Вот и Мэтт Снайдер похожим путем идет. А как вы решаете эту дилемму?

05.04.2009

JSLint

Валидировали, валидировали, да не вывалидировали.

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

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

Главное — не перегибать палку

Не стоит принимать отчет JSLint как истину в последней инстанции и сразу бросаться править код. Это всего лишь рекомендация, поэтому нужно включить у себя в голове thinking mode и по каждой ошибке в отчете решить самому — согласиться с JSLint или нет. Благодаря тому, что у JSLint есть множество опций, позволяющих указать какие ошибки искать, а какие игнорировать, этот инструмент можно легко настроить на свой вкус.

Варианты использования

1. Самый простой — пойти на сайт JSLint и скопипейстить свой код в форму валидации.

2. Виджеты JSLint Widget, JSLint Multi widget, JSLint Dashboard widget for Mac OS X.

Можно драгндропнуть JS-файл или целую папку в окошко виджета, и получить отчет JSLint. В настройках виджета есть полный комплект опций JSLint.

JSLint Widget

Чем больше объем JS-кода, тем больше хочется интеграции со средой разработки (IDE). Также для крупных проектов желательно сделать валидацию рутинной операцией, выполняющейся автоматически, например, на этапе сборки и упаковки JS-кода.

3. В Aptana есть встроенный JSLint, который изначально выключен. Включить можно в настройках: Preferences → Aptana → Editors → JavaScript → Validation. После этого код будет валидироваться по мере того, как вы его печатаете.

JSLint в Аптане

К сожалению, у JSLint в Аптане нет опций.

4. Плагин к Eclipse. В начале этого года компания RockstarApps выпустила JSLint Eclipse Plugin. Опции все есть, но нет возможности указать predefined global variables, что, конечно, обломно.

5. Rhino и Windows Script Host. На одном из проектов мы используем Rhino для запуска JSLint. Написали скрипт, который обходит все проектные JS-файлы, для каждого из них вызывает JSLint и формирует общий отчет — очень удобно! Пожалуй, надо будет написать отдельный пост про это :-)

JSLint продолжает развиваться. Следить за обновлениями можно в группе JSLint, куда часто пишет сам Крокфорд, автор JSLint.

А вы валидируете свой JavaScript-код?

15.03.2009

Электропочта

Инбокс

Для меня инбокс — это фактически туду-лист. Пока я не решил затронутую в письме проблему, письмо сидит в инбоксе. Как только по письму все сделано, оно немедленно отправляется в папку (или в Gmail навешивается метка и архивируется). Я часто сам себе пишу письма чтобы что-то не забыть, потому что знаю — если есть в инбоксе, то задача не промандится. Вообще не понимаю, как живут и работают люди, у которых все письма хранятся в инбоксе.

Фильтры

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

Периодичность проверки почты

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

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

Черновики

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

--

А у вас какие приемы работы с почтой для повышения собственной эффективности?

Передача параметров из HTML в JavaScript

Часто при инициализации JS-компонента нужно найти определенный DOM-элемент с которым компонент будет работать, а также достать из HTML параметры (настройки). О способах хранения и передачи в JS этих параметров я и хотел бы поговорить.

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

Предположим, у нас есть DOM-элемент:

<span id="test">тест</span>

При клике на этот элемент мы хотим показывать некий попап. Для показа попапа нужно задать следующие параметры: ширина, высота, таскаемость попапа и текст. Раньше я написал бы примерно следующее:

<span id="test" class="width_250 height_150 draggable"><span class="text">Трам-парам!</span>тест</span>

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

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

<span id="test" onclick="return {width: 250, height: 150, draggable: true, text: 'Трам-парам!'};">тест</span>

Как достать этот объект:

var element = document.getElementById('test');

// Забираем параметры
var options = element.onclick instanceof Function ? element.onclick() : {};

// Заметаем следы - обнуляем onclick
element.onclick = null;
element.removeAttribute('onclick');

// Навешиваем обработчик onclick для показа попапа
element.onclick = function () {
    showPopup(options);
};

По сути, для передачи настроек используется формат JSON в котором есть шесть типов значений: объект, массив, строка, число, булевское значение и null. Используя эти типы, можно передавать довольно сложную структуру данных, немыслимую для передачи через классы.

По-моему, очень круто. Блин, почему я сам не додумался до этого? :)

21.02.2009

Особенности верстки Gmail

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

1. Названия классов

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

2. Несемантическая верстка

Например, список папок сделан не ul>li, а дивчиками (адепты семантической верстки содрогнулись от ужаса). Однако, учитывая что все генерится яваскриптом, не вижу в этом большой проблемы.

3. Спрайт с фоном

Картинка со всеми иконками содержит фиолетово-голубой паттерн-бэкграунд.

Очевидно, сделано это для того, чтобы сразу заметить съехавшее на пиксел позиционирование иконки. Такая самотестирующаяся верстка получается. Круто, но я бы не решился отдавать в продакшн такую картинку. Мало ли что :)

4. Скругленные уголки

Думаю, в какой-то момент (вероятно, когда делали Themes) чуваки заманались вырезать эти уголки и сделали сервис, который генерит картинки на лету.

http://mail.google.com/mail/rc?a=af&c=c3d9ff&w=4&h=4
http://mail.google.com/mail/rc?a=af&c=black&w=32&h=16

Параметры: c — цвет в RGB или словом, w — ширина (от 1 до 64), h — высота (от 1 до 64). Что означает параметр a=af я не осилил.

Smart folks, those Google people :)

16.02.2009

Пока, Студия! Привет, Яндекс!

Сегодня был мой первый рабочий день в Яндексе.

Некоторое время назад я принял непростое решение покинуть Студию Лебедева. Мне нравилось в Студии. Можно сказать, это был мой второй дом. Однако, после почти 7 лет настала пора двигаться дальше.

Cпасибо Студии за все, что между нами было. Мне будет вас не хватать. Удачи!

14.02.2009

JavaScript!

Не перестаю удивляться сложности задач, которые можно решить с помощью JavaScript.

Один чувак написал распознавалку капчей сайта Megaupload. Джон Ресиг разобрал как это сделано.

Другой чувак заебошил карту мира на канвасе.

(Ну не говоря уже про Gmail, Google Reader и Google Docs.)