Tom Adler’s blog

блокирование кнопок и полей ввода, карринг

наверное, именно для этой задачи чаще всего используется javascript. Нужно заблокировать кнопку, чтобы пользователь не кликнул её по ошибке, и сделать блокировку заметной, чтобы он даже не пытался. Иногда вместо кнопки блокируется поле ввода.

в идеальном мире задача решается очень просто: element.disabled = true. Это сделает поле неактивным, а также применит к нему css-правила из селектора [disabled]. В реальности всенародный браузер не понимает таких селекторов, поэтому на элемент приходится навешивать дополнительный класс, например, disabled. Впрочем, это имя не всегда устраивает верстальщиков, поэтому хорошо бы иметь возможность задать другой класс.

в посте «стандарты для расширения Element.Methods» был описан шаблон функции для расширения:

function (element) {
    element = $(element);
    // …
    return element;
}

в этот шаблон мы добавляем параметр (опциональное имя класса) и пару строк, выполняющих нужные нам действия:

Element.Methods.disable = function(element, className) {
    element = $(element);
    element.disabled = true;
    element.addClassName(className || 'disabled');
    return element;
}

решение почти готово, осталась только одна деталь: в пару к функции блокирования неплохо бы иметь и ее зеркальную противоположность. Она будет отличаться только значением для свойства disabled, и работающим с именем класса методом. А для того, чтобы избежать копипаста, мы применим технику карринга (currying):

function toggle(state, method, element, className) {
    element = $(element);
    element.disabled = state;
    element[method](className || 'disabled');
    return element;
};
Element.Methods.disable = toggle.curry(true, 'addClassName');
Element.Methods.enable  = toggle.curry(false, 'removeClassName');

здесь используется шаблонная функция четырех параметров, первые два из которых мы фиксируем разными значениями для того, чтобы получить два зеркальных метода. Того же эффекта можно было добиться конструкцией типа disable = function(a, b){ toggle(1, 2, a, b) }, но метод .curry() на мой взгляд элегантнее и проще читается

, ,

pkunzip.zip 2.0

Для меня долгое время самым коротким околокомпьютерным анекдотом было «pkunzip.zip». Потом я ещё более короткий и заодно рефлексирующий «ha.ha». Время меняется, и теперь то же самое делается по-другому:

document.write('<noscript><img src="…"></noscript>')

via miscoded

,

неожиданный способ очистки массива

мои поиски русских блогов о javascript были сравнительно небезуспешными. Сейчас, просматривая один из обнаруженных блогов, нашел в нем заметку «Три варианта удаления childNodes». Она напомнила мне об одной забавной особенности яваскрипта

наверное, многие программисты на ЯВУ привыкли к тому, что у программного массива есть метаданные, которые можно напрямую прочитать. Но далеко не всем приходит в голову, что эти же данные можно и записать ; )

>>> a = [1, 2, 3]
[1, 2, 3]
>>> a.length
3
>>> a.length = 0
0
>>> a
[]

к сожалению, childNodes — это не массив, а NodeList, поэтому напрямую задать ему длину не удастся:

>>> $1.childNodes.length = 0
setting a property that has only a getter

prototype.js минус браузер

Изначально задачей разработчиков prototype было улучшить сам язык. Добавить в него синтаксического сахара, используя существующие возможности javascript, в конечном итоге приближая к ruby. Естественно, при этом решались и проблемы кроссбраузерности, но не они были основными.

Недавно в их листе рассылки увидел своеобразное подтверждение того, насколько хорошо им это удалось: Non-browser version of Prototype.js. В этой теме один программист рассказывает, как их компания использует prototype в своём серверном javascript, а другой — о подключении библиотеки к скриптам для Windows Scripting Host.

, ,

стандарты для расширения Element.Methods

Prototype.js объявляет множество удобных методов для DOM-объектов, но разработчикам всегда хочется большего. Добавить объекту новый метод очень просто, но при этом рекомендуется соблюдать несколько правил.

  1. ссылка на элемент или его id должна быть первым параметром метода, обычно его называют element
  2. первой строкой метода становится element = $(element);, чтобы быть уверенным, что дальше идет работа именно с объектом
  3. последней строкой метода становится return element;, благодаря этому можно использовать method chaining типа element.update().hide();
  4. после добавления всех желаемых методов в Element.Methods нужно вызвать Element.addMethods();

Почему нужно выполнять первый пункт? Без этого вы не сможете вызывать эту функцию как метод объекта. Дело в том, что prototype создает у всех DOM-объектов методы, имена которых совпадают с аналогами из Element.Methods, но при этом первым параметром в них передается сам DOM-объект. Поэтому, если ваша функция ожидает первым параметром что-то другое, её нельзя будет вызывать с использованием синтаксиса element.method().

, ,