# Gallery3x: вставка галерей в визуальный редактор

# Вставка галерей в визуальный редактор

Компонент Gallery3x добавляет в визуальный редактор MODX кнопку **«Вставить из галереи»**. Она открывает окно выбора изображений текущего ресурса и вставляет в текст готовый вызов сниппета (или тег `<img>`) с ID выбранных фото. В зависимости от выбранного «вида вывода» в вызов подставляются разные чанки — сетка Fancybox, карусель, простые миниатюры и т.д.

## Поддерживаемые редакторы

- **CKEditor** — аддон `ckeditor` 1.4.x (CKEditor 4);
- **TinyMCE RTE** — аддон `tinymcerte` 3.x (TinyMCE 6).

Адаптер выбирается автоматически: скрипты Gallery3x сами определяют, какой редактор загружен на странице, и молча отключаются, если «их» редактора нет. Настройки самих аддонов CKEditor / TinyMCE RTE менять **не нужно** — кнопка регистрируется программно.

## Включение и настройка

Все настройки находятся в системных настройках MODX, пространство имён `gallery3x`, раздел «Визуальный редактор (RTE)».

<table border="1" cellpadding="6" cellspacing="0" id="bkmrk-%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-%D0%9F%D0%BE-%D1%83%D0%BC%D0%BE%D0%BB%D1%87%D0%B0%D0%BD"><thead><tr><th>Настройка</th><th>По умолчанию</th><th>Описание</th></tr></thead><tbody><tr><td>`gallery3x.rte_enable`</td><td>Нет</td><td>Включает кнопку галереи в визуальном редакторе. Главный выключатель.</td></tr><tr><td>`gallery3x.rte_templates`</td><td>пусто</td><td>На каких шаблонах показывать кнопку:  
• пусто — использовать список из `gallery3x.templates` (там же, где вкладка галереи);  
• `*` — на всех шаблонах;  
• `5,10` — только на шаблонах с этими ID.</td></tr><tr><td>`gallery3x.rte_views`</td><td>пусто</td><td>JSON-массив «видов вывода» для окна вставки. Пусто — стандартный набор (см. ниже).</td></tr></tbody></table>

После включения настройки откройте ресурс с визуальным редактором — кнопка появится в тулбаре (в CKEditor — отдельной группой в конце, в TinyMCE — в конце первого ряда). Если кнопки нет — обновите страницу менеджера со сбросом кэша браузера (Ctrl+F5).

## Окно выбора изображений

По клику на кнопку открывается окно со всеми изображениями текущего ресурса:

- **Фильтр по группе** — слева вверху; кнопка «Сбросить» возвращает все фото;
- **Миниатюры** — клик выбирает/снимает фото (Ctrl не нужен), выбор работает и между страницами пагинации;
- **Порядок кликов запоминается** — фото будут выведены на странице именно в той последовательности, в которой вы их выбирали;
- **Счётчик «Выбрано: N»** и кнопка «Сбросить выбор» — справа вверху;
- внизу — параметры вставки (см. следующий раздел) и кнопки «Вставить» / «Отмена».

## Режимы вставки

<table border="1" cellpadding="6" cellspacing="0" id="bkmrk-%D0%A0%D0%B5%D0%B6%D0%B8%D0%BC-%28%C2%AB%D0%A7%D1%82%D0%BE-%D0%B2%D1%81%D1%82%D0%B0%D0%B2%D0%B8%D1%82%D1%8C"><thead><tr><th>Режим («Что вставить»)</th><th>Что попадёт в текст</th><th>Поведение</th></tr></thead><tbody><tr><td>Выбранные фото</td><td>`[[!Gallery3x? &ids=`17,5,42` &tplOuter=`...` &tplThumb=`...`]]`</td><td>Выводятся ровно эти фото, в порядке кликов. Состав фиксированный.</td></tr><tr><td>Всю группу (динамически)</td><td>`[[!Gallery3x? &group=`Имя группы` &resource=`12` &tplOuter=`...`]]`</td><td>Выводятся все фото группы. Если позже в группу добавить фото — они появятся на странице автоматически.</td></tr><tr><td>Все фото ресурса</td><td>`[[!Gallery3x? &resource=`12` &tplOuter=`...`]]`</td><td>Вся галерея ресурса, тоже динамически.</td></tr><tr><td>Вид «Одиночное фото (тег img)»</td><td>`<img src="[[g3xGetImage? &input=`17` &options=`medium`]]" alt="...">`</td><td>На каждое выбранное фото вставляется отдельный `<img>`. Размер выбирается в поле «Размер фото» (thumb / small / medium / large / original). Адрес картинки вычисляется по ID при выводе страницы, поэтому переживает перегенерацию превью.</td></tr></tbody></table>

