Как решить проблему с обработкой событий клавиатуры (keydown, keypress, keyup) в поле HTML-документа в 1С?

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

При разработке современных интерфейсов на управляемых формах 1С программисты часто прибегают к использованию поля HTML-документа. Это позволяет встраивать интерактивные карты, графики, сложные таблицы или нестандартные элементы управления, созданные на HTML и JavaScript. Однако при реализации взаимодействия пользователя с веб-интерфейсом через клавиатуру многие сталкиваются с неприятной особенностью: стандартные события keydown, keypress и keyup начинают вести себя непредсказуемо.

Симптомы проблемы обычно выглядят следующим образом: события клавиатуры либо не отрабатывают вовсе, либо срабатывают избирательно. Например, события keyup и keypress могут возникать только при нажатии клавиш Backspace и Delete, в то время как keydown реагирует на любые клавиши, кроме них. Попытки отловить нажатия навигационных клавиш (стрелки «Влево», «Вправо», «Вверх», «Вниз») в JavaScript-коде часто заканчиваются полной неудачей. Выясним причину этой проблемы и разберем по шагам эффективные методы ее решения.

Почему платформа 1С перехватывает клавиатурные события?

Для того чтобы понять природу этой проблемы, проанализируем архитектуру поля HTML-документа. Данный элемент управления на управляемых формах 1С представляет собой контейнер (ActiveX или Web-контрол), внутрь которого встраивается движок браузера. В операционных системах семейства Windows исторически использовался движок MSHTML (ядро Internet Explorer), а в современных версиях платформы 1С (начиная с релиза 8.3.14) — движки на базе WebKit и Chromium (WebView2).

Когда фокус ввода находится внутри поля HTML-документа, операционная система Windows посылает сообщения о нажатии клавиш главному окну приложения 1С. Платформа 1С, являясь родительским контейнером, перехватывает эти сообщения для обеспечения собственной глобальной навигации. Платформа обрабатывает системные клавиши самостоятельно:

  1. Клавиши Tab и Shift+Tab используются для перемещения фокуса между элементами управляемой формы 1С.
  2. Клавиши со стрелками используются для навигации по элементам формы, табличным частям или спискам.
  3. Клавиши Enter и Escape служат для подтверждения или отмены действий в диалоговых окнах платформы.
  4. Комбинации клавиш (например, Ctrl+S, Ctrl+F) обрабатываются глобальным меню 1С.

Поскольку платформа 1С обрабатывает эти сообщения на уровне своего главного цикла обработки сообщений (Message Loop), они попросту не доходят до дочернего окна браузера. Браузерный движок не получает извещений о нажатии клавиш, и, соответственно, в вашем JavaScript-коде события keydown или keyup для этих клавиш не генерируются.

Рассмотрим подробнее способы борьбы с этой особенностью интеграции.

Решение 1. Принудительное управление фокусом и атрибут tabindex

По умолчанию в спецификации HTML далеко не все элементы веб-страницы могут принимать фокус ввода. Например, теги <div>, <span>, <p> или сам элемент <body> игнорируются фокусом, если они не являются интерактивными. Если фокус физически не находится на элементе, то и события клавиатуры для него генерироваться не будут.

Чтобы заставить любой элемент на странице принимать фокус и генерировать события клавиатуры, мы должны использовать глобальный HTML-атрибут tabindex. Установив его значение в "0", мы делаем элемент доступным для фокусировки с клавиатуры в естественном порядке навигации.

Выполним это по шагам:

  1. Добавим атрибут tabindex="0" к основному контейнеру на вашей HTML-странице.
  2. Программно передадим фокус этому элементу сразу после загрузки документа.

Посмотрим на пример реализации разметки и JavaScript-кода:


<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Интерактивный ввод</title>
    <style>
        #main-container {
            width: 100%;
            height: 100%;
            border: 1px solid #ccc;
            outline: none; /* Убираем стандартную синюю рамку при фокусе */
        }
    </style>
</head>
<body>
    <div id="main-container" tabindex="0">
        Щелкните здесь для активации ввода с клавиатуры...
    </div>

    <script>
        window.onload = function() {
            var container = document.getElementById("main-container");
            // Устанавливаем фокус на наш контейнер при загрузке страницы
            container.focus();

            // Назначаем обработчики событий
            container.addEventListener("keydown", function(event) {
                console.log("Нажата клавиша (keydown): " + event.keyCode);
                // Если нужно предотвратить стандартное поведение платформы 1С для этой клавиши:
                if (event.keyCode === 37 || event.keyCode === 39) { // Стрелки влево/вправо
                    event.stopPropagation();
                }
            });

            container.addEventListener("keyup", function(event) {
                console.log("Отпущена клавиша (keyup): " + event.keyCode);
            });
        };
    </script>
</body>
</html>

Благодаря вызову метода focus() и установке tabindex, браузерный движок захватывает клавиатурный поток ОС более агрессивно, что позволяет обрабатывать большинство нажатий клавиш без потерь.

Решение 2. Использование свойства contentEditable для обхода перехвата 1С

Если ваша задача заключается в создании кастомного текстового редактора или поля ввода, лучшим решением будет использование встроенного в браузеры режима редактирования контента. Свойство contentEditable указывает браузеру, что пользователь может редактировать содержимое элемента непосредственно на странице.

Когда фокус ввода попадает в область с включенным свойством contenteditable="true", операционная система переключает контекст обработки ввода. Движок встроенного браузера забирает управление клавиатурой у родительской формы 1С. В этом режиме навигационные стрелки, клавиши удаления (Backspace, Delete), а также клавиша переноса строки Enter начинают работать абсолютно штатно внутри HTML-документа.

Рассмотрим пример создания такого интерактивного поля:


