Как реализовать перетаскивание файлов (Drag-and-Drop) в поле HTML документа на форме 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке пользовательских интерфейсов в 1С с использованием HTML часто возникает задача интеграции веб-технологий непосредственно в формы. Одной из таких задач является реализация механизма Drag-and-Drop (перетаскивание файлов) с рабочего стола или из папки операционной системы прямо в поле HTML документа на форме 1С. Казалось бы, стандартный HTML5 предоставляет для этого все необходимые события, однако на практике разработчики сталкиваются с тем, что встроенный в 1С браузер (WebKit) перехватывает событие и просто открывает файл вместо того, чтобы передать управление вашему скрипту.

Давайте подробно разберем, почему возникает эта проблема, и рассмотрим рабочее решение, которое позволит вам корректно обрабатывать перетаскивание внешних файлов.

Суть проблемы и поведение платформы

Рассмотрим ситуацию, с которой мы сталкиваемся. У нас есть форма, на ней размещен реквизит типа Строка или, что чаще, элемент формы связанный с типом ПолеHTMLДокумента. Этот элемент обладает огромным потенциалом, позволяя реализовать универсальный ввод на WEB клиенте, однако при его использовании мы пишем стандартный HTML-код с обработчиками ondrop и ondragover. Если открыть этот HTML в обычном браузере (Chrome, Firefox), все работает: при перетаскивании файла срабатывает скрипт. Но внутри 1С происходит следующее:

  1. Мы перетаскиваем файл в поле.
  2. Вместо выполнения нашей JavaScript-функции, поле HTML документа пытается открыть этот файл (отобразить картинку или текст).
  3. Событие Drop не срабатывает должным образом, или поле становится недоступным для взаимодействия.

Замечено интересное поведение: если сначала выделить какой-то элемент внутри самого поля HTML и перетащить его "сам в себя", то механизм Drag-and-Drop "просыпается", и после этого внешние файлы начинают приниматься корректно. Это связано с инициализацией фокуса и контекста браузерного движка внутри окна 1С.

Однако заставлять пользователя делать лишние движения — плохой тон. Нам нужно решение, которое работает сразу при открытии формы.

Решение через атрибут contenteditable

Наиболее эффективным и стабильным способом заставить поле HTML документа в 1С принимать внешние события перетаскивания является использование атрибута contenteditable. Этот атрибут сообщает браузеру, что содержимое элемента может быть отредактировано пользователем. В этом режиме браузер активирует расширенные механизмы взаимодействия, включая нативную обработку перетаскивания.

Давайте рассмотрим пример кода, который необходимо разместить в модуле формы. Мы будем формировать HTML-код программно при создании формы на сервере.

В обработчике события ПриСозданииНаСервере сформируем строку с HTML-контентом:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Формируем HTML с CSS стилями и JavaScript обработчиками
    ПолеHTML = "<html> 
    |   <style> 
    |       .dragndrop {
    |           width: 100%; 
    |           height: 100%; 
    |           border: 3px solid orange; /* Визуально выделяем зону */
    |           padding: 30px; 
    |           box-sizing: border-box; /* Важно для корректных отступов */
    |           text-align: center; 
    |           background: cornsilk; 
    |           display: flex;
    |           align-items: center;
    |           justify-content: center;
    |       }
    |   </style>
    |   <head></head>
    |   <body>
    |       <!-- Ключевой момент: атрибуты contenteditable и draggable -->
    |       <div class=""dragndrop"" 
    |            ondrop=""drop(event)"" 
    |            draggable=""true"" 
    |            contenteditable=""true"">
    |           Кидай файлы сюда!
    |       </div>
    |
    |       <script>
    |           // Функция обработки сброса
    |           function drop(ev) {
    |               ev.preventDefault(); // Останавливаем открытие файла
    |               ev.stopPropagation();
    |               alert(""Файл успешно перетащен!""); 
    |               // Здесь можно добавить логику передачи данных в 1С
    |           }
    |           
    |           // Предотвращаем стандартное поведение при наведении
    |           document.body.ondragover = function(ev) {
    |               ev.preventDefault();
    |               return false;
    |           };
    |       </script>
    |   </body> 
    |</html>";  
    
КонецПроцедуры

Разберем ключевые моменты решения

Давайте проанализируем, почему этот код работает, в отличие от стандартной разметки.

  1. Атрибут contenteditable="true": Это главная часть решения. Когда элемент div помечен как редактируемый, движок WebKit внутри 1С переключается в режим, готовый принимать вставку контента, включая перетаскиваемые объекты. Это обходит блокировку, из-за которой событие drop ранее игнорировалось или работало некорректно.
  2. Событие ondragover: Обратите внимание, что для корректной работы Drag-and-Drop крайне важно отменить стандартное поведение браузера в событии dragover. Если этого не сделать (не вызвать event.preventDefault()), браузер может решить, что сброс в это место невозможен, или попытаться открыть ссылку/файл самостоятельно. В примере выше мы перехватываем это событие на уровне document.body.
  3. Атрибут draggable="true": Хотя он больше предназначен для перетаскивания самого элемента, его наличие в связке с contenteditable помогает движку правильно инициализировать подсистему Drag-and-Drop.

Нюансы обработки событий (preventDefault)

В процессе обсуждения данной темы часто возникает путаница с методом preventDefault(). Давайте проясним ситуацию.

В стандартном HTML5 Drag-and-Drop API:

Однако при использовании contenteditable поведение может незначительно меняться. Некоторые разработчики отмечают, что удаление обработчика dragover иногда "чинит" ситуацию, но это скорее исключение или особенность конкретной версии платформы. Мы рекомендуем придерживаться стандарта и явно отменять стандартные действия браузера, чтобы код был предсказуемым.

Как передать данные о файле в 1С?

Приведенный выше пример показывает alert, что подтверждает факт срабатывания события. Чтобы реально обработать файл в 1С, нам нужно усовершенствовать JavaScript функцию drop(ev).

Помните о безопасности: современные браузеры (и WebKit в 1С) не дают полный путь к файлу на диске пользователя (вы увидите что-то вроде C:\fakepath\file.txt). Чтобы передать файл в базу 1С, нам нужно прочитать его содержимое с помощью FileReader внутри JavaScript и передать его, например, как Base64 строку. Этот подход во многом схож с тем, как реализуется отображение картинки из буфера обмена.

Рассмотрим пример расширения функции drop:


function drop(ev) {
    ev.preventDefault();
    
    if (ev.dataTransfer.files.length > 0) {
        var file = ev.dataTransfer.files[0];
        var reader = new FileReader();
        
        reader.onload = function(event) {
            // Получаем содержимое файла в base64
            var fileData = event.target.result;
            // Отправляем событие в 1С
            // В 1С его нужно ловить в процедуре ПриНажатии (для старых версий) 
            // или через специальные методы взаимодействия
            var hiddenButton = document.getElementById('btn1c'); 
            // Логика передачи данных зависит от метода интеграции
        };
        
        reader.readAsDataURL(file);
    }
}

Для более сложной логики можно использовать подходы, применяемые при использовании 1С + JavaScript для расширения интерактивных функций.

Рекомендации по стилизации

Чтобы пользователь понимал, куда именно нужно бросать файлы, используйте CSS. В примере мы использовали класс .dragndrop. Полезно также менять стиль при наведении курсора с файлом (событие dragenter), например, подсвечивать рамку другим цветом. Если же вам необходимо работать с изображениями, полученными не локально, а из интернета, можно рассмотреть варианты добавления картинок по внешним ссылкам.

Используя этот подход с contenteditable, вы сможете создать интуитивно понятный интерфейс для пользователей, позволяя им загружать файлы в 1С простым перетаскиванием, без необходимости нажимать кнопки "Загрузить" и искать файлы через диалоговые окна.

← На главную