Флажок **«Некэшированный вызов»** (включён по умолчанию) вставляет тег как `[[!Gallery3x?...]]`. Для одиночных фото вызов всегда кэшированный — это безопасно и быстрее.

## Виды вывода

«Вид вывода» определяет, какая пара чанков подставится в вызов сниппета. Стандартный набор:

<table border="1" cellpadding="6" cellspacing="0" id="bkmrk-%D0%92%D0%B8%D0%B4-tplouter-tplthum"><thead><tr><th>Вид</th><th>tplOuter</th><th>tplThumb</th></tr></thead><tbody><tr><td>Fancybox: сетка</td><td>`tpl.Gallery3x.Fancybox.GridOuter`</td><td>`tpl.Gallery3x.Fancybox.GridItem`</td></tr><tr><td>Fancybox: фото + миниатюры</td><td>`tpl.Gallery3x.Fancybox.outer`</td><td>`tpl.Gallery3x.Fancybox.thumbItem`</td></tr><tr><td>Карусель (lightGallery)</td><td>`tpl.Gallery3x.carousel.outer`</td><td>`tpl.Gallery3x.carousel.item`</td></tr><tr><td>Простые миниатюры</td><td>`tpl.Gallery3x.static_thumbnails.outer`</td><td>`tpl.Gallery3x.static_thumbnails`</td></tr><tr><td>Одиночное фото (тег img)</td><td colspan="2">специальный вид — вставляет `<img>`, чанки не используются</td></tr></tbody></table>

### Свои виды вывода (gallery3x.rte\_views)

Набор видов задаётся JSON-массивом в настройке `gallery3x.rte_views`. Каждый элемент массива — один пункт выпадающего списка «Вид вывода» в окне вставки.

**Важно знать перед настройкой:**

- Настройка **заменяет весь набор целиком**, а не дополняет его. Если стандартные виды нужны — включите их в JSON тоже (готовый блок — в примере 1).
- Порядок элементов в JSON = порядок в выпадающем списке; первый элемент выбран по умолчанию. Вид «Одиночное фото (тег img)» добавляется в конец списка всегда автоматически.
- Вид «зашивается» в тег при вставке. Изменение `gallery3x.rte_views` влияет только на будущие вставки — уже вставленные в контент теги не изменятся (но их можно править руками прямо в тексте).
- После изменения настройки перезагрузите страницу редактирования ресурса — конфиг читается при её открытии.
- Кавычки внутри значений JSON экранируются как `\"` (см. пример 4).

