Перейти к содержанию

Расширение ui.viewer открывает файл поверх страницы: изображение, видео, аудио, PDF, текстовый файл или файл с кодом. Разработчик размечает ссылку на файл набором data-атрибутов, а расширение само перехватывает клик по ней, определяет тип файла и показывает подходящий просмотрщик.

Используйте расширение, когда пользователь работает с файлами, которые уже лежат в файловом хранилище: вложения к записи, документы карточки, изображения галереи. Файл не нужно скачивать, чтобы посмотреть его содержимое, а несколько файлов одной записи можно листать стрелками.

Серверную разметку строит класс \Bitrix\Main\UI\Viewer\ItemAttributes модуля main, интерфейс просмотра — JavaScript-расширение ui.viewer модуля ui.

Подключить расширение

Загрузите ui.viewer на той странице, где выводятся ссылки на файлы.

\Bitrix\Main\UI\Extension::load('ui.viewer');

При загрузке расширение подписывается на клик по документу. Обработчик ищет атрибут data-viewer у элемента, по которому кликнул пользователь, и у семи его родителей. Отдельно назначать обработчик каждой ссылке не нужно.

Просмотрщик всегда открывается в верхнем окне. Если страница выводится в iframe — например, в боковой панели, — расширение догружает себя в верхнее окно и передает управление его экземпляру. Поэтому просмотр не обрезается границами фрейма.

Разметить ссылку на файл

Объект ItemAttributes собирает набор атрибутов для одного файла. Создают его статическими методами, а не через new: конструктор закрыт.

|

|| Метод | Описание || || buildByFileId($fileId, $sourceUri) | Читает данные файла из файлового хранилища по идентификатору. Если файла нет, выбрасывает ArgumentException || || tryBuildByFileId($fileId, $sourceUri) | То же, но вместо исключения для несуществующего файла возвращает объект с типом unknown || || buildByFileData(array $fileData, $sourceUri) | Берет готовый массив данных файла. Если в массиве нет ключа ID, выбрасывает ArgumentException || || tryBuildByFileData(array $fileData, $sourceUri) | То же, но вместо исключения для пустого массива возвращает объект с типом unknown || || buildAsUnknownType($sourceUri) | Создает объект без данных файла. Просмотрщик покажет заглушку с кнопкой скачивания || |#

Параметр $sourceUri — адрес, по которому браузер получит сам файл. По этому же адресу просмотрщик запрашивает служебные данные, поэтому точка отдачи файла должна быть подготовлена, а не вести на произвольный обработчик.

Методы с приставкой try подходят там, где файл мог быть удален, а разметку нужно вывести в любом случае. Методы buildByFileId() и buildByFileData() подходят там, где отсутствие файла — ошибка данных и ее нужно увидеть.

Объект приводится к строке, поэтому его подставляют прямо в тег. Для одного файла тег может быть любым: ссылка, блок, изображение.

Пример. Ссылка открывает в просмотрщике файл с идентификатором 2208, который отдает страница /local/show-file.php.

<?php

use Bitrix\Main\UI\Extension;
use Bitrix\Main\UI\Viewer\ItemAttributes;

Extension::load('ui.viewer');

$attributes = ItemAttributes::tryBuildByFileId(2208, '/local/show-file.php?fileId=2208');
$attributes->setTitle('Спецификация оборудования.pdf');
?>

<a href="#" <?= $attributes ?>>Спецификация оборудования.pdf</a>

Метод setTitle() задает заголовок в шапке просмотрщика. Метод экранирует значение, поэтому передавать его через htmlspecialcharsbx() заранее не нужно.

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

  • data-viewer — метка для обработчика клика,
  • data-viewer-type — тип просмотрщика,
  • data-src — адрес файла.

Тип определяется по CONTENT_TYPE файла, а если он не распознан, дополнительно по расширению имени файла.

У изображения, которое меньше окна просмотра, появляется и четвертый атрибут data-viewer-resized. По нему просмотрщик показывает исходный файл и не запрашивает у сервера уменьшенную копию.

Внимание

Если размеченный элемент не ссылка и лежит внутри ссылки с атрибутом target="_blank", просмотрщик не откроется. Обработчик пропускает такой клик и оставляет переход по внешней ссылке.

Подготовить точку отдачи файла

