Фреймы
Фреймы предназначены для отображения любого контента, позволяя встраивать их в любые другие компоненты интерфейса, в том числе и в самих себя. Могут быть пустые фреймы, однако обычно они привязаны к Клиентскому объекту, то есть загружают профайл Класса/Клиентского объекта и его полей, а также загружают данные указанной записи.
Разработчик может реализовать любую верстку, но при этом использовать шаблонизацию подставляя загруженные поля, с редактором или только значение. При подстановке значений с редактором, отображение будет выполнено с учетом настроек редактора для этого поля в профайле, а также с учетом настройки редактируемости. Для не редактируемого поля не будет подключен соответствующий редактор, однако все остальные атрибуты поля будет (например, подсказка).
Базово, обычно используется верстка bootstrap (вроде еще v3). Но можете писать как хотите.
Помимо вывода полей Класса/КО, могут быть также встроены таблицы или другие фреймы, об этом упоминалось в описании таблиц.
Чтобы встроить таблицу, необходимо вывести div элемент с определенным классом и дата атрибутами, тогда при загрузки формы/фрейма в этом div будет загружена соответствующая таблица. См. описание “Таблицы. Внутри формы или фрейма (в верстке)”.
<div data-tbls="CLASS_NAME.TABLE_CO_NAME" class="fn-child-tbl-holder marTop10"></div>
Чтобы встроить фрейм, также необходимо вывести div с определенным классом и дата атрибутом.
<div data-frame="CLASS_NAME.FRAME_CO_NAME" data-ids="{+{id}+}" data-new_if_not_id="true" class="fn-child-frm-holder"></div>
data-frame. Указать имя класса и КО через точку. КО можно не указывать.
class. Должен содержать класс “fn-child-frm-holder”
data-ids. Если указано “{+{id}+}” то будет подставлено ID записи, той формы или фрейма в которое вставляется.
data-new_if_not_id. Указывает, что если id не передан, то запись открывается для создание (как новая строка в таблице). Значение будет истинно, только если строка равна “true”, во всех остальных будет false.
Можно указать и другие дата-аттрибуты, они будут переданы как params при создании фрейма
Как создать
Создание профайла
Как уже говорилось выше, вы можете не создавать отдельный профайл для таблицы, а использовать профайл класса.
Если же вам нужны особые настройки профайла, отличные от настроек профайла класса, то создайте Клиентский объект, как это описано в разделе “Создание Клиентских Объектов”.
Верстка и js
Файлы фрейма необходимо создать в кодовой базе и разместить в public_src/html/frames. Имя директории это и есть имя фрейма, а внутри должны быть одноименные html и js файлы. Опционально может быть размещен ccs файл. Как правило это имя совпадает с именем клиентского объекта или имеет вид “frame_<class_name>”.
Вы можете писать любую верстку, как уже говорилось выше.
В js файле вы также можете как угодно организовывать код, но есть несколько полезных вещей, которые следует знать.
Весь код оборачивается в самовызываемую функцию (function(){})().
Чтобы получить инстанс фрейма, напишите в самом начале (уже имеется в примере):
var frameID = MB.Frames.justLoadedId;
var frameInstance = MB.Frames.getFrame('frame_example', frameID);
Важно! Строковый первый параметр в методе getFrame нужно заменить на имя вашего фрейма.
Далее по аналогии с таблицами вы можете использовать этот инстанс. Вы можете получить настройки профайлов Класса/КО и его полей, загруженные данные, состояния (например измененные поля), родителя при наличии. А также определить функции, которые вызываются после определенных событий фрейма, таких как afterLoad, afterReload, afterAdd.
Часто для объединения всех задач конкретного фрейма используется объект frameEditor у которого есть поля для хранения состояния и различные методы, например load или setHandlers. Это лишь пример, и код можно организовыввать по другому (более современно) если в этом есть какая-либо необходимость.
Смотрите пример, и используйте как референс для копипаста C:\NET\CCS.ARLAN_SALON\public_src\html\frames\frame_example
Кнопка сохранения
В верстке можно разместить кнопку сохранения и задать ей любые стили. Пример кнопки:
<div class="save-traits mw-save-frame"><i class="fa fa-save"></i> Save</div>
Определяющим является класс mw-save-frame
Если кнопка не указана, то функция сохранения (и подсветки кнопки при наличии изменений) автоматически передается родителю, а тот в свою очередь может поступить также, вплоть до формы (при ее наличии в родителях).
Кроме этого, вы можете четко указать, кому именно делегировать сохранение, через параметр saveBtnBy (инстанс фрейма или формы).
Параметр может быть установлен в файле кода фрейма:
frameInstance.saveBtnBy = frameInstance.parent;
// Или это может быть любой другой фрейм, не обязательно среди родителей.
Если вы устанавливаете frameInstance.saveBtnBy, вы также можете сохранить собственную кнопку фрейма через верстку. Тогда будут работать обе.
Размещение в интерфейсе
В основном меню
Необходимо создать пункт меню типа “Фрейм” в редакторе меню (System->Menu editor), указать Родительский элемент (в каком пункте разместить), выбрать Класс и при желании Клиентский объект (если выбран клиентский объект, он должен быть основан на том же классе, что и выбранный класс).
Такой элемент появится в меню и при его выборе будет открыт указанный фрейм в основной контентной области.
В коде ничего писать не потребуется.
Внутри формы или фрейма (в верстке)
В верстке формы или фрейма вы можете указать специальный div элемент как описано в описании к фреймам, см выше.
Кодом, в любой контейнер
Чтобы создать фрейм кодом, нужно вызвать MB.Frames.createFrame, передав параметры и callback функцию. Если это делается внутри какого нибудь другого фрейма или формы, то при ее обновлении закрытии, надо уничтожать и дочерний созданный фрейм.
Также фрейм может создаваться при, например, переключении выбранного пункта в списке или выбранной ноды в дереве. Ниже, рассмотрим пример, который имеется в frame_example.js. Он создает соответствующий фрейм при клике на ноду, предварительно уничтожив старый (при наличии).
holder.on('select_node.jstree', function (e,a) {
var frame_class = a.node.original.item._content_class;
var frame_co = a.node.original.item._content_co;
const obj = {
container:frameEditor.frame_content,
class:frame_class,
client_object:frame_co,
parent:frameInstance,
ids:[a.node.original.item._id],
name:frame_co
}
if (frameEditor.current_frame && typeof frameEditor.current_frame.remove ==='function') {
frameEditor.current_frame.remove({remove_from_parent: true});
}
MB.Frames.createFrame(obj, (err, frame)=>{
frameEditor.current_frame = frame;
if (err) return console.error('Не удалось создать фрейм',err);
});
});
Здесь мы берем нужный класс и клиентский объект из пункта меню/ноды, по которой кликнули, если имеется старый фрейм в frameEditor.current_frame уничтожаем его, потом создаем новый и сохраняем в frameEditor.current_frame.
Поля по аналогии с таблицей. Вызывает вопросы поле ids, но там просто берется нулевой элемент. Имя в принципе может быть любое, parent может быть не указан, если, например, вы создаете фрейм в модальном окне или просто в основной контентной области.