jQuery UI виджет, имитирующий кнопку

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

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

Объявляем наш виджет.

$.widget("trv.button", {

Так как я его изначально писал для проекта под кодовым названием «TRAVEL», то и пространство имен у меня будет особое, а не стандартное «ui». Если вы будете использовать свое пространство имен (а я настоятельно рекомендую вам это, чтобы избежать путаницы), то не забудьте переименовать классы CSS.

Далее объявляем инициализирующий метод нашего будущего виджета.

    _init: function() {
        var me = this;
        me.element
            .bind('mousedown.' + me.name, function() {
                me._down();
                return false;
            })
            .bind('mouseup.' + me.name, function () {
                me._up();
                return false;
            })
            .bind('click.' + me.name, function(event) {
                if (!me._getData('disabled')) {
                    me._trigger('press', event);
                }
                return false;
            });
    },

В этом методе подписываемся на события, связанные с нажатием левой кнопки мыши — «mousedown», «mouseup» и «click». Я не буду создавать дополнительные элементов для оформления кнопки, так-как предполагаю, что вся необходимая верстка присутствует на странице.

    destroy: function() {
        var me = this;
        me.element
            .unbind('mousedown.' + me.name)
            .unbind('mouseup.' + me.name)
            .unbind('click.' + me.name);
    },

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

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

    _down: function () {
        var me = this;

        if (!me._getData('disabled')) {
            me.element
                .addClass(me.widgetBaseClass + '-pressed')
                .one('mouseout.' + me.name, function () {
                    me._up();
                    me.element.one('mouseover.' + me.name, function () {
                        me._down();
                    });
                });

            $(document).one('mouseup.' + me.name, function () {
                me._up();
            });
        }
    },

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

Стоит заметить, что событие «mouseup» ловится на документе потому, что когда указатель мышки покинет элемент, то он уже не сможет ловить это событие.

    _up: function () {
        var me = this;
        me.element
            .unbind('mouseout.' + me.name)
            .unbind('mouseover.' + me.name)
            .removeClass(this.widgetBaseClass + '-pressed');
    }

Убираем дополнительный CSS класс с элемента, чтобы вернуть кнопку в исходное состояние, и отписываемся от событий «mouseout» и «mouseover».

});

Верстка кнопки может варьироваться вне зависимости от кода. Например, я использую такую:

<span class="trv-button">
    <span class="first-child">
        <em>Press me!</em>
    </span>
</span>

Кнопка полностью состоит из строчных элементов и теоретически может быть размещена внутри текста.

Когда на нее нажимают, то к основному элементу добавляется класс «trv-button-press». Этот класс автоматически создается из названия виджета и суффикса «-press».

Отслеживать нажатие кнопки можно через функцию обратного вызова «press» или соответствующее событие «buttonpress». Выбирайте, что вам больше нравится.