Просмотрщик обращается к адресу из data-src не только за содержимым файла. Сначала он запрашивает по этому адресу служебные данные: готовую разметку, уменьшенную копию изображения или состояние конвертации. Служебный запрос отличается заголовками, и разбирает его класс \Bitrix\Main\UI\Viewer\PreviewManager.

|

|| Заголовок или параметр запроса | Что просит просмотрщик || || BX-Viewer | Готовый HTML для показа файла и данные для плеера || || BX-Viewer-image | Изображение, уменьшенное до размеров окна просмотра || || BX-Viewer-src | Адрес исходной страницы, от которого строятся ссылки внутри ответа. Сам по себе служебный ответ не запускает и работает вместе с другими заголовками || || BX-Viewer-force-transformation | Запуск конвертации файла заново, если предыдущая не дала результата || || BX-Viewer-check-transformation | Проверку, готова ли конвертированная копия || || ibxPreview | Содержимое конвертированной копии файла || || ibxShowImage | Исходное изображение без уменьшения || |#

Разбирать эти заголовки самостоятельно не нужно: класс PreviewManager встроен в стандартную отдачу файла.

Внимание

Отдавайте файл методом \CFile::viewByUser() или объектом \Bitrix\Main\Engine\Response\BFile. Если обработчик читает файл с диска сам, служебный запрос до PreviewManager не дойдет и просмотрщик покажет ошибку.

Метод \CFile::viewByUser() принимает массив данных файла и массив настроек отдачи.

Пример. Отдельная страница подключает ядро Bitrix Framework, проверяет права текущего пользователя и отдает файл вместе со служебными ответами просмотрщика.

<?php

require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';

use Bitrix\Main\Context;

$fileId = (int)Context::getCurrent()->getRequest()->get('fileId');

// здесь проверяем, можно ли текущему пользователю смотреть этот файл

$file = \CFile::getFileArray($fileId);
if (!$file)
{
    \CHTTP::setStatus('404 Not Found');

    die();
}

\CFile::viewByUser($file, ['cache_time' => 0]);

Передавайте в метод \CFile::viewByUser() массив данных файла, а не идентификатор. Служебный запрос просмотрщика распознается по ключу ID в этом массиве, и с одним идентификатором проверка не пройдет.

Основные ключи массива настроек.

  • cache_time — время кеширования ответа в секундах. По умолчанию 10800.

  • force_download — отдает файл на скачивание вместо показа в браузере.

  • attachment_name — имя файла в ответе, если оно должно отличаться от исходного.

  • content_type — тип содержимого, если он должен отличаться от записанного в файловом хранилище.

Второй способ — вернуть объект \Bitrix\Main\Engine\Response\BFile из действия контроллера. Объект сам читает данные файла и сам вызывает отдачу.

Пример. Действие контроллера отдает файл для просмотра в браузере.

<?php

namespace Vendor\Catalog\Controller;

use Bitrix\Main\Engine\Controller;
use Bitrix\Main\Engine\Response\BFile;
use Bitrix\Main\Error;

class Document extends Controller
{
    public function viewAction(int $fileId): ?BFile
    {
        // проверяем права текущего пользователя кодом своего модуля
        if (!$this->isViewAllowed($fileId))
        {
            $this->addError(new Error('Access denied'));

            return null;
        }

        return BFile::createByFileId($fileId)->showInline(true);
    }
}

Метод showInline(true) отдает файл для показа в браузере. Без него ответ уходит с заголовком на скачивание.

Права доступа просмотрщик не проверяет: он только запрашивает файл по тому же адресу, который уже стоит в разметке. Проверку выполняет точка отдачи файла, и она же решает, показывать файл или ответить ошибкой.

Листать несколько файлов

Файлы одной записи объединяют в группу. Просмотрщик покажет стрелки для перехода между файлами, а если хотя бы у одного файла группы задан адрес миниатюры — еще и ленту миниатюр внизу окна.

|

|| Метод | Описание || || setGroupBy($id) | Задает идентификатор группы. Метод экранирует значение || || getGroupBy() | Возвращает идентификатор группы или null || || unsetGroupBy() | Убирает файл из группы || |#

Идентификатор группы должен быть уникальным на странице. Когда пользователь кликает по файлу, расширение ищет в том же документе все элементы с атрибутом data-viewer и таким же значением data-viewer-group-by, собирает из них список и открывает просмотр с того файла, по которому был клик.

Пример. Три вложения одной записи открываются как один список: пользователь листает их стрелками, не закрывая просмотрщик.

<?php

use Bitrix\Main\UI\Viewer\ItemAttributes;

