27.01.2010

JavaScript Shortcuts Library

Выложил библиотеку для создания клавиатурных шорткатов JavaScript Shortcuts Library (jQuery plugin). Пригодится при разработке больших веб-приложений, а также написании игр на JavaScript.

Библиотека приятна и проста в использовании. Добавляем шорткат:

$.Shortcuts.add({
    type: 'down',
    mask: 'Ctrl+A',
    handler: function() {
        debug('Ctrl+A');
    }
});

Добавляем еще один:

$.Shortcuts.add({
    type: 'up',
    mask: 'Shift+B',
    handler: function() {
        debug('Shift+B');
    }
});

Начинаем реагировать на шорткаты:

$.Shortcuts.start();

Поддерживаются три типа событий, по которым могут срабатывать обработчики:

  1. down — на нажатие клавиши или сочетания клавиш
  2. up — на отпускание
  3. hold — на нажатие и удержание (обработчик будет вызван сразу после нажатия и потом будет вызываться с некоторой периодичностью пока нажата клавиша)

Строка задающая сочетание клавиш должна состоять из имен клавиш разделенных плюсами. Может быть не более одной клавиши отличной от Ctrl, Shift или Alt. Строка нечувствительна к регистру. Примеры: "Esc", "Shift+Up", "ctrl+a".

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

Добавляем шорткат в список "another":

$.Shortcuts.add({
    type: 'hold',
    mask: 'Shift+Up',
    handler: function() {
        debug('Shift+Up');
    },
    list: 'another'
});

Переключаемся на список шорткатов "another":

$.Shortcuts.start('another');

Также можно удалять шорткаты:

$.Shortcuts.remove({
    type: 'hold',
    mask: 'Shift+Up',
    list: 'another'
});

Останавливаем работу шорткатов (делается unbind навешенных обработчиков событий):

$.Shortcuts.stop();

Поддерживаемые клавиши:

  • Модификаторы: Ctrl, Shift, Alt
  • Цифры: 0—9
  • Буквы: A—Z (case-insensitive)
  • Специальные клавиши: Backspace, Tab, Enter, Pause, CapsLock, Esc, Space, PageUp, PageDown, End, Home, Left, Up, Right, Down, Insert, Delete, F1—F12, ? (знак вопроса), минус, плюс

Буду рад замечаниям и предложениям по улучшению.

22.01.2010

Простое шаблонирование в JavaScript

Задача: в JS на основе имеющихся данных сгенерить блок (кусок хтмл), заполнить его этими данными и вставить в DOM.

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

var data = {
    url: '/test/',
    thumb_src: 'test.gif',
    thumb_width: 60,
    thumb_height: 30,
    caption: 'Трам-парам!'
};

В итоге для этих данных хотим получить вот такой хтмл:

<div class="preview"><p class="image"><a href="/test/"><img src="test.gif" width="60" height="30"/></a></p><p class="caption">Трам-парам!</p></div>

Встают вопросы: в каком виде хранить шаблон и как впердолить в этот шаблон наши данные?

Вручную создавать элементы (createElement) и аппендить их (appendChild) довольно муторно. Получается громоздко и шаблон размазывается тонким слоем по JS-коду.

Часто делают конкатенацию кусочков шаблона вперемешку с данными:

var result = '<div class="preview"><p class="image"><a href="' + data.url + '"><img src="' + data.thumb_src + '" width="' + data.thumb_width + '" height="' + data.thumb_height + '"/></a></p><p class="caption">' + data.caption + '</p></div>';

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

Я использую способ, который подсмотрел в лекциях Дугласа Крокфорда. Добавляем в прототипы объекта String метод supplant, который в строке ищет выражения заключенные в фигурные скобки {}. Каждое найденное выражение используется как ключ к переданному объекту, и, если по этому ключу лежит строковое или числовое значение, то выражение в фигурных скобках заменяется этим значением.

/**
 * supplant() does variable substitution on the string. It scans
 * through the string looking for expressions enclosed in {} braces.
 * If an expression is found, use it as a key on the object,
 * and if the key has a string value or number value, it is
 * substituted for the bracket expression and it repeats. 
 */
String.prototype.supplant = function(o) {
    return this.replace(/{([^{}]*)}/g,
        function(a, b) {
            var r = o[b];
            return typeof r === 'string' || typeof r === 'number' ? r : a;
        }
    );
};

Теперь мы можем сделать так:

var template = '<div class="preview"><p class="image"><a href="{url}"><img src="{thumb_src}" width="{thumb_width}" height="{thumb_height}"/></a></p><p class="caption">{caption}</p></div>';

var result = template.supplant(data);

Еще один пример (подстановка данных в сообщение пользователю):

var template = 'Take train {number} from {from} to {to}.';

var data = {
    from: 'Madrid',
    to: 'Barcelona',
    number: '78A'
};

var result = template.supplant(data);

05.01.2010

Coders at Work

Coders at Work by Peter SeibelЭтот сборник интервью с известными программистами я решил прочитать по совету Джеффа Атвуда, автора клевого блога Coding Horror. Умение Питера Сибела задавать животрепещущие вопросы, помноженное на 15 самых влиятельных программистов, дало на выходе захватывающую книгу, от которой с трудом отрываешься только в четыре часа ночи.

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

Чуть ли не всю книгу хочется цитировать. Я понавыписывал целую кучу цитат, и несколькими из них хочу поделиться с вами (из первых трех интервью с Завински, Фитцпатриком и Крокфордом).

Читать цитаты