Блог разработчика 1С-Битрикс

Обработка событий в ядре 1С-Битрикс: BX.denyEvent и BX.allowEvent

В JavaScript-ядре Bitrix Framework есть пара лаконичных, но невероятно полезных методов — BX.denyEvent() и BX.allowEvent(). С их помощью можно временно отключать и снова включать обработчики конкретного события на конкретном DOM-элементе. Это особенно удобно, когда нужно предотвратить «дребезг» событий, циклические вызовы или непреднамеренное срабатывание логики во время сложных UI-операций.

Обработка событий. BX.denyEvent/BX.allowEvent

Важно: сейчас методы влияют только на обработчики, назначенные через свойство element['on' + event] (то есть через elem.onclick = … и др.). Слушатели, добавленные BX.bind, addEventListener или jQuery, не блокируются.

Сигнатуры методов

/**
 * Запрещает указанное событие только для данного узла.
 * @param {HTMLElement} node   – DOM-элемент-адресат
 * @param {String}     type   – имя события (без «on»)
 */
BX.denyEvent(node, type);
/**
 * Снимает запрет на событие, введённый BX.denyEvent().
 * Параметры аналогичны первому методу.
 */
BX.allowEvent(node, type);

Когда это нужно

Ситуация Что даёт deny/allow
Кнопка «Сохранить» посылает AJAX-запрос, и пользователь кликает по ней многократно На время запроса блокируем click, исключая повторную отправку
Слайдер сам изменяет scrollLeft, а «scroll» триггерит тяжёлые вычисления Внутри анимации запрещаем scroll, затем включаем обратно
Массовое заполнение полей формы через скрипт Отрубаем change, чтобы не запускать валидацию на каждое поле

Практические примеры

1. Защита кнопки от «залипания» кликов

<button id="saveBtn" class="ui-btn ui-btn-primary">Сохранить</button>
<script>
BX.ready(function () {
    const btn = document.getElementById('saveBtn');
    // Бизнес-логика по «нажатию»
    btn.onclick = function handleSave () {
        // имитация долгого запроса
        BX.ajax.runAction('demo:storage.save', { data: collectFormData() })
            .then(showSuccess)
            .catch(showError)
            .finally(unlock);
    };
    // Вешаем «щелчок» исключительно во внешний код,
    // а внутри временно запрещаем прежний onclick
    BX.bind(btn, 'click', function () {
        lock();
        btn.onclick();           // вызываем основной обработчик вручную
    });
    function lock () {
        BX.denyEvent(btn, 'click');    // отключили
        btn.classList.add('ui-btn-wait');
    }
    function unlock () {
        BX.allowEvent(btn, 'click');   // включили
        btn.classList.remove('ui-btn-wait');
    }
    function showSuccess () { BX.UI.Notification.Center.notify({content: 'Сохранено!'}); }
    function showError ()   { BX.UI.Notification.Center.notify({content: 'Ошибка сохранения'}); }
});
</script>

Особенности:

  • BX.bind ставит отдельный слушатель addEventListener, поэтому не попадает под запрет.
  • Запрещаем только «нативный» onclick, предотвращая повторную отправку данных.

2. Анимация списка без «дребезга» scroll

<div id="gallery" class="gallery">
    <!-- длинная горизонтальная лента -->
</div>
<script>
BX.ready(function () {
    const box  = document.getElementById('gallery');
    box.onscroll = throttle(highlightVisibleSlide, 100);  // тяжёлый код
    function moveTo(position) {
        BX.denyEvent(box, 'scroll');      // стоп heavy-scroll
        BX.easing({
            duration : 500,
            start    : {x: box.scrollLeft},
            finish   : {x: position},
            transition: BX.easing.makeEaseOut(BX.easing.transitions.quad),
            step: state => box.scrollLeft = state.x,
            complete: () => BX.allowEvent(box, 'scroll')
        }).animate();
    }
    // пример перехода
    BX.bindDelegate(document, 'click', {className: 'js-slide-link'}, e => {
        const targetPos = Number(e.target.dataset.offset);
        moveTo(targetPos);
    });
});
</script>

Здесь мы:

  1. На время анимации полностью «глушим» scroll.
  2. После окончания плавно включаем обработчик обратно, чтобы подсветка слайдов возобновилась.

3. Массовый апдейт формы без каскада change

<script>
BX.ready(function () {
    const form = document.forms.namedItem('dealEdit');
    const inputs = Array.from(form.querySelectorAll('[data-auto-fill]'));
    // Каждый input хранит в onChange валидацию
    inputs.forEach(input => {
        input.onchange = () => validateField(input);
    });
    // Массовое заполнение
    function autoFillDemoData () {
        // временно вырубаем change у каждого поля
        inputs.forEach(i => BX.denyEvent(i, 'change'));
        // симуляция вставки данных
        BX.Promise.all(inputs.map(i => {
            i.value = getMock(i.name);
            return BX.Promise.resolve();
        })).then(() => {
            // возвращаем change
            inputs.forEach(i => BX.allowEvent(i, 'change'));
            // финальная полная валидация
            validateForm(form);
        });
    }
    BX.bind(document.getElementById('demoFill'), 'click', autoFillDemoData);
});
</script>

Советы и подводные камни

  1. Убедитесь, что используете element.on<Event>. Если обработчик назначен через BX.bind или сторонние библиотеки, запрет не подействует.
  2. Соблюдайте симметрию — всегда вызывайте BX.allowEvent после BX.denyEvent, иначе пользователь может «зависнуть» без нужной реакции интерфейса.
  3. Имена событий указываются без префикса on: 'click', 'scroll', 'change'.
  4. Исключайте вложенные блокировки: если в разных частях кода применяется denyEvent к одному элементу, продумайте порядок включения обратно, чтобы не снять запрет преждевременно.
  5. Для частого запрета/разрешения событий рассмотрите дебаунс или троттлинг вместо полного отключения. Это даст тот же эффект без риска забыть вернуть обработчик.

Заключение

BX.denyEvent и BX.allowEvent — точечный, но мощный инструмент фронтенд-разработчика в 1С-Битрикс. Они позволяют управлять жизненным циклом событий так, чтобы UI оставался отзывчивым, а логика — предсказуемой. Используйте их, когда нужно временно приостановить реакцию интерфейса, и обязательно возвращайте события в исходное состояние — тогда ваш код будет не только удобочитаемым, но и безопасным для пользователя.

Теги:  обработка событий, BX.denyEvent, BX.allowEvent, JavaScript, DOM-элементы, веб-разработка


Стоимость услуг по разработке и сопровождению сайтов на 1C-Битрикс

Разработка корпоративного сайта

от 7 дней

от 40 000 рублей

Разработка сайта без системы оплаты заказов через корзину

* стоимость зависит от наличия верстки, использования готового решения и т.д.

Перенос сайтов на «1С-Битрикс»

сайты на платформе «1С-Битрикс» — это удобство, надежность и высокая посещаемость

от 12 000 рублей
Перенос сайтов с любых CMS и статичных страниц на платформу «1С-Битрикс», с учетом дизайна, верстки и урл-адресов. С сохранением всей информации и структуры сайта.

* зависит от объема выполняемых работ.

Аутсорсинг

готов помочь, если нет времени

договорная

Могу взять на себя работы по full-stack на основе готовой верстки

* если нет верстки, то возможность верстать с Figma в режиме редактора