$groupId = 'catalog-document-42';

foreach ($documents as $document)
{
    $attributes =
        ItemAttributes::tryBuildByFileId($document['FILE_ID'], $document['URL'])
            ->setTitle($document['NAME'])
            ->setGroupBy($groupId)
    ;

    echo '<a href="#" ' . $attributes . '>' . htmlspecialcharsbx($document['NAME']) . '</a>';
}

Внутри группы работают клавиши: стрелка вправо и пробел показывают следующий файл, стрелка влево — предыдущий, клавиша Esc закрывает просмотрщик.

По умолчанию список замкнут в кольцо: за последним файлом снова идет первый. Чтобы листание останавливалось на краях, выключите кольцо для группы методом setOptionsByGroup(). Тогда на первом и последнем файле стрелка скрывается.

Пример. Группа листается без зацикливания.

BX.UI.Viewer.Instance.setOptionsByGroup('catalog-document-42', { cycleMode: false });

Дополнить разметку файла

Кроме заголовка и группы объект принимает необязательные настройки. Они меняют то, как просмотрщик показывает файл и какие кнопки выводит в шапке.

|

|| Метод | Описание || || setViewerType($type) | Переопределяет тип просмотрщика, выбранный по CONTENT_TYPE || || setTypeClass($class) | Задает имя JavaScript-класса, который покажет файл. Нужно для своего типа файла || || setExtension($extension) | Задает расширение, которое просмотрщик загрузит перед показом файла || || setSources($sources) | Передает готовый список источников видео. Каждый элемент — массив с ключами src и type. Без него плеер запрашивает источники у сервера || || setWidth($width) и setHeight($height) | Задают размеры окна видео. Работают вместе со списком источников || || setAttribute($name, $value) | Добавляет произвольный атрибут || || unsetAttribute($name) | Удаляет атрибут || || getAttribute($name) | Возвращает значение атрибута или null || || getViewerType() | Возвращает тип просмотрщика, выбранный для файла || |#

Часть возможностей просмотрщика включают атрибуты, для которых отдельного метода нет. Их задают методом setAttribute().

  • data-viewer-preview — адрес миниатюры для ленты в нижней части окна. Без него просмотрщик берет миниатюру из атрибута data-thumb-src или, для изображения, из самого тега.

  • data-unified-link — постоянная ссылка на файл. Когда атрибут задан, в шапке появляется кнопка копирования ссылки.

  • data-viewer-separate-item — метка файла, который показывают без окна просмотра. Значение должно быть непустым: пустая строка в JavaScript ложна, и режим не включится. Как этим пользоваться, описано в разделе Добавить свой тип файла.

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

<?php

use Bitrix\Main\UI\Viewer\ItemAttributes;

$attributes =
    ItemAttributes::tryBuildByFileId($fileId, $videoUrl)
        ->setTitle('Инструкция по сборке.mp4')
        ->setSources([
            ['src' => $videoUrl, 'type' => 'video/mp4'],
        ])
        ->setWidth(1280)
        ->setHeight(720)
        ->setAttribute('data-unified-link', $permanentUrl)
;

Для разметки, которую собирает не PHP-шаблон, объект отдает атрибуты массивом.

  • toDataSet() — массив для свойства dataset DOM-элемента: имена атрибутов приведены к виду viewerGroupBy.

  • toVueBind() — массив для привязки атрибутов во Vue: имена оставлены как есть.

  • toString() — строка с атрибутами, тот же результат, что и при подстановке объекта в шаблон.

Добавить действия в меню

Кнопка дополнительных действий в шапке просмотрщика открывает список того, что можно сделать с файлом. Наполняет его метод addAction(): объект накапливает вызовы и отдает их в разметку одним атрибутом data-actions. Пока у файла нет ни одного действия, эта кнопка скрыта.

|

|| Ключ | Описание || || type | Тип действия. Для встроенных типов заполняет текст пункта меню || || id | Идентификатор действия, по которому его запускают из кода. Если не задан, берется значение ключа type || || text | Текст пункта меню. Заменяет текст встроенного типа || || action | Обработчик: имя JavaScript-функции строкой. Функция получает объект файла, массив params и дополнительные параметры вызова || || href | Адрес перехода. Используется, если обработчик не задан || || params | Массив, который придет в обработчик вторым аргументом || || extension | Расширение с обработчиком. Просмотрщик загрузит его перед показом файла. Можно передать массив расширений || || className | CSS-класс пункта меню || || items | Пункты выпадающего меню вместо одного действия || || disableBeforeLoaded | Блокирует пункт меню, пока файл не загрузился || |#

