VGRollup

Сворачивание контента

Управление и события

Внешняя кнопка, программное переключение, callbacks и DOM-события.

VGRollup оставляет превью текста или первые элементы списка. Кнопки раскрывают уже загруженное содержимое — запросов на сервер нет. Во всех примерах инициализация выполняется после появления разметки.

Внешняя кнопка и журнал событий

Автоматическая кнопка отключена. Основная кнопка работает через Data API; соседняя вызывает VGRollup.toggle с тем же управляющим элементом. Журнал показывает callbacks и DOM-события.

Внешняя кнопка полезна, когда действия должны находиться в собственной панели. Здесь VGRollup не создаёт автоматическую кнопку: её разметка принадлежит приложению. Модуль обновляет её подпись и aria-expanded при каждом переключении.

Кнопка «Переключить через API» обращается к тому же контейнеру и передаёт основной управляющий элемент. Благодаря этому состояние остаётся согласованным, а журнал получает одинаковые callbacks и события независимо от способа переключения.

Прочитайте текущее состояние, сверните описание и сравните записи журнала. Сначала вызывается callback, затем контейнер отправляет DOM-событие show или hide. Для инициализации доступен отдельный callback, но не DOM-событие.


HTML
<div class="rollup-demo">
    <div id="rollup-api" class="rollup-demo-copy">
        <p>Внешняя кнопка полезна, когда действия должны находиться в собственной панели. Здесь VGRollup не создаёт автоматическую кнопку: её разметка принадлежит приложению. Модуль обновляет её подпись и aria-expanded при каждом переключении.</p>
        <p>Кнопка «Переключить через API» обращается к тому же контейнеру и передаёт основной управляющий элемент. Благодаря этому состояние остаётся согласованным, а журнал получает одинаковые callbacks и события независимо от способа переключения.</p>
        <p>Прочитайте текущее состояние, сверните описание и сравните записи журнала. Сначала вызывается callback, затем контейнер отправляет DOM-событие show или hide. Для инициализации доступен отдельный callback, но не DOM-событие.</p>
    </div>
    <div class="rollup-demo-actions">
        <button id="rollup-api-toggle" type="button" class="btn btn-primary btn-sm"
            data-vg-toggle="rollup" data-vg-target="#rollup-api"
            aria-controls="rollup-api" aria-expanded="false">Развернуть заметку</button>
        <button id="rollup-api-call" type="button" class="btn btn-surface btn-sm">Переключить через API</button>
        <button id="rollup-api-read" type="button" class="btn btn-surface btn-sm">Прочитать состояние</button>
    </div>
    <output id="rollup-api-state" class="rollup-demo-result" aria-live="polite"></output>
    <pre id="rollup-api-log" class="rollup-demo-result rollup-demo-log" aria-label="Журнал VGRollup" aria-live="polite"></pre>
</div>
JavaScript
/**
 * Описание: внешнее управление VGRollup с журналом событий.
 * Возможности: Data API, статический toggle, чтение isShow, callbacks и DOM-события.
 */
import { VGRollup } from 'vgapp';

function initRollupDemo() {
    const root = document.querySelector('#rollup-api');
    if (!root || VGRollup.getInstance(root)) return;
    const control = document.querySelector('#rollup-api-toggle');
    const state = document.querySelector('#rollup-api-state');
    const log = document.querySelector('#rollup-api-log');
    const entries = [];
    const record = (message) => {
        entries.unshift(message);
        log.textContent = entries.slice(0, 12).join('\n');
    };
    const renderState = (instance) => {
        state.textContent = instance.isShow() ? 'Состояние: развёрнуто' : 'Состояние: свёрнуто';
    };
    for (const name of ['show', 'hide']) {
        root.addEventListener(`vg.rollup.${name}`, (event) => {
            record(`DOM ${name}: relatedTarget=#${event.detail.relatedTarget.id}`);
            renderState(VGRollup.getInstance(root));
        });
    }
    VGRollup.init(root, {
        height: 112,
        fade: false,
        button: { enabled: false, more: 'Развернуть заметку', less: 'Свернуть заметку' },
        callbacks: {
            init: () => record('callback init'),
            expand: () => record('callback expand'),
            collapse: () => record('callback collapse')
        }
    }, (instance) => {
        record('init callback: экземпляр получен');
        renderState(instance);
    });
    document.querySelector('#rollup-api-call').addEventListener('click', () => VGRollup.toggle(root, control));
    document.querySelector('#rollup-api-read').addEventListener('click', () => {
        const instance = VGRollup.getInstance(root);
        record(`isShow(): ${instance.isShow()}`);
        renderState(instance);
    });
}

initRollupDemo();
CSS
/* Композиция примеров; обрезкой и видимостью управляет VGRollup. */
.rollup-demo { min-width: 0; }
.rollup-demo-copy { line-height: 28px; }
.rollup-demo-copy p { margin: 0 0 1rem; }
.rollup-demo-copy p:last-child { margin-bottom: 0; }
.rollup-demo-list { margin: 0; padding-left: 1.5rem; }
.rollup-demo-item { padding: .5rem 0; }
.rollup-demo-actions { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 1.5rem; }
.rollup-demo-result {
    display: block;
    margin: 1.5rem 0 0;
    padding: .75rem;
    border: 1px solid var(--vg-border-default);
    border-radius: .5rem;
    background: var(--vg-background-secondary);
    color: var(--vg-text-primary);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}
.rollup-demo-log { max-height: 16rem; overflow-y: auto; }
.rollup-demo-empty { margin-top: 1.5rem; color: var(--vg-text-secondary); }

Публичный API

VGRollup.init(element, params, callback)
Создаёт экземпляр или использует существующий. Возвращает undefined; экземпляр доступен в callback(instance) и через VGRollup.getInstance(element). Повторный init не обновляет параметры.
VGRollup.toggle(target, relatedTarget)
Переключает содержимое и синхронизирует текст и aria-expanded переданной кнопки. Передавайте реальный управляющий элемент. Методов instance.show() и instance.hide() нет.
instance.isShow()
Возвращает текущее состояние раскрытия. Кнопка «Прочитать состояние» использует этот метод.
Data API
data-vg-toggle="rollup" и data-vg-target="#id" обрабатывают клик. Для начального сворачивания нужен явный init: один маркер data-vgrollup библиотека сама не сканирует.
Параметры из HTML
data-height, data-content, data-cnt, data-number; вложенные параметры — data-button-more, data-button-less, data-ellipsis-line. Атрибуты читаются при создании экземпляра.
build / switch / dispose
Низкоуровневые методы. switch меняет отображение без полной синхронизации кнопки и isShow; повторный build может добавить ещё одну кнопку. dispose удаляет экземпляр, но не восстанавливает разметку. Для обычного управления используйте toggle.

События и callbacks

vg.rollup.show / vg.rollup.hide
Возникают на контейнере после переключения. event.detail.relatedTarget — переданная кнопка. Это информационные события, не ожидание конца анимации.
callbacks.init(element, instance)
Вызывается при первоначальном построении, в том числе для короткого текста. Отдельного DOM-события init нет.
callbacks.expand(element, instance)
Срабатывает при раскрытии до DOM-события show.
callbacks.collapse
Для текста: (element, instance). Для списка: (element, items, instance), где items — коллекция элементов. Срабатывает до DOM-события hide.
Ограничения
Модуль не наблюдает за динамическим добавлением контента и не реализует AJAX-подгрузку. Инициализируйте текст в видимом контейнере: высота измеряется при построении.