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

Управление DOM-структурой в 1С-Битрикс: BX.setUnselectable() и BX.setSelectable()

Функции ядра 1С-Битрикс позволяют мгновенно запретить или разрешить выделение текста на любом DOM-узле. Это полезно, когда вы создаёте drag-and-drop-интерфейсы, интерактивные меню или карточки, где случайная подсветка портит UX. Ниже — полное руководство с актуальными, проверенными примерами.

Управление DOM-структурой. BX.setUnselectable/BX.setSelectable

Что делают функции

BX.setUnselectable(node); // запрещает выделение всего, что находится внутри node
BX.setSelectable(node);   // возвращает стандартное поведение
  • node — DOM-элемент или его id.
  • Работают сразу после вызова, без ожидания BX.ready, если элемент уже присутствует в DOM.
  • Учитывают все вендорные префиксы (-webkit-, -ms-, -moz-) и добавляют обработчик selectstart для старых IE, поэтому кросс-браузерность уже «вшита».

Пример 1. Запрет выделения заголовка

<h1 id="page-title">CRM и интеграции</h1>
<script>
BX.ready(function () {
    BX.setUnselectable(BX('page-title'));
});
</script>

Пример 2. Массовая обработка коллекции элементов

<ul id="sidebar">
    <li class="sidebar-item">Пункт 1</li>
    <li class="sidebar-item">Пункт 2</li>
    <li class="sidebar-item">Пункт 3</li>
</ul>
<script>
BX.ready(function () {
    /* Ищем ВСЕ дочерние элементы с классом .sidebar-item */
    var items = BX.findChildren(BX('sidebar'), {className: 'sidebar-item'}, true);
    /* Кросс-браузерный классический цикл */
    for (var i = 0; i < items.length; i++) {
        BX.setUnselectable(items[i]);
    }
});
</script>

Работает даже в IE 11 и во всех актуальных браузерах.

Пример 3. Временное отключение выделения при drag-and-drop

<style>
#drag-box{
    width:150px;
    height:150px;
    background:#f4f6f8;
    cursor:move;
    position:absolute;   /* критично для перемещения */
    left:0;
    top:0;
    display:flex;
    align-items:center;
    justify-content:center;
    user-select:none;    /* fallback, если JS не прогрузился */
}
</style>
<div id="drag-box">Перетащи&nbsp;меня</div>
<script>
BX.ready(function () {
    var box    = BX('drag-box');
    var isDrag = false, shiftX = 0, shiftY = 0;
    /* Унификация координат для тач- и мышиных событий */
    function point(e){
        return (e.touches && e.touches[0]) ? e.touches[0] : e;
    }
    function start(e){
        e = point(e);
        e.preventDefault();                 // убираем первичное выделение
        isDrag = true;
        shiftX = e.clientX - box.offsetLeft;
        shiftY = e.clientY - box.offsetTop;
        BX.setUnselectable(document.body);  // глобальный запрет на время перетаскивания
    }
    function move(e){
        if (!isDrag) return;
        e = point(e);
        box.style.left = (e.clientX - shiftX) + 'px';
        box.style.top  = (e.clientY - shiftY) + 'px';
    }
    function end(){
        if (!isDrag) return;
        isDrag = false;
        BX.setSelectable(document.body);    // возвращаем выделение
    }
    /* бинды с учётом passive:true по умолчанию на touch-событиях */
    BX.bind(box,      'mousedown',  start);
    BX.bind(box,      'touchstart', start, {passive:false});
    BX.bind(document, 'mousemove',  move);
    BX.bind(document, 'touchmove',  move,  {passive:false});
    BX.bind(document, 'mouseup',    end);
    BX.bind(document, 'touchend',   end);
});
</script>

Дополнительные лайфхаки

Ситуация Решение
Нужно сохранить запрет даже при отключённом JavaScript Добавьте CSS-класс .noselect { user-select:none; } в верстку, а в скрипте вызывайте BX.addClass(node, 'noselect') совместно с BX.setUnselectable(node).
Требуется инвертировать правило динамически Храните состояние в data-атрибутах и вызывайте нужную функцию при клике/change.
Нужно массово запретить выделение для блоков, создаваемых по AJAX После вставки новых узлов в DOM сразу проходите по коллекции: BX.findChildren(container, {...}, true) и применяйте BX.setUnselectable.

Коротко о производительности

  • Функция меняет только inline-стили выбранного элемента, поэтому не вызывает рекалькуляцию стилей всего документа.
  • Слушатель selectstart добавляется «лениво» — один раз, без дублирования, что полезно для элементов, создаваемых в цикле.

Итоги

BX.setUnselectable() и BX.setSelectable() — быстрый и надёжный способ держать интерфейс «чистым» от случайной подсветки текста. Исправленные примеры выше подтверждают, что при правильной верстке и минимальном коде можно избежать проблем даже в самом консервативном браузере. Используйте функции точечно, комбинируйте с CSS-классами и не забывайте возвращать выделение после drag-операций — это залог дружелюбного UX в любом проекте на 1С-Битрикс.

Теги:  DOM, BX.setUnselectable, BX.setSelectable, JavaScript, веб-разработка, UX, drag-and-drop


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

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

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

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

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

Лечение сайтов от вирусов

восстановление сайта и подъем версии PHP

от 25 000 рублей
Лечение сайтов на решениях АСПРО и прочих.

* полный комплекс лечения проекта и закрытия дыр

Разработка интернет-магазина с готовой версткой

от 4 недель

от 90 000 рублей

* указана минимальная стоимость. Стоимость выбранной лицензии «1С-Битрикс» оплачивается отдельно.