У шести типов действий текст уже задан:

  • download — скачивание,
  • edit — редактирование,
  • share — публикация,
  • print — печать,
  • info — сведения о файле,
  • delete — удаление.

Ключ, заданный в самом действии, важнее значения по умолчанию, поэтому текст встроенного типа можно заменить. Свое значение ключа type создает действие, у которого текст задает разработчик.

Действие с типом download в меню не попадает: адрес из ключа href становится ссылкой кнопки скачивания в шапке. Само действие добавлять не обязательно — без него кнопка скачивания ведет на адрес из data-src.

Для PDF действие print просмотрщик добавляет сам: класс BX.UI.Viewer.Document ставит печать перед действием info, а если действия info нет — в конец списка.

Пример. В меню просмотрщика появляется действие, которое удаляет вложение.

<?php

use Bitrix\Main\UI\Viewer\ItemAttributes;

$attributes =
    ItemAttributes::tryBuildByFileId($fileId, $fileUrl)
        ->setTitle('Спецификация оборудования.pdf')
        ->addAction([
            'type' => 'delete',
            'action' => 'BX.Catalog.Viewer.Actions.remove',
            'params' => [
                'documentId' => $documentId,
            ],
            'extension' => 'catalog.viewer.actions',
        ])
;

Обработчик объявляют в расширении, которое указано в ключе extension. К моменту клика по кнопке функция уже объявлена.

Пример. Обработчик получает объект файла и параметры из ключа params.

BX.namespace('BX.Catalog.Viewer.Actions');

BX.Catalog.Viewer.Actions.remove = function(item, params) {
    BX.ajax.runAction('catalog.document.delete', {
        data: { documentId: params.documentId },
    }).then(function() {
        BX.UI.Viewer.Instance.close();
    });
};

Метод clearActions() убирает все накопленные действия, метод getActions() возвращает текущий список.

Форматы файлов и конвертация

Тип просмотрщика выбирает класс PreviewManager по CONTENT_TYPE файла. Если тип не совпал ни с одним из встроенных классов, менеджер повторяет поиск по расширению имени файла.

|

|| Тип | Что открывает || || image | Изображения image/gif, image/jpeg, image/png, image/webp, image/bmp. Просмотрщик запрашивает у сервера копию, уменьшенную до 1920 пикселей по большей стороне || || video | Видео video/mp4, video/webm, video/ogg, video/quicktime, video/x-flv || || audio | Аудио audio/mp3, audio/mpeg, audio/ogg, audio/mp4, audio/x-m4a || || document | Файлы application/pdf || || code | Текстовые файлы и файлы с кодом: text/plain, text/html, text/css, text/markdown, text/csv, application/json, application/xml, application/x-php, text/javascript и другие текстовые типы. Файл больше 2 Мб открывается как неизвестный || || unknown | Остальные файлы. Просмотрщик показывает заглушку с кнопкой скачивания || |#

Офисные документы просмотрщик открывает через конвертацию в PDF. Конвертацию выполняет модуль transformer: если он установлен, файл неизвестного типа уходит на преобразование, а просмотрщик ждет результат и показывает готовую копию. Пока конвертация идет, в окне выводится сообщение о ходе работы.

|

|| Что конвертируется | Во что | Предельный размер исходного файла || || Документы doc, docx, xls, xlsx, ppt, pptx, rtf, odt, epub, djvu и другие офисные форматы | PDF | 10 Мб, для Битрикс24 — 40 Мб. Значение меняет настройка max_size_for_document_transformation модуля main || || Видео avi, mkv, wmv, 3gp и другие форматы, которые браузер не проигрывает | MP4 | 300 Мб, для коммерческого Битрикс24 — 3072 Мб. Значение меняет настройка max_size_for_video_transformation модуля main || |#

Как только сервер сообщил, что конвертация запущена, просмотрщик начинает ждать готовую копию. Если в браузере установлено соединение Push and Pull, о завершении приходит уведомление. Без соединения просмотрщик переспрашивает сервер каждые 5 секунд. Ожидание ограничено 22 секундами: после этого в окне выводится сообщение о неудачной конвертации со ссылкой на скачивание файла.

