Контекст выполнения коллбэков

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


Базовые принципы контекста

Внутри большинства коллбэков Tooltipster значение this указывает на экземпляр подсказки (instance). Это не DOM-элемент и не глобальный объект, а специальный API-объект Tooltipster, через который осуществляется управление подсказкой.

Пример:

$('.tooltip').tooltipster({
    functionReady: function(instance, helper) {
        console.log(this === instance); // true
    }
});

Ключевые особенности:

  • this === instance
  • доступ к методам Tooltipster осуществляется через this или instance
  • helper содержит вспомогательные данные (DOM-элементы, состояние)

Объект instance

Экземпляр (instance) — центральная точка управления подсказкой. Через него доступны методы:

  • open(), close()
  • content()
  • status()
  • option()
  • destroy()

Пример использования внутри коллбэка:

functionBefore: function(instance, helper) {
    if (instance.status().open) {
        instance.close();
    }
}

Контекст (this) полностью дублирует instance, поэтому допустим альтернативный синтаксис:

this.close();

Объект helper

Второй аргумент большинства коллбэков — helper. Он предоставляет доступ к связанным DOM-элементам и метаданным.

Структура helper:

{
    origin: HTMLElement,   // исходный элемент
    tooltip: HTMLElement,  // DOM подсказки
    event: Event           // событие, вызвавшее коллбэк (если есть)
}

Пример:

functionReady: function(instance, helper) {
    console.log(helper.origin);   // элемент, к которому привязана подсказка
    console.log(helper.tooltip);  // DOM самой подсказки
}

Контекст в разных коллбэках

functionInit

Вызывается при инициализации.

functionInit: function(instance, helper) {
    // this === instance
}

Контекст уже полностью готов, но DOM подсказки ещё не создан.


functionBefore

Срабатывает перед открытием подсказки.

functionBefore: function(instance, helper) {
    // можно отменить открытие
    return false;
}

Контекст позволяет:

  • управлять логикой открытия
  • менять контент до отображения

functionReady

Вызывается после того, как подсказка добавлена в DOM.

functionReady: function(instance, helper) {
    $(helper.tooltip).addClass('custom');
}

Контекст здесь особенно важен, так как доступны:

  • DOM подсказки
  • полный API instance

functionAfter

Срабатывает после открытия.

functionAfter: function(instance, helper) {
    // финальные действия после показа
}

Контекст не изменяется, но состояние подсказки уже “открыто”.


functionClose

Вызывается перед закрытием.

functionClose: function(instance, helper) {
    console.log(instance.status().open); // true
}

Контекст используется для:

  • логики отмены закрытия
  • очистки состояния

functionAfterClose

Вызывается после закрытия.

functionAfterClose: function(instance, helper) {
    // подсказка уже закрыта
}

Особенности контекста в стрелочных функциях

Стрелочные функции не имеют собственного this, поэтому использовать их в коллбэках Tooltipster не рекомендуется.

Неправильный пример:

functionReady: (instance, helper) => {
    console.log(this); // не instance
}

Правильный подход — использовать обычные функции:

functionReady: function(instance, helper) {
    console.log(this); // instance
}

Потеря контекста и способы её предотвращения

При передаче методов instance в сторонние функции возможно “потеря” контекста.

Проблемный пример:

setTimeout(this.close, 1000);

В этом случае this внутри close будет указывать не на instance.

Решения:

1. bind

setTimeout(this.close.bind(this), 1000);

2. замыкание

var self = this;

setTimeout(function() {
    self.close();
}, 1000);

Взаимодействие с jQuery-контекстом

Важно не путать:

  • this внутри Tooltipster-коллбэка
  • this внутри jQuery-обработчика

Пример:

$('.tooltip').on('click', function() {
    console.log(this); // DOM-элемент
});

В Tooltipster:

functionReady: function(instance, helper) {
    console.log(this); // instance
}

Для доступа к DOM-элементу:

helper.origin

Комбинированное использование instance и helper

Частая практика — одновременное использование API и DOM:

functionReady: function(instance, helper) {
    var $tooltip = $(helper.tooltip);

    if (instance.status().open) {
        $tooltip.fadeIn();
    }
}

Контекст при динамическом обновлении контента

Tooltipster позволяет изменять содержимое “на лету”:

functionBefore: function(instance, helper) {
    instance.content('Загрузка...');
}

Здесь важно:

  • контекст (this) уже активен
  • изменения применяются до рендера

Контекст в пользовательских событиях Tooltipster

Tooltipster генерирует собственные события, которые можно отслеживать:

instance.on('reposition', function() {
    console.log(this); // instance
});

Контекст сохраняется и в пользовательских событиях.


Вложенные коллбэки и область видимости

При использовании вложенных функций контекст может изменяться:

functionReady: function(instance, helper) {
    setTimeout(function() {
        console.log(this); // window / undefined
    }, 1000);
}

Решения аналогичны:

  • bind
  • сохранение this в переменную
  • использование стрелочной функции (в данном случае допустимо)
setTimeout(() => {
    console.log(this); // instance
}, 1000);

Практика: управление поведением через контекст

Пример комплексного использования:

$('.tooltip').tooltipster({
    functionBefore: function(instance, helper) {
        if ($(helper.origin).hasClass('disabled')) {
            return false;
        }
    },
    functionReady: function(instance, helper) {
        this.content('Обновлённый текст');
    },
    functionAfter: function(instance) {
        this.option('theme', 'tooltipster-light');
    }
});

Здесь контекст используется для:

  • управления доступом
  • изменения контента
  • динамической настройки параметров

Итоговые принципы работы с контекстом

  • this всегда указывает на instance (если используется обычная функция)
  • instance — основной API объект
  • helper — источник DOM и событий
  • стрелочные функции нарушают контекст Tooltipster
  • при асинхронности требуется явное управление this
  • контекст сохраняется во всех встроенных коллбэках и событиях библиотеки