<table border="1" cellpadding="6" cellspacing="0" id="bkmrk-%D0%9F%D0%BE%D0%BB%D0%B5-%D0%9E%D0%B1%D1%8F%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5-%D0%9E%D0%BF"><thead><tr><th>Поле</th><th>Обязательное</th><th>Описание</th></tr></thead><tbody><tr><td>`key`</td><td>да</td><td>Уникальный ключ вида (латиницей, без пробелов).</td></tr><tr><td>`label`</td><td>да</td><td>Название в выпадающем списке окна вставки.</td></tr><tr><td>`tplOuter`</td><td>да</td><td>Чанк-обёртка, подставится в `&tplOuter`.</td></tr><tr><td>`tplThumb`</td><td>обычно да</td><td>Чанк элемента, подставится в `&tplThumb`. Можно опустить, если обёртка сама перебирает файлы (Fenom/@INLINE, см. пример 6).</td></tr><tr><td>`snippet`</td><td>нет</td><td>Имя вызываемого сниппета. По умолчанию `Gallery3x` (пример 5).</td></tr><tr><td>`fenom`</td><td>нет</td><td>`true` — добавить в вызов `&fenom=`1`` (чанки в синтаксисе Fenom, нужен pdoTools).</td></tr><tr><td>`extra`</td><td>нет</td><td>Строка с любыми дополнительными параметрами сниппета, добавляется в конец вызова как есть: `&limit`, `&offset`, `&sortby`, `&sortdir`, `&where`, `&showInactive` и т.д.</td></tr></tbody></table>

#### Пример 1. Стандартный набор + свой вид

Самый частый случай: оставить всё как было и добавить один свой вид. Ниже — полный JSON стандартного набора, к которому в конец добавлен вид «Моя сетка» на собственных чанках:

```
[
  {"key": "fancybox_grid", "label": "Fancybox: сетка", "tplOuter": "tpl.Gallery3x.Fancybox.GridOuter", "tplThumb": "tpl.Gallery3x.Fancybox.GridItem"},
  {"key": "fancybox", "label": "Fancybox: фото + миниатюры", "tplOuter": "tpl.Gallery3x.Fancybox.outer", "tplThumb": "tpl.Gallery3x.Fancybox.thumbItem"},
  {"key": "carousel", "label": "Карусель (lightGallery)", "tplOuter": "tpl.Gallery3x.carousel.outer", "tplThumb": "tpl.Gallery3x.carousel.item"},
  {"key": "static", "label": "Простые миниатюры", "tplOuter": "tpl.Gallery3x.static_thumbnails.outer", "tplThumb": "tpl.Gallery3x.static_thumbnails"},
  {"key": "my_grid", "label": "Моя сетка", "tplOuter": "tpl.My.GridOuter", "tplThumb": "tpl.My.GridItem"}
]
```

При выборе «Моя сетка» и трёх фото в текст вставится:

```
[[!Gallery3x? &ids=`17,5,42` &tplOuter=`tpl.My.GridOuter` &tplThumb=`tpl.My.GridItem`]]
```

#### Пример 2. Fenom-виды на готовых чанках компонента

В составе Gallery3x уже есть Fenom-варианты чанков Fancybox — их можно подключить отдельными видами (нужен pdoTools):

```
[
  {"key": "fancybox_grid", "label": "Fancybox: сетка", "tplOuter": "tpl.Gallery3x.Fancybox.GridOuter", "tplThumb": "tpl.Gallery3x.Fancybox.GridItem"},
  {"key": "fb_grid_fenom", "label": "Fancybox: сетка (Fenom)", "tplOuter": "tpl.Gallery3x.Fancybox.GridOuter.fenom", "tplThumb": "tpl.Gallery3x.Fancybox.GridItem.fenom", "fenom": true}
]
```

Что вставится:

```
[[!Gallery3x? &ids=`17,5,42` &tplOuter=`tpl.Gallery3x.Fancybox.GridOuter.fenom` &tplThumb=`tpl.Gallery3x.Fancybox.GridItem.fenom` &fenom=`1`]]
```

#### Пример 3. Дополнительные параметры через extra: лимит и сортировка

Поле `extra` — точка расширения: любые параметры сниппета `Gallery3x` допишутся в конец вызова. Вид «Последние 6 фото» (удобен с режимами «Вся группа» / «Все фото ресурса» — лимит и сортировка применятся к динамической выборке):

```
[
  {"key": "last6", "label": "Последние 6 фото", "tplOuter": "tpl.Gallery3x.Fancybox.GridOuter", "tplThumb": "tpl.Gallery3x.Fancybox.GridItem", "extra": "&limit=`6` &sortby=`createdon` &sortdir=`DESC`"}
]
```