Конвертацию можно запустить заранее, не дожидаясь, пока пользователь откроет файл. Метод generatePreview() класса PreviewManager ставит файл в очередь и возвращает объект Result с ошибками постановки. Без модуля transformer метод возвращает null.

Пример. Модуль отправляет документ на конвертацию сразу после загрузки, чтобы первый просмотр не ждал преобразования.

<?php

use Bitrix\Main\UI\Viewer\PreviewManager;

$result = (new PreviewManager())->generatePreview($fileId);
if ($result !== null && !$result->isSuccess())
{
    // здесь записываем ошибки постановки в очередь в журнал
}

Без модуля transformer файл, для которого нет своего класса, так и остается типом unknown.

При любой другой ошибке загрузки просмотрщик показывает вместо содержимого файла блок с описанием ошибки, а перед этим вызывает событие BX.UI.Viewer.Controller:onItemError.

Управлять просмотрщиком из JavaScript

Экземпляр просмотрщика доступен как BX.UI.Viewer.Instance. Он создается при первом обращении и существует до перезагрузки страницы. Внутри iframe свойство возвращает экземпляр верхнего окна, поэтому обращаться к нему из фрейма можно так же, как из основной страницы.

|

|| Метод | Описание || || openByNode(node) | Открывает просмотр по размеченному элементу. Группу и список файлов собирает так же, как обработчик клика || || runActionByNode(node, actionId, params) | Запускает действие для файла, не открывая окно просмотра || || setItems(items) | Заменяет список файлов. Возвращает промис: он выполняется, когда загружены расширения, нужные действиям || || open(index) | Открывает окно и показывает файл с указанным номером в списке || || showNext() и showPrev() | Переходят к следующему и предыдущему файлу || || close() | Закрывает окно просмотра || || isOpen() | Возвращает true, если окно открыто. До первого открытия возвращает undefined || || getCurrentItem() | Возвращает объект файла, который показан сейчас || || reloadCurrentItem(options) | Пересобирает показанный файл по его элементу разметки и выводит заново. Для видео ключ forceTransformation в настройках запускает конвертацию заново || |#

Отдельный объект файла строит функция BX.UI.Viewer.buildItemByNode(node): она читает data-атрибуты элемента и возвращает объект нужного класса.

Пример. Кнопка открывает просмотр файла, размеченного ссылкой с идентификатором documentLink.

document.getElementById('openDocument').addEventListener('click', function() {
    BX.UI.Viewer.Instance.openByNode(document.getElementById('documentLink'));
});

Встроенное действие edit содержимое окна не обновляет: после того как файл сохранен, перерисуйте его сами.

Метод reloadCurrentItem() читает атрибуты исходного элемента заново и запрашивает файл у сервера. Проверка isOpen() нужна потому, что пользователь мог закрыть окно, пока шло редактирование.

Пример. Обработчик действия edit обновляет файл в окне просмотра после сохранения.

BX.Catalog.Viewer.Actions.edit = function(item, params) {
    BX.ajax.runAction('catalog.document.update', {
        data: { documentId: params.documentId },
    }).then(function() {
        if (BX.UI.Viewer.Instance.isOpen())
        {
            BX.UI.Viewer.Instance.reloadCurrentItem();
        }
    });
};

Если размеченные элементы появляются на странице после загрузки — например, их дорисовывает список, — привяжите к контейнеру делегированный обработчик функцией BX.UI.Viewer.bind(container, filter). Первый аргумент — контейнер, второй — необязательный фильтр элементов. Без фильтра обработчик реагирует на элементы с атрибутом data-viewer.

Просмотрщик вызывает события на объекте BX во время работы.

|

|| Событие | Когда вызывается || || BX.UI.Viewer.Controller:onSetItems | При замене списка файлов. Параметры: просмотрщик и новый список || || BX.UI.Viewer.Controller:onBeforeShow | Перед показом файла. Параметры: просмотрщик и номер файла в списке || || BX.UI.Viewer.Controller:onAfterShow | После показа файла. Параметры: просмотрщик и объект файла || || BX.UI.Viewer.Controller:onItemError | При ошибке загрузки файла. Параметры: просмотрщик, причина и объект файла || || BX.UI.Viewer.Controller:onClose | При закрытии окна просмотра. Параметр: просмотрщик || || BX.UI.Viewer.Controller:onFindType | Перед поиском класса по коду типа. Параметры: просмотрщик и код типа || |#

