# Ожидание элементов, переменных и событий

Методы в этом разделе помогают выполнять код после появления DOM-элементов, переменных, пользовательских событий или выполнения произвольного условия.

---

## Ожидание элемента

Функция ожидает появления одного или нескольких элементов на странице и вызывает колбэк с `NodeList`.

**Синтаксис**

```jsx
GF.waitForElement(selector, callback, minElements, interval, maximumRetries)
```

{.compact}
| Параметр | Тип | Описание |
| --- | --- | --- |
| `selector` [!badge variant="danger" text="обязательно"] | `string` | CSS-селектор элемента. |
| `callback` [!badge variant="danger" text="обязательно"] | `function` | Выполняется после нахождения элементов. Получает `NodeList` найденных элементов. |
| `minElements` | `number` | Минимальное количество элементов. По умолчанию `1`. |
| `interval` | `number` | Интервал проверки в миллисекундах. По умолчанию `100`. |
| `maximumRetries` | `number` | Максимальное число попыток. По умолчанию не ограничено. |

=== Пример использования

```jsx
GF.waitForElement('.product-item', function (elements) {
  console.log(elements);
}, 5, 100, 50);

GF.waitForElement('body', function (elements) {
  console.log(elements[0]);
});
```
===

---

## Ожидание переменной

Функция ожидает появления переменной или функции внутри `window`. Возвращает `Promise`.

**Синтаксис**

```jsx
GF.waitForVariable(variable, interval, maximumRetries)
```

{.compact}
| Параметр | Тип | Описание |
| --- | --- | --- |
| `variable` [!badge variant="danger" text="обязательно"] | `string` | Имя переменной внутри `window`. Можно указывать путь в глубину: `someLibrary.jQuery`. |
| `interval` | `number` | Интервал проверки в миллисекундах. По умолчанию `100`. |
| `maximumRetries` | `number` | Максимальное число попыток. По умолчанию не ограничено. |

=== Пример использования

```jsx
GF.waitForVariable('someLibrary.jQuery').then(function () {
  // window.someLibrary.jQuery is defined
});
```
===

---

## Подписка на события SDK

`GF.PubSub` позволяет подписываться на внутренние события скрипта. Чаще всего используются `on`, `once` и `off`.

**Синтаксис**

```jsx
const token = GF.PubSub.on(topic, callback);
GF.PubSub.once(topic, callback);
GF.PubSub.off(token);
```

{.compact}
| Метод | Описание |
| --- | --- |
| `on(topic, callback)` | Подписывает обработчик на событие. Возвращает токен подписки. |
| `once(topic, callback)` | Подписывает обработчик на одно срабатывание. |
| `off(topicOrToken)` | Отписывает по имени события или токену подписки. |
| `trigger(topic, data)` | Публикует событие асинхронно. Обычно используется внутри скрипта. |
| `triggerSync(topic, data)` | Публикует событие синхронно. |
| `has(topic)` | Проверяет наличие подписчиков. |

{.compact}
| Событие | Когда срабатывает |
| --- | --- |
| `sl-event` | После вызова `GF.API('event', ...)`. |
| `spa` | После вызова `GF.API('spa', ...)`. |
| `sl-mouse-leave-doc` | При Exit Intent. |
| `sl-event-internal` | После внутренних запросов `event`, `page` или `spa`. Используется для диагностики. |

=== Пример использования

```jsx
const token = GF.PubSub.on('sl-event', function (data) {
  console.log(data.eventName, data.properties);
});

GF.PubSub.off(token);
```
===

---

## Ожидание выполнения условия

Функция периодически проверяет условие. Если `check` возвращает `true`, вызывается `onComplete`. Если условие не выполнено до `timeout`, вызывается `onFail`.

**Синтаксис**

```jsx
GF.Utils.waitUntil(check, onComplete, onFail, delay, timeout)
```

{.compact}
| Параметр | Тип | Описание |
| --- | --- | --- |
| `check` [!badge variant="danger" text="обязательно"] | `function` | Функция, которая возвращает `true` или `false`. |
| `onComplete` [!badge variant="danger" text="обязательно"] | `function` | Выполняется после успешной проверки. |
| `onFail` | `function` | Выполняется после истечения `timeout`. |
| `delay` | `number` | Интервал проверки в миллисекундах. По умолчанию `100`. |
| `timeout` | `number` | Максимальное время ожидания в миллисекундах. По умолчанию не ограничено. |

=== Пример использования

```jsx
GF.Utils.waitUntil(
  function () {
    return document.querySelectorAll('.someElement').length === 3;
  },
  function () {
    // condition is true
  },
  function () {
    // timeout
  },
  500,
  10000,
);
```
===

---

## Отправка события при попадании элемента в экран

`GF.Utils.sendEventInViewport` отправляет событие через `GF.API('event', ...)`, когда элемент попадает в экран. Метод использует `IntersectionObserver`.

**Синтаксис**

```jsx
GF.Utils.sendEventInViewport(target, event, options)
```

{.compact}
| Параметр | Тип | Описание |
| --- | --- | --- |
| `target` [!badge variant="danger" text="обязательно"] | `string / HTMLElement` | CSS-селектор или DOM-элемент. |
| `event` [!badge variant="danger" text="обязательно"] | `string / Object` | Название события или полный объект события для `GF.API('event', ...)`. |
| `options` | `Object` | Настройки `IntersectionObserver`: `root`, `rootMargin`, `threshold`. Дополнительно можно передать `wait: true`, если элемент появляется позже. |

=== Пример использования

```jsx
GF.Utils.sendEventInViewport('.promo-banner', {
  name: 'Promo Banner Viewed',
  properties: {
    eventType: 'custom',
    bannerId: 'summer-sale',
  },
}, {
  threshold: 0.5,
  wait: true,
});
```
===
