А как выводить большое количество сообщений (довольно информативных), да и ещё, чтобы можно было на эти сообщения нажимать, открывать объекты, создавать новые прямо из этого окна? Если вы задавались таким вопросом, то надеюсь данная статья вам поможет. В самой статье, я постараюсь донести саму логику и суть реализации моей идеи. Полный код с примером будет прикреплен ниже. (Каждая скачка является мотивацией для написания новых статей)
Обязательные условия для работоспособности модуля:
- Конфигурация на УФ;
- Сбор ошибок должен всегда стартовать и завершаться на Клиенте;
Если вышеперечисленные пункты вас устраивают, то предлагаю ознакомиться с кратким описанием идеи. Итак, если нам нужно собрать сообщения в процедуре "ТекущаяИсполняемаяПроцедураНаКлиенте", то перед ней мы вызываем процедуру начала сбора сообщений (по сути это просто генератор уникального идентификатора для хранилища значений где будут временно храниться наши сообщения), а после процедуры "ТекущаяИсполняемаяПроцедураНаКлиенте" мы вызываем процедуру окончания сбора ошибок, которая почистит за собой мусор и выведет наши сообщения на форму в HTML.
Самое замечательно то, что ссылки в HTML поле уже хранят в себе наши параметры. Что позволяет работать с ними как нам захочется (открывать значения по ссылкам, создавать объекты, передавая в них наши параметры и тп.) Надеюсь, идея немного понятна, ведь она довольно простая.
А теперь немного пробегусь по основному коду и покажу реализацию примера вывода такого сообщения.
Итак, у нас есть кнопка на форме и её клиентская процедура, а также у нас будет процедура"ЛюбаяПроцедураВКоторойБудетФормированиеОшибок()", в которой у нас непосредственно и будет происходить сбор сообщений для последующего вывода на экран.
&НаКлиенте
Процедура ЛюбаяПроцедура(Команда)
GUIDОперации = СообщенияВHTMLКлиент.НачатьФормированиеHTMLСообщений();
ЛюбаяПроцедураВКоторойБудетФормированиеОшибок(GUIDОперации);
СообщенияВHTMLКлиент.ЗакончитьФормированиеHTMLСообщений(ЭтаФорма,"Сообщения в HTML поле",GUIDОперации);
КонецПроцедуры
Как мы видим, передается параметр GUIDОперации он необходим для того случая, когда сбор сообщений будет одновременно в нескольких процедурах и это нам позволит разделить данные списки сообщений (да, параметр GUIDОперации придется тащить через все вложенные процедуры и функции, этот параметр не обязательный, но тогда вы берете на себя ответственность за некорректный вывод сообщений. Повторюсь, работать будет :) ) Вообще, все параметры необязательные, ЭтаФорма нужна если мы захотим заблокировать форму вызова в момент работы с окном ошибок. Второй параметр соответственно заголовок формы HTML.
Итак, проваливаемся в процедуру ЛюбаяПроцедураВКоторойБудетФормированиеОшибок()
&НаКлиенте
Процедура ЛюбаяПроцедураВКоторойБудетФормированиеОшибок(GUIDОперации)
СообщенияВHTMLКлиент.ДобавитьСообщение("Начинаем выводить сообщения (эта строчка с отступом слева, написана жирным шрифтом и красным цветом) "
,GUIDОперации,,,Истина,Истина,Истина);
СообщенияВHTMLКлиент.ДобавитьСообщение("Выводим ссылку на контрагента (клиент) "
+ СообщенияВHTMLКлиент.СсылкаНаОбъект(Объект.Контрагент), GUIDОперации);
СообщенияВHTMLКлиент.ДобавитьСообщение("Картинка на клиенте (размещена по центру)"
+ СообщенияВHTML.ВставитьКартинку(БиблиотекаКартинок.ВнешнийИсточникДанных), GUIDОперации,Истина,Истина,,,,Истина);
ЛюбаяПроцедураВКоторойБудетФормированиеОшибокНаСервере(GUIDОперации);
СообщенияВHTMLКлиент.ДобавитьСообщение("Эта строчка последняя (сделаем отступ сверху) "
,GUIDОперации,Истина);
КонецПроцедуры
&НаСервере
Процедура ЛюбаяПроцедураВКоторойБудетФормированиеОшибокНаСервере(GUIDОперации)
СообщенияВHTML.ДобавитьСообщение("Выводим ссылку на контрагента (сервер) "
+СообщенияВHTML.СсылкаНаОбъект(Объект.Контрагент),GUIDОперации);
ТаблицаТовары = Объект.Товары.Выгрузить();
СообщенияВHTML.ДобавитьСообщение("Это сообщение где мы сможем создать "
+ СообщенияВHTML.СсылкаНаОбъектСПараметром( "новый документ поступления", ТаблицаТовары, "СоздатьДокументПоступлениеТоваров")
+ " с передачей текущей табличной части (сделаем отступ сверху и слева)",GUIDОперации,Истина,,,Истина);
СообщенияВHTML.ДобавитьСообщение("Картинка на сервере на которую можно нажать, после чего откроется контрагент"
+СообщенияВHTML.ВставитьКартинку(БиблиотекаКартинок.БизнесПроцесс,Объект.Контрагент,"ОткрытьЗначение"),GUIDОперации,,,,,,);
КонецПроцедуры
Результат выполнения данного кода:
Теперь немного подробнее о показанных процедурах:
Вариант вызова данный процедуры на сервере СообщенияВHTML.ДобавитьСообщение("");
ОписаниеСообщения непосредственно само сообщение текстом, которое мы хотим вывести;
GuidОперации - уникальный идентификатор текущего события (необязательное поле);
ОтступСверху,ОтступСнизу,ВыделитьЖирным,ОтступСлева,ВыделитьКрасным - Тип Булево - простое редактирование выводимого текста
Самое интересное, что в параметре ОписаниеСообщения мы также можем формировать ссылки на объекты, которые захотим открыть и даже сохранять в них параметры для дальнейшей обработки, все это в виде текста в формате HTML;
Пример вызова такой преобразовывающей процедуры:
СообщенияВHTMLКлиент.СсылкаНаОбъект(Объект.Контрагент,ПредставлениеОбъекта)
Вариант вызова данной процедуры на сервере СообщенияВHTML.СсылкаНаОбъект(Объект.Контрагент,ПредставлениеОбъекта)
Где Объект.Контрагент - ссылка, которую мы хотим сохранить, а ПредставлениеОбъекта (необязательное поле, по умолчанию выведет представление объекта в 1С) как ссылка должна выглядеть в HTML поле.
Посмотрим, что у неё внутри:
Функция СсылкаНаОбъект(СсылкаНаТекущийОбъект,ПредставлениеОбъекта=неопределено)
Если ПредставлениеОбъекта=неопределено тогда
ПредставлениеОбъекта=Строка(СсылкаНаТекущийОбъект);
КонецЕсли;
УникальныйИдентификатор = Новый УникальныйИдентификатор;
Адрес = ПоместитьВоВременноеХранилище(СсылкаНаТекущийОбъект, УникальныйИдентификатор);
Возврат "<A id=""" + "ОткрытьЗначение" + """ href= """+ Адрес + """ >"+ПредставлениеОбъекта+"</A>";
КонецФункции
Как видим, просто формируется строка с тегами для HTML, которые мы будем обрабатывать при нажатии.
Таким же образом, мы можем помещать во временное хранилище ссылки на Таблицы значений, Структуры, Соответствия и т.п., что дает нам больше возможностей для обработки нажатия на ссылку. К примеру, при нажатии на ссылку создать документ, загрузить в него заранее переданную таблицу значений и открыть созданный документ.
Давайте посмотрим, как это просто реализовать:
&НаСервере
Процедура ЛюбаяПроцедураВКоторойБудетФормированиеОшибокНаСервере(GUIDОперации)
ТаблицаТовары = Объект.Товары.Выгрузить();
СообщенияВHTML.ДобавитьСообщение("Это сообщение где мы сможем создать "
+СообщенияВHTML.СсылкаНаОбъектСПараметром("новый документ поступления",ТаблицаТовары,"СоздатьДокументПоступлениеТоваров")
+" с передачей текущей табличной части (сделаем отступ сверху и слева)",GUIDОперации,Истина,,,Истина);
КонецПроцедуры
Тут мы используем процедуру СообщенияВHTML.СсылкаНаОбъектСПараметром("новый документ поступления", ТаблицаТовары, "СоздатьДокументПоступлениеТоваров")
Первый параметр - представление ссылки
Второй параметр - данные, которые захотим получить при нажатии на текущую ссылку
Третий параметр (важно!!!) - ключ, по которому мы будем определять действие, которое нам нужно сделать при нажатии на ссылку
Посмотрим, что внутри процедуры:
Функция СсылкаНаОбъектСПараметром(ПредставлениеОбъекта,ДополнительныйПараметр,КлючПроцедуры)
УникальныйИдентификатор = Новый УникальныйИдентификатор;
Адрес = ПоместитьВоВременноеХранилище(ДополнительныйПараметр, УникальныйИдентификатор);
Возврат "<A id=""" + КлючПроцедуры + """ href= """+ Адрес + """ >"+ПредставлениеОбъекта+"</A>";
КонецФункции
Как видим, все по-прежнему просто.
Осталось только понять, а как обрабатывать ссылки в HTML поле? Для этого у нас есть замечательное событие у элемента "ПриНажатии"
&НаКлиенте
Процедура ОтображениеИнформацииПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка)
СтандартнаяОбработка=Ложь;
Если ВРег(ДанныеСобытия.Element.tagName) = "A" Тогда
ОбработкаНажатияНаСсылкуПоляHTML(ДанныеСобытия.Element);
ИначеЕсли ВРег(ДанныеСобытия.Element.tagName) = "IMG" Тогда
ОбработкаНажатияНаСсылкуПоляHTML(ДанныеСобытия.Element.parentElement);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ОбработкаНажатияНаСсылкуПоляHTML(ДанныеСобытия)
КлючСобытия = ДанныеСобытия.id;
Если СообщенияВHTMLОбработкаСобытийСервер.ПроверитьВерсиюПлатформы("8.3.15") тогда
ДанныеИзHTML = ДанныеСобытия.attributes[1].nodeValue;
Иначе // работает на версии 8.3.12
ДанныеИзHTML = "e1cib/tempstorage/"+ДанныеСобытия.nameProp;
КонецЕсли;
СообщенияВHTMLОбработкаСобытийКлиент.ОбработкаСобытийПоКлючам(КлючСобытия,ДанныеИзHTML);
КонецПроцедуры
Где мы обращаем внимание на процедуру СообщенияВHTMLОбработкаСобытийКлиент.ОбработкаСобытийПоКлючам(КлючСобытия,ДанныеИзHTML);
Вот где и понадобился нам ключ, который мы задавали при записи в HTML, к примеру, я передал ключ "СоздатьДокументПоступлениеТоваров", а значит в самой процедуре мы видим:
Процедура ОбработкаСобытийПоКлючам(КлючСобытия,ДанныеИзHTML) Экспорт
Если КлючСобытия="ОткрытьЗначение" тогда
ОткрытьПолученнуюСсылкуИзHTML(ДанныеИзHTML);
ИначеЕсли КлючСобытия="СоздатьДокументПоступлениеТоваров" тогда
ОткрытьДокументПоступлениеТоваров(ДанныеИзHTML);
ИначеЕсли КлючСобытия="НеОбрабатыватьНажатие" тогда
КонецЕсли;
КонецПроцедуры
Здесь в параметре КлючСобытия нам и прилетает тот самый ключ, а в параметре ДанныеИзHTML хранится адрес на наши любые переданные параметры, которые мы легко можем получить таким образом:
АВотИНашиПараметры = ПолучитьИзВременногоХранилища(ДанныеИзHTML);
Итого, у нас ключ и мы знаем что необходимо создать и открыть документ, а также имеются параметры, которые мы хотим поместить в новый документ.
(Более подробный пример есть в прикрепленном dt - файле).
Ещё довольно интересный момент, по поводу вывода картинок (в следующем примере написана функция только под "БиблиотекаКартинок", т.е для всех картинок, которые добавлены в конфигурацию, но по данному примеру я думаю не составит труда добавить функции с картинками по ссылке, либо указав путь на диске)
СообщенияВHTML.ВставитьКартинку(БиблиотекаКартинок.БизнесПроцесс,Объект.Контрагент,"ОткрытьЗначение");
Первый параметр - Картинка из метаданных, это может быть как стандартная картинка так и добавленная в ветку "Общие картинки".
Второй параметр (необязательный) - любой дополнительный параметр который мы захотим обрабатывать при нажатии на картинку.
Третий параметр (необязательный, по умолчанию стоит ключ по которому клик на картинку будет игнорироваться) - ключ, по которому мы будем определять действие, которое нам нужно сделать при нажатии на ссылку.
Посмотрим что у неё внутри:
Функция ВставитьКартинку(СтандартнаяКартинка,ДополнительныйПараметр="",КлючПроцедуры="НеОбрабатыватьНажатие",РазмерРамкиКартинки=0) Экспорт
Если ТипЗнч(СтандартнаяКартинка)<>Тип("Картинка") тогда
Возврат "";
КонецЕсли;
Если ДополнительныйПараметр<>"" тогда
УникальныйИдентификатор = Новый УникальныйИдентификатор;
Адрес = ПоместитьВоВременноеХранилище(ДополнительныйПараметр, УникальныйИдентификатор);
Иначе
Адрес=""
КонецЕсли;
Попытка
ТекущийМассивСтрок=СтрРазделить(ЗначениеВСтрокуВнутр(СтандартнаяКартинка), ",");
ТекущийIDКартинки = Лев(ТекущийМассивСтрок[5],СтрДлина(ТекущийМассивСтрок[5])-1);
Исключение
ТекущийIDКартинки ="";
КонецПопытки;
Если СтрДлина(ТекущийIDКартинки)<>36 тогда
Возврат "";
КонецЕсли;
ПредставлениеКартинки = "<img src=""v8config://v8cfgHelp/mdpicture/id"+ТекущийIDКартинки+"/00000000-0000-0000-0000-000000000000"" border="""+РазмерРамкикартинки+""">";
Возврат "<A id=""" + КлючПроцедуры + """ href= """+ Адрес + """ >"+ПредставлениеКартинки+"</A>";
КонецФункции
Спасибо что дочитали до конца :) Значит мой труд уже не был напрасен, плюсик вам в карму.
P.S. Понимаю, что идея не уникальна и не совершенна, так что приветствуется критика и предложения в комментариях.