Расширение шлет эти события механизмом BX.onCustomEvent, поэтому подписываются на них функцией BX.addCustomEvent. Обработчик получает параметры по отдельности, а не одним объектом события: подписка через EventEmitter, принятая в других расширениях ui, здесь не сработает.

Пример. Обработчик читает заголовок файла, который просмотрщик только что показал.

BX.addCustomEvent('BX.UI.Viewer.Controller:onAfterShow', function(controller, item) {
    console.log(item.getTitle());
});

Встроить просмотр документа в страницу

Класс BX.UI.Viewer.SingleDocumentController показывает один PDF прямо в блоке страницы, без окна поверх нее. Под документом выводятся счетчик страниц и кнопки масштаба.

|

|| Параметр или метод | Описание || || baseContainer | Элемент, внутрь которого просмотрщик выводит документ || || stretch | Растягивает документ по ширине контейнера || || setPdfSource(source) | Задает источник документа: адрес или содержимое файла || || setScale(scale) | Задает масштаб. Значение 1 — исходный размер страницы || || print() | Отправляет документ на печать || |#

Пример. Документ выводится в блоке страницы с масштабом больше исходного, а кнопка отправляет его на печать.

const container = document.getElementById('documentContainer');
const link = document.getElementById('documentLink');

const viewer = new BX.UI.Viewer.SingleDocumentController({
    baseContainer: container,
    stretch: true,
});

viewer.setItems([BX.UI.Viewer.buildItemByNode(link)]);
viewer.setScale(1.2);
viewer.open();

document.getElementById('printDocument').addEventListener('click', function() {
    viewer.print();
});

Для остальных типов файлов встроенный показ дает базовый класс BX.UI.Viewer.InlineController. Он выводит файл в переданный контейнер и не меняет страницу вокруг: не добавляет отступ телу страницы, не меняет масштаб окна на мобильном устройстве и не перехватывает клавиши.

Добавить свой тип файла

Свой тип нужен, когда встроенные классы формат не открывают или когда файл показывают по-особому: в редакторе, на доске, во внешнем сервисе.

Серверную часть добавляют классом-наследником \Bitrix\Main\UI\Viewer\Renderer\Renderer. Класс объявляет типы содержимого, которые он берет на себя, код типа для JavaScript и разметку.

|

|| Метод | Описание || || getAllowedContentTypes() | Возвращает массив значений CONTENT_TYPE, за которые отвечает класс || || getJsType() | Возвращает код типа. Он попадает в атрибут data-viewer-type || || getSizeRestriction() | Возвращает предельный размер файла в байтах. Файл крупнее откроется как неизвестный. По умолчанию null — без ограничения || || render() | Возвращает разметку для окна просмотра. Если разметка не нужна, возвращает null, и файл показывает JavaScript-класс по данным из метода getData() || || getData() | Возвращает дополнительные данные для JavaScript-класса || |#

Готовый класс регистрируют на событии onPreviewRendererBuildList модуля main. Обработчик события возвращает объект EventResult с типом SUCCESS и массивом классов, и просмотрщик проверяет эти классы раньше встроенных. Результат с другим типом менеджер пропускает, поэтому вернуть просто массив недостаточно.

Пример. Модуль добавляет свой класс для файлов диаграмм.

<?php

use Bitrix\Main\EventManager;
use Bitrix\Main\EventResult;
use Vendor\Catalog\Viewer\Diagram;

EventManager::getInstance()->addEventHandler(
    'main',
    'onPreviewRendererBuildList',
    static fn() => new EventResult(EventResult::SUCCESS, [Diagram::class])
);

Клиентскую часть добавляют классом-наследником BX.UI.Viewer.Item и связывают с кодом типа функцией BX.UI.Viewer.addType(type, className).

Пример. Расширение связывает код типа diagram со своим классом.

BX.UI.Viewer.addType('diagram', 'BX.Catalog.Viewer.DiagramItem');

Второй способ связать разметку с классом — атрибут data-viewer-type-class с полным именем класса. Его задают методом setTypeClass(), а расширение с классом — методом setExtension(). Способ подходит, когда класс нужен не для всего типа содержимого, а для отдельных файлов.

Если в классе переопределить метод load() и пометить файл атрибутом data-viewer-separate-item с непустым значением, просмотрщик окно не откроет, а только вызовет этот метод. Так открывают файлы во внешнем редакторе или на отдельной странице. Просмотрщик обрабатывает такой файл в одиночку, даже если у него задана группа.

Связанные материалы