Что вставится (режим «Все фото ресурса»):

```
[[!Gallery3x? &resource=`12` &tplOuter=`tpl.Gallery3x.Fancybox.GridOuter` &tplThumb=`tpl.Gallery3x.Fancybox.GridItem` &limit=`6` &sortby=`createdon` &sortdir=`DESC`]]
```

#### Пример 4. Фильтр по полям через &amp;where (экранирование кавычек)

Параметр `&where` принимает JSON — внутри значения настройки его кавычки надо экранировать обратной косой: `\"`. Вид «Только особенные фото» (поле `special`, звёздочка в галерее):

```
[
  {"key": "special", "label": "Только особенные фото", "tplOuter": "tpl.Gallery3x.Fancybox.GridOuter", "tplThumb": "tpl.Gallery3x.Fancybox.GridItem", "extra": "&where=`{\"special\":1}`"}
]
```

Аналогично можно фильтровать по любым полям изображения: `{\"extra_num\":2024}`, `{\"description:!=\":\"\"}` и т.д.

#### Пример 5. Свой сниппет вместо Gallery3x

Если у вас есть сниппет-обёртка со своей логикой (свои дефолты, кэширование, обработка), укажите его в поле `snippet` — кнопка будет вставлять вызов именно его, передавая те же параметры (`&ids` / `&group` / `&resource` и чанки):

```
[
  {"key": "my_slider", "label": "Слайдер (свой сниппет)", "snippet": "MySlider", "tplOuter": "tpl.MySlider.outer", "tplThumb": "tpl.MySlider.item", "extra": "&autoplay=`1` &interval=`5000`"}
]
```

Что вставится:

```
[[!MySlider? &ids=`17,5,42` &tplOuter=`tpl.MySlider.outer` &tplThumb=`tpl.MySlider.item` &autoplay=`1` &interval=`5000`]]
```

#### Пример 6. @INLINE-шаблон без отдельного чанка (продвинутый, нужен pdoTools)

С `"fenom": true` обёртку можно задать прямо строкой `@INLINE` — без создания чанка. Внутри доступен массив `$files` (все поля фото + URL всех размеров: `small_url`, `medium_url`, `large_url`, `original_url`). `tplThumb` в этом случае не нужен:

```
[
  {"key": "inline_row", "label": "Ряд миниатюр (inline)", "fenom": true, "tplOuter": "@INLINE {foreach $files as $f}<a href=\"{$f.original_url}\"><img src=\"{$f.small_url}\" alt=\"{$f.alt}\"></a>{/foreach}"}
]
```

Такой вид удобен для мелких служебных вставок, когда заводить чанк избыточно. Для чего-то сложнее пары строк лучше всё же создать чанк — его проще править и переиспользовать.

#### Типовые ошибки

- Забыли включить стандартные виды в свой JSON — в списке останутся только ваши (это не поломка, но часто неожиданность).
- Невалидный JSON (лишняя запятая, неэкранированные кавычки) — компонент откатится на стандартный набор и запишет предупреждение в журнал ошибок MODX (Управление → Журнал ошибок).
- Опечатка в имени чанка — вызов вставится, но на странице галерея не выведется; проверьте имена в дереве «Элементы».
- Fenom-чанк без `"fenom": true` (или без установленного pdoTools) — на странице будет сырой текст шаблона вместо галереи.

## Изменения в сниппетах

### Gallery3x: параметр &amp;ids

`&ids=`17,5,42`` — вывод конкретных изображений по их ID (именно этот параметр использует режим «Выбранные фото»).

- ID изображения уникален на весь сайт и сам однозначно определяет фото, поэтому параметры выбора по ресурсам (`&resource` / `&resources` / `&parents`) в вызове с `&ids` не нужны и не учитываются. Иначе фото, прикреплённое к другому ресурсу, молча пропадало бы из вывода.
- Порядок вывода равен порядку перечисления ID; его можно переопределить обычным `&sortby`.
- Фильтр активности (`active = 1`), а также `&where`, `&limit`, `&showInactive` действуют как обычно.
- **Обратная совместимость полная:** на вызовы без `&ids` изменение не влияет — выполняется прежний код выборки по ресурсам.

### g3xGetImage: размер original

`[[g3xGetImage? &input=`17` &options=`original`]]` теперь возвращает URL оригинального файла (раньше были доступны только размеры превью: thumb, small, medium, large).

## Возможные проблемы и решения

<table border="1" cellpadding="6" cellspacing="0" id="bkmrk-%D0%A1%D0%B8%D0%BC%D0%BF%D1%82%D0%BE%D0%BC-%D0%9F%D1%80%D0%B8%D1%87%D0%B8%D0%BD%D0%B0-%D0%B8-%D1%80%D0%B5"><thead><tr><th>Симптом</th><th>Причина и решение</th></tr></thead><tbody><tr><td>Кнопки нет в тулбаре</td><td>Проверьте: `gallery3x.rte_enable` = Да; шаблон ресурса входит в `gallery3x.rte_templates` (или `gallery3x.templates`, если первая пуста); страница менеджера обновлена с Ctrl+F5.</td></tr><tr><td>Кнопка без иконки (пустой квадрат)</td><td>Браузер держит старый CSS/JS — обновите менеджер с Ctrl+F5.</td></tr><tr><td>CKEditor: кнопки нет при нестандартном тулбаре</td><td>Если тулбар CKEditor задан нестандартной конфигурацией, добавьте кнопку `Gallery3x` в неё вручную.</td></tr><tr><td>TinyMCE: в сохранённом тексте `&amp;` вместо `&` внутри тега MODX</td><td>Это нормально: MODX-парсер понимает `&amp;` в параметрах тегов, вывод работает.</td></tr><tr><td>TinyMCE искажает `src` у одиночного фото</td><td>Зависит от настроек конвертации URL аддона — установите `tinymcerte.relative_urls` = Нет.</td></tr><tr><td>Галерея не выводится на странице</td><td>Убедитесь, что чанки выбранного вида существуют, а вызов вставлен некэшированным (`[[!...]]`), если содержимое должно обновляться.</td></tr></tbody></table>

## Техническая справка

- `core/components/gallery3x/elements/plugins/plugin.gallery3x_rte.php` — MODX-плагин (событие `OnDocFormPrerender`): проверяет настройки и шаблон, передаёт конфиг в JS, подключает скрипты и стили;
- `assets/components/gallery3x/js/mgr/rte/gallery3x.rte.picker.js` — окно выбора (ExtJS), редактор-независимое ядро: `Gallery3x.rte.openPicker(callback)`;
- `assets/components/gallery3x/js/mgr/rte/gallery3x.rte.ckeditor.js` — адаптер CKEditor 4: регистрирует плагин и кнопку через `CKEDITOR.plugins.add` + событие `instanceCreated`/`configLoaded`;
- `assets/components/gallery3x/js/mgr/rte/gallery3x.rte.tinymce.js` — адаптер TinyMCE 6: регистрирует плагин через `tinymce.PluginManager.add` и дописывает `gallery3x` в `plugins`/`toolbar1` объекта `TinyMCERTE.editorConfig` до вызова `tinymce.init()`;
- `assets/components/gallery3x/css/mgr/rte.picker.css` — стили окна и иконка кнопки CKEditor;
- `assets/components/gallery3x/gallery3x-icon.svg` — фирменная иконка Gallery3x (мастер-копия).

Данные окно берёт через штатный коннектор компонента (`connector.php`, процессоры `File\GetList` и процессор групп из `gallery3x.groups_processor`) — работает только в контексте менеджера с активной сессией.

Чтобы подключить другой редактор, достаточно написать новый адаптер, который по своему событию вызывает `Gallery3x.rte.openPicker(function (html) { /* вставка html в редактор */ })`.