В статье рассмотрен вопрос о доработанной вставки картинки из буфера обмена через компоненту Документооборота. Рассмотрим вопросы касаемо 2-х типов приложений: Управляемое - Через Форматированный Документ, для Обычных Форм касаемо
- Вставка в Поле HTML осуществляем в 2 этапа:
- Картинку из Буфера обмена будем получать при помощи метода документооборота.
- Вставку в код HTML будем осуществлять непосредственно на Javascript, поскольку в отличие от Форматированного документа нужного функционала по определению курсора нету. Поэтому для этого используем вставку полностью на основе вызова Функции JS.
- Вставку в Форматированный документ на Тонком Клиенте делаем аналогично тому, что было в исходной статье.
При этом последний функционал необходимо полностью доработать до возможности использования в Общем модуле, из которого будем вызывать экспортную процедуру с Формы (Управляемой или Обычной). Хотя есть уже до этого публикация Вставка снимка экрана (screenshot) в форматированный документ, тем не менее не очень удобно переносить 3 процедуры в каждую форму.
Предлагаю модернизированный вариант этого способа, и ещё применительно к обычным формам. Тестировалось на платформах 8.3.14 - 8.3.16.
Вставка картинки в HTML поле положения курсора при помощи JavaScript.
Рассмотрим следующие режимы:
- Тонкий Клиент.
- Обычное Приложение.
Для Обычного приложения код выглядит так:
Процедура Кнопка1Нажатие(Элемент)
#Если ВебКлиент тогда
Сообщить("Компонента в контектсе Web Клиента не работает. Используйте Ctrl+V для вставки изображений");
#Иначе
КомпонентаУстановлена = РаботаСКартинкамиКлиент.ПроинициализироватьКомпоненту();
Если Не КомпонентаУстановлена Тогда
Обработчик = Новый ОписаниеОповещения("ВставитьКартинкуИзБуфераЗавершение", ЭтотОбъект);
РаботаСКартинкамиКлиент.УстановитьКомпоненту(Обработчик);
Возврат;
КонецЕсли;
ВставитьКартинкуИзБуфераЗавершение(Истина, Неопределено,ЭлементыФормы.ПолеHTMLДокумента1.Имя);
#КонецЕсли
КонецПроцедуры
Функция ВставитьКартинкуИзБуфераЗавершение(Результат,ПараметрыВыполнения,НазваниеФорматДок)
Если Результат = Истина Тогда
ПутьКФайлу = КомпонентаПолученияКартинкиИзБуфера.ПолучитьКартинкуИзБуфера();
Если Не ПустаяСтрока(ПутьКФайлу) Тогда
Картинка = Новый Картинка(ПутьКФайлу);
Данные2=КаталогВременныхФайлов();
Текст = ЭтаФорма.ЭлементыФормы[НазваниеФорматДок].ПолучитьТекст();
ИндексВложений=СтрЧислоВхождений(Текст,"img");
ИмяСкриншота="image"+Прав("00"+ИндексВложений,3)+".jpg";
РасположениеСкриншота=Данные2+ИмяСкриншота;
ПереместитьФайл(ПутьКФайлу,РасположениеСкриншота);
ПутьКФайлу=Данные2;
Text="<P><FONT face=Tahoma><FONT size=2> <BR></FONT></FONT></P><IMG src="""+РасположениеСкриншота + """ width = ""200"" height = ""200"" />";
ЭтаФорма.ЭлементыФормы[НазваниеФорматДок].Документ.defaultView.insertHtmlAfterSelection(Text);
Иначе
ПоказатьПредупреждение(,НСтр("ru = 'Буфер обмена не содержит картинки'"));
КонецЕсли;
КонецЕсли;
КонецФункции
Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
ДокументHTML = "<html><head>
|</head><script language='JavaScript'>
|function insertHtmlAfterSelection(html) {
| var sel, range, expandedSelRange, node;
| if (window.getSelection) {
| sel = window.getSelection();
| if (sel.getRangeAt && sel.rangeCount) {
| range = window.getSelection().getRangeAt(0);
| expandedSelRange = range.cloneRange();
| range.collapse(false);
| // Range.createContextualFragment() would be useful here but is
| // non-standard and not supported in all browsers (IE9, for one)
| var el = document.createElement('div');
| el.innerHTML = html;
| var frag = document.createDocumentFragment(), node, lastNode;
| while ( (node = el.firstChild) ) {
| lastNode = frag.appendChild(node);
| }
| range.insertNode(frag);
|
| // Preserve the selection
| if (lastNode) {
| expandedSelRange.setEndAfter(lastNode);
| sel.removeAllRanges();
| sel.addRange(expandedSelRange);
| }
| }
| } else if (document.selection && document.selection.createRange) {
| range = document.selection.createRange();
| expandedSelRange = range.duplicate();
| range.collapse(false);
| range.pasteHTML(html);
| expandedSelRange.setEndPoint('EndToEnd', range);
| expandedSelRange.select();
| }
|}
|</script><body contenteditable='true'></body></html>";
ЭлементыФормы.ПолеHTMLДокумента1.УстановитьТекст(ДокументHTML);
КонецПроцедуры
Однако, применяемая функция JavaScript может быть использована для вставки не только картинок после курсора - а в целом любого HTML в документе после курсора.
Для управляемых форм код не будет особо отличаться, и в целом будет похож на предыдущий случай. И будет выглядеть таким образом.
&НаКлиенте
Процедура Команда1(Команда)
// Вставить содержимое обработчика.
#Если ВебКлиент тогда
Сообщить("Компонента в контектсе Web Клиента не работает. Используйте Ctrl+V для вставки изображений");
#Иначе
КомпонентаУстановлена = РаботаСКартинкамиКлиент.ПроинициализироватьКомпоненту();
Если Не КомпонентаУстановлена Тогда
Обработчик = Новый ОписаниеОповещения("ВставитьКартинкуИзБуфераЗавершение", ЭтотОбъект);
РаботаСКартинкамиКлиент.УстановитьКомпоненту(Обработчик);
Возврат;
КонецЕсли;
ВставитьКартинкуИзБуфераЗавершение(Истина, Неопределено,Элементы.Документ.Имя);
#КонецЕсли
КонецПроцедуры
&НаКлиенте
Функция ВставитьКартинкуИзБуфераЗавершение(Результат,ПараметрыВыполнения,НазваниеФорматДок)
Если Результат = Истина Тогда
ПутьКФайлу = КомпонентаПолученияКартинкиИзБуфера.ПолучитьКартинкуИзБуфера();
Если Не ПустаяСтрока(ПутьКФайлу) Тогда
Картинка = Новый Картинка(ПутьКФайлу);
Данные2=КаталогВременныхФайлов();
Текст = ДокументHTML;
ИндексВложений=СтрЧислоВхождений(Текст,"img");
ИмяСкриншота="image"+Прав("00"+ИндексВложений,3)+".jpg";
РасположениеСкриншота=Данные2+ИмяСкриншота;
ПереместитьФайл(ПутьКФайлу,РасположениеСкриншота);
ПутьКФайлу=Данные2;
Text="<P><FONT face=Tahoma><FONT size=2> <BR></FONT></FONT></P><IMG src="""+РасположениеСкриншота + """ width = ""200"" height = ""200"" />";
ЭтаФорма.Элементы[НазваниеФорматДок].Документ.defaultView.insertHtmlAfterSelection(Text);
Иначе
ПоказатьПредупреждение(,НСтр("ru = 'Буфер обмена не содержит картинки'"));
КонецЕсли;
КонецЕсли;
КонецФункции
&НаКлиенте
Процедура ПриОткрытии(Отказ)
//Вставить содержимое обработчика
ЭтаФорма.ДокументHTML = "<html><head>
|</head><script language='JavaScript'>
|function insertHtmlAfterSelection(html) {
| var sel, range, expandedSelRange, node;
| if (window.getSelection) {
| sel = window.getSelection();
| if (sel.getRangeAt && sel.rangeCount) {
| range = window.getSelection().getRangeAt(0);
| expandedSelRange = range.cloneRange();
| range.collapse(false);
| // Range.createContextualFragment() would be useful here but is
| // non-standard and not supported in all browsers (IE9, for one)
| var el = document.createElement('div');
| el.innerHTML = html;
| var frag = document.createDocumentFragment(), node, lastNode;
| while ( (node = el.firstChild) ) {
| lastNode = frag.appendChild(node);
| }
| range.insertNode(frag);
|
| // Preserve the selection
| if (lastNode) {
| expandedSelRange.setEndAfter(lastNode);
| sel.removeAllRanges();
| sel.addRange(expandedSelRange);
| }
| }
| } else if (document.selection && document.selection.createRange) {
| range = document.selection.createRange();
| expandedSelRange = range.duplicate();
| range.collapse(false);
| range.pasteHTML(html);
| expandedSelRange.setEndPoint('EndToEnd', range);
| expandedSelRange.select();
| }
|}
|</script><body contenteditable='true'></body></html>";
КонецПроцедуры
Таким образом, код для 2-х режимов является достаточно похожим. Единственное исключение - Web Клиент, но там вставка осуществляется полностью за счет JavaScript (Это описано в статье - Вставка картинки из буфера обмена (на выбор: JavaScript / внешняя компонента / штатно)) или если платформа более старая - Java Апплет можно попробовать дополнить.
Вставка картинки в Форматированный Документ компонентой ДО в Управляемых Формах.
Форматированный Документ - это вариант HTML документа (потому что текст получается там HTML) со следующими особенностями, которые были выявлены в ходе работы над внутренней конфигурации:
- Не стабильно "форматирование документа", а поэтому стили не всегда работают.
- Нет возможности вызвать JavaScript.
- Нет доступа к Объекту Документ.
- Drag-Drop для картинок работает ужасно. Не возможно потом вытащить картинку.
Однако, взамен 1С дописала удобный для разработчиков интерфейс, благодаря чему можно обойтись без вызовов javascript, правда и расширить функционал можно только за счет внешних компонент. В данном случае код вставки будет выглядеть таким образом:
&НаКлиенте
Процедура КомандаТест(Команда)
#Если ВебКлиент тогда
Сообщить("Компонента в контектсе Web Клиента не работает. Используйте Ctrl+V для вставки изображений");
#Иначе
КомпонентаУстановлена = РаботаСКартинкамиКлиент.ПроинициализироватьКомпоненту();
Если Не КомпонентаУстановлена Тогда
Обработчик = Новый ОписаниеОповещения("ВставитьКартинкуИзБуфераЗавершение", ЭтотОбъект);
РаботаСКартинкамиКлиент.УстановитьКомпоненту(Обработчик);
Возврат;
КонецЕсли;
ВставитьКартинкуИзБуфераЗавершение1(Истина, Неопределено,Элементы.ФорматированныйДокумент.Имя);
#КонецЕсли
КонецПроцедуры
&НаКлиенте
Функция ВставитьКартинкуИзБуфераЗавершение1(Результат,ПараметрыВыполнения,НазваниеФорматДок)
Если Результат = Истина Тогда
ПутьКФайлу = КомпонентаПолученияКартинкиИзБуфера.ПолучитьКартинкуИзБуфера();
Если Не ПустаяСтрока(ПутьКФайлу) Тогда
Картинка = Новый Картинка(ПутьКФайлу);
УдалитьФайлы(ПутьКФайлу);
ПозицияНачала=0;
ПозицияОконч=0;
ЭтаФорма.Элементы[НазваниеФорматДок].ПолучитьГраницыВыделения(ПозицияНачала,ПозицияОконч);
ЭтаФорма.ВставитьКартинкуВФорматированныйДокумент(Картинка,ПозицияОконч,НазваниеФорматДок);
Иначе
ПоказатьПредупреждение(,НСтр("ru = 'Буфер обмена не содержит картинки'"));
КонецЕсли;
КонецЕсли;
КонецФункции
&НаСервере
Процедура ВставитьКартинкуВФорматированныйДокумент(Кар,Закладка,Док) экспорт
ЭтотОбъект[Док].Вставить(Закладка,Кар, Тип("КартинкаФорматированногоДокумента"));
КонецПроцедуры
Следует отметить, что все процедуры, кроме ВставитьКартинкуВФорматированныйДокумент можно вставить в модуль и осуществить вызов из модуля, для этого последнюю достаточно сделать экспортной, и также необходимо добавить туда наименование какого-либо события, если вставку картинки в Форматированный Документ необходимо контролировать.
Итоговый код для упрощения процедуры вставки
если обе процедуры поместить в модуль, то код при переносе можно существенно сократить, и он будет выглядеть для различных режимов несколько по разному. Я приведу лишь код в самих формах, так как если его немного изменить - получим некоторые нюансы:
- Код для Форматированного Документа в УФ.
- Код для поля HTML в ОбычныхФормах. Код для Тонкого Клиента УФ я не привожу, так как он не сильно отличается.
Для Форматированного Документа:
&НаКлиенте
Процедура ВставитьКартинкуИзБуфера(Команда)
КлиентРаботаСФормами.ВставитьКартинкуВФорматированныйДокументКлиент(Элементы.СодержаниеФД.Имя,ЭтаФорма);
КонецПроцедуры
&НаСервере
Процедура ВставитьКартинкуВФорматированныйДокумент(Кар,Закладка,Док) экспорт
ЭтотОбъект[Док].Вставить(Закладка,Кар, Тип("КартинкаФорматированногоДокумента"));
КонецПроцедуры
Для HTML поля обычные Формы:
Процедура ВставитьКартинкуИзБуфераОбменаНажатие(Элемент)
КлиентРаботаСФормами.ВставитьКартинкуВФорматированныйДокументКлиент(ЭлементыФормы.ПолеHTML.Имя,ЭтаФорма,"ВставитьКартинку");
КонецПроцедуры
//Универсальный CallBack:
Процедура ВставитьКартинкуВФорматированныйДокумент(Текст,РасположениеСкриншота,ИмяСкриншота,НазваниеФорматДок,Событие,Кнопка) экспорт
Если Событие="ВставитьКартинку" тогда
//Вставить Обход События
КонецЕсли;
КонецПроцедуры
Как видно - код достаточно компактный, и легко переносить из одной формы в другую - не прибегая к излишествам. Излишества можно добавить по своему желанию.