Root /ArchiveAbout
()

«js-core» — JavaScript framework

«js-core» JavaScript framework

Не так давно я начал заниматься разработкой JavaScript framework'а «js-core» для применения в небольших проектах, в которых использование таких готовых универсальных решений, как «Prototype», «MooTools» или «jQuery» является не оправданным, в связи с достаточно большим объемом кода, большая часть которого не используется. Framework получился легкий (в несжатом виде версия 2.5.1 занимает около 15кб), но в тоже время достаточно функциональным.

При разработке «js-core» я ориентировался на опытных программистов, поэтому постарался исключить как можно больше лишних проверок. Например, «jQuery» может автоматически подставить вместо переданного параметра «class» значение «className», либо позволить ввести сразу «className», в связи с чем, каждый раз при использовании метода «attr» идет проверка и подстановка соответствующего значения. Так же в «js-core» активно применяется расширение стандартных прототипов встроеных объектов, поэтому не забывайте делать проверку «hasOwnProperty» в конструкиции «for(…in…)». Чтобы не делать такую проверку в framework'е предумотрены методы «object.each(fn, [arg])», «$.foreach(object, fn)», а также реализован метод «array.forEach(fn, context)» для старых браузеров, не поддерживающих его.

Для начала, рассмотрим пример, демонстрирующий упрощенный принцип работы JavaScript framework'а.

// Глобальный объект с набором частоиспользуемых
// функций, на основе которых построено большинство
// методов framework'а.
var core = {
    // Определение версии «Internet Explorer»
    ie: 0 /*@cc_on + @_jscript_version * 10 % 10 @*/,
    // …
    // и другие атрибуты и методы.
    // …
};

// Главная функция-конструктор.
function _$(arg) {
    // В атрибут «node» нового объекта запоминаем ссылку на DOM-узел
    this.node = typeof arg == 'string' ? document.getElementById(arg) : arg;
}

// Методы работы с DOM-узлами,
// доступные через прототип функции «_$».
_$.prototype = {
    parent: function() {
    // Возвращаем новую копию объекта «_$»
    // с сылкой на родительский узел
    // текущего элемента.
    return new _$(this.node.parentNode);
    },
    html: function(html) {
    // Если указан входной параметр «html»,
    // то заменяем «innerHTML» текущего узла
    // на переданный во входном параметре.
    if(typeof html != 'undefined') {
        this.node.innerHTML = html;
        return this;
    }
    // Иначе возвращаем «innerHTML» текущего узла.
    else return this.node.innerHTML;
    },
    // …
    // здесь же и все остальные методы.
    // …
};

// Функция, сокращающа запись создания
// новой копии объекта «_$».
function $(arg) {
    return new _$(arg);
}

// Дополнительные методы
$.n = function(tag) {
    // Возвращаем новую копию объекта «_$»
    // с сылкой на новый узел с именем тега,
    // указанным в параметре «tag».
    return new _$(document.createElement(tag));
};

Как видим, каждый раз во время выполнения функции «$» происходит конструирование нового объекта, который содержит всего одну ссылку «node» на DOM-узел, но через прототип функции-конструктора «_$» для него доступен набор методов, работающих с текущим узлом по этой ссылке.

В «js-core» реализовано кэширование для ссылок на DOM-узлы, полученных по идентификатору. То есть метод «document.getElementById» выполняется всего один раз для каждого запрашиваемого узла с идентификатором. Это позволяет повысить производительность в некоторых ситуациях.

В весрии 2.5.1 реализовано более 50-и методов, позволяющих JavaScript-программисту сразу приступить к написанию веб-приложения, не затрачивая время на подготовку основы для его работы. Рассмотрим некоторые из них.

Функция $(…)

Для получения новой копии объекта «_$» используется функция «$(…)», которая может принимать строку, содержащую идентификатор или ссылку на DOM-узел. Допустим, у нас есть узел <DIV> с идентификатором «test», тогда мы можем выполнить следующее:

var obj = $('test');
// или
var node = document.getElementById('test');
var obj = $(node);

Далее, чтобы сократить запись, запомним, что все функции, возвращающие один узел, возвращают его в обертке — новой копии объекта «_$» c атрибутом «node», содержащим ссылку на этот DOM-узел. А функции, возвращающие набор значений, отдают нумерованный массив или «DOMNodeList» ссылок на узлы. Некоторые функции (css, attr) могут возвращать как одиночные значения, так и массивы, в зависимости от количества входящих параметров.

Функция exist(…)

В отличие от «jQuery» в «js-core» не проверяется каждый раз наличие элемента, поэтому если, попытаться выполнить некоторые методы с несуществующим узлом, произойдет ошибка. Для случаев, когда элемент может отсутствовать, предусмотрен метод «exist», который может принимать в качестве входных параметров 2 функции: 1-я выполнится, если указанный элемент существует, 2-я выполнится, если такой элемент отсутствует.

$('test').exist(
    function() {
    // По ссылке «this» доступен текущий DOM-узел
    $(this)…
    },
    function() {
    alert('Элемент отсутствует');
    }
);

Так же функцию «exist» можно вызывать без параметров. В этом случае она вернет логическое значение «true» или false».

if($('test').exist()) {…}

Функции append(…) и prepend(…)

Для добавления нового дочернего узла или перемещения уже существующего в список дочерних элементов текущего узла используются функции «append(…)» и «prepend(…)». Первая функция добавляет элемент в конец списка дочерних элементов, вторая — в начало.

$('test').append('h1');
// или
var node = document.createElement('h1');
$('test').append(node);
// а так же
var node = document.getElementById('some-id');
$('test').append(node);

Функции html(…) и text(…)

Можно продолжить предыдущую цепочку и сразу же добавить в новый дочерний узел какой-нибудь текст или HTML-код:

$('test').append('h1').text('Hello World!');
// или
$('test').append('h1').html('<span>Hello</span> World!');

Для тех, кто хорошо знает «jQuery» сразу становится видно отличие «js-core» в работе с элементами в пределах одной цепочки вызовов. В «jQuery» метод «html» заменил бы «innerHTML» DOM-элемента с идентификатором «test», а в «js-core» работа ведется с последним используемым узлом, в данном примере это заголовок первого уровня <H1>.

Функции after(…) и before(…)

Создают новый узел после (перед) текущим или переносят существующий.

$('test').after('p').text('example');
$('test').after(document.getElementById('some-id'));
$('test').before(document.createElement('span')).html('example');

Функции appendTo(…) и prependTo(…)

Переносят текущий узел в конец (начало) списка дочерних элементов узла, переданного в качестве входного параметра (ссылка на DOM-элемент или строка, содержащая идентификатор узла).

$('test').appendTo('some-id');
$('test').prependTo(document.body);

Функции insertAfter(…) и inserBefore(…)

Ставят текущий узел после (перед) указанного узла (ссылка на DOM-элемент или строка, содержащая идентификатор узла).

$('test').insertAfter(document.getElementsByTagName('div')[0]);
$('test').inserBefore('some-id');

Функции next(…) и prev(…)

Возвращают первый соседний справа или слева элемент. В качестве входного параметра может приниматься строка и именем тега. Если входной параметр не указан, то возвращается первый соседний узел с «nodeType == 1».

$('test').next('blockquote');
$('test').prev();

Если соседний элемент отсутствует, функция вернет «undefined».

Функция child(…)

Возвращает массив дочерних элементов. Для фильтрации элементов в качестве первого параметра функции можно указать строку или массив строк, содержащих имена тегов. Если указан второй параметр «true», то поиск элементов производится по всем вложенным узлам.

$('test').child('input select textarea', true);
$('test').child(['div', 'p']);

Функция parent(…)

Возвращает родительский элемент текущего узла.

$('test').parent();

Функции remove(…) и empty(…)

Удаляют и очищают текущий узел соответственно.

$('test').remove();
$('test').empty();

Заметим, что функция «empty» возвращает текущую копию объекта «_$», поэтому мы можем продолжить работу с узлом.

$('test').empty().append('h1').text('example');

Полный перечень методов «js-core» можно посмотреть на главной странице проекта. Для каждой функции указаны все возможные комбинации параметров. В ближайшее время постараюсь сделать, что-то вроде «sheatsheet» по всем функциям.

Сейчас framework используется здесь и на сайте «ЗАО КЛФЗ».

Похожие темы