<div contenteditable="true" id="custom-editor" style="border: 1px solid gray; padding: 10px; min-height: 100px;">
    Введите текст здесь...
</div>

<script>
    var editor = document.getElementById("custom-editor");

    editor.addEventListener("keydown", function(event) {
        // Все клавиши, включая стрелки и Backspace, теперь перехватываются здесь!
        if (event.keyCode === 13) {
            console.log("Нажат Enter внутри редактируемой области");
        }
    });
</script>

Этот способ является наиболее надежным, если вам требуется полноценный текстовый ввод в поле HTML-документа на управляемой форме 1С.

Решение 3. Настройка эмуляции Internet Explorer в реестре Windows

Если вы работаете на относительно старых версиях платформы 1С (до 8.3.14) или конфигурация запускается в режиме совместимости, поле HTML-документа под управлением ОС Windows использует устаревший движок рендеринга Internet Explorer 7. В этом режиме модель обработки событий сильно урезана, а многие современные свойства JavaScript не поддерживаются.

Чтобы заставить встроенный браузер использовать современный стандарт обработки событий (соответствующий IE11), необходимо прописать эмуляцию версии браузера в системном реестре Windows для исполняемых файлов платформы 1С (1cv8.exe, 1cv8c.exe).

Проанализируем программный способ решения этой задачи на языке 1С. Мы можем автоматически прописывать нужные параметры в реестр при запуске системы.

Для этого добавим в модуль управляемого приложения или в код инициализации вашей обработки следующий фрагмент кода 1С:


Процедура НастроитьЭмуляциюБраузераДля1С() Экспорт
    #Если ТонкийКлиент Или ТолстыйКлиентОбычноеПриложение Или ТолстыйКлиентУправляемоеПриложение Тогда
    
    Попытка
        Шелл = Новый COMОбъект("WScript.Shell");
        
        // Путь в реестре для настройки эмуляции IE
        ПутьРеестра = "HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION\";
        
        // Версия 11001 (0x2AF9) соответствует режиму IE11 Edge
        ЗначениеЭмуляции = 11001; 
        
        // Записываем параметры для тонкого и толстого клиентов 1С
        Шелл.RegWrite(ПутьРеестра + "1cv8.exe", ЗначениеЭмуляции, "REG_DWORD");
        Шелл.RegWrite(ПутьРеестра + "1cv8c.exe", ЗначениеЭмуляции, "REG_DWORD");
        
        // Для клиент-серверного режима и работы в конфигураторе также полезно зарегистрировать:
        Шелл.RegWrite(ПутьРеестра + "1cv8s.exe", ЗначениеЭмуляции, "REG_DWORD");
        
    Исключение
        ЗаписьЖурналаРегистрации("ПолеHTML.ЭмуляцияРеестра", 
            УровеньЖурналаРегистрации.Предупреждение, , , 
            "Не удалось записать параметры эмуляции IE в реестр: " + ОписаниеОшибки());
    КонецПопытки;
    
    #КонецЕсли
КонецПроцедуры

После применения этой настройки и перезапуска клиентского сеанса 1С встроенный веб-движок перейдет на использование модели рендеринга стандарта IE11. В результате обработка событий клавиатуры станет полностью соответствовать поведению современного браузера, а проблемы с избирательным срабатыванием keydown/keyup исчезнут.

Решение 4. Использование события input вместо клавиатурных событий

Если ваша конечная цель состоит в том, чтобы просто фиксировать изменения в текстовых полях ввода (например, <input type="text"> или <textarea>) и передавать их обратно в 1С, вам совсем не обязательно отслеживать конкретные нажатия клавиш клавиатуры через keyup или keydown.

Рекомендуется использовать стандартное HTML5-событие input. Это событие обладает следующими неоспоримыми преимуществами:

Посмотрим на пример использования события input в связке с передачей данных в управляемую форму 1С:


<input type="text" id="target-input" placeholder="Введите наименование...">

<script>
    var textInput = document.getElementById("target-input");

    textInput.addEventListener("input", function(event) {
        var currentValue = event.target.value;
        
        // Передаем измененное значение обратно в платформу 1С.
        // Способ передачи зависит от версии платформы (например, через отправку события)
        if (typeof FileCreator !== 'undefined') {
            // Для современных платформ 1С через механизм взаимодействия
            // (например, window.msecAsync или отправку через объект оповещения)
        } else {
            // Старый универсальный способ передачи данных через изменение хэша URL
            window.location.hash = "update_value:" + encodeURIComponent(currentValue);
        }
    });
</script>

В коде формы 1С вам останется лишь перехватить изменение данных в обработчике события ПриИзмененииСодержимогоДокумента (или OnURLChanged в зависимости от метода реализации) вашего реквизита формы типа "Поле HTML-документа". Это гарантирует 100% стабильность работы интерфейса вне зависимости от того, как именно пользователь изменил текст.

Резюме и рекомендации

Подведем итог проанализированным подходам. Борьба с клавиатурными событиями в поле HTML-документа управляемой формы 1С требует понимания специфики работы операционной системы и интеграционных механизмов платформы. Для достижения наилучшего результата рекомендуем придерживаться следующих правил:

  1. Если вы создаете форму ввода данных внутри HTML, всегда делайте элементы интерактивными, используя свойство contenteditable="true" или назначая tabindex="0".
  2. Для отслеживания ввода текста полностью откажитесь от низкоуровневых клавиатурных событий keyup/keydown в пользу высокоуровневого события input.
  3. При развертывании системы на компьютерах пользователей обязательно внедрите механизм автоматической настройки эмуляции браузера (IE11/Edge) через системный реестр Windows с помощью объекта WScript.Shell.
← На главную