При разработке современных интерфейсов на управляемых формах 1С программисты часто прибегают к использованию поля HTML-документа. Это позволяет встраивать интерактивные карты, графики, сложные таблицы или нестандартные элементы управления, созданные на HTML и JavaScript. Однако при реализации взаимодействия пользователя с веб-интерфейсом через клавиатуру многие сталкиваются с неприятной особенностью: стандартные события keydown, keypress и keyup начинают вести себя непредсказуемо.
Симптомы проблемы обычно выглядят следующим образом: события клавиатуры либо не отрабатывают вовсе, либо срабатывают избирательно. Например, события keyup и keypress могут возникать только при нажатии клавиш Backspace и Delete, в то время как keydown реагирует на любые клавиши, кроме них. Попытки отловить нажатия навигационных клавиш (стрелки «Влево», «Вправо», «Вверх», «Вниз») в JavaScript-коде часто заканчиваются полной неудачей. Выясним причину этой проблемы и разберем по шагам эффективные методы ее решения.
Для того чтобы понять природу этой проблемы, проанализируем архитектуру поля HTML-документа. Данный элемент управления на управляемых формах 1С представляет собой контейнер (ActiveX или Web-контрол), внутрь которого встраивается движок браузера. В операционных системах семейства Windows исторически использовался движок MSHTML (ядро Internet Explorer), а в современных версиях платформы 1С (начиная с релиза 8.3.14) — движки на базе WebKit и Chromium (WebView2).
Когда фокус ввода находится внутри поля HTML-документа, операционная система Windows посылает сообщения о нажатии клавиш главному окну приложения 1С. Платформа 1С, являясь родительским контейнером, перехватывает эти сообщения для обеспечения собственной глобальной навигации. Платформа обрабатывает системные клавиши самостоятельно:
Поскольку платформа 1С обрабатывает эти сообщения на уровне своего главного цикла обработки сообщений (Message Loop), они попросту не доходят до дочернего окна браузера. Браузерный движок не получает извещений о нажатии клавиш, и, соответственно, в вашем JavaScript-коде события keydown или keyup для этих клавиш не генерируются.
Рассмотрим подробнее способы борьбы с этой особенностью интеграции.
По умолчанию в спецификации HTML далеко не все элементы веб-страницы могут принимать фокус ввода. Например, теги <div>, <span>, <p> или сам элемент <body> игнорируются фокусом, если они не являются интерактивными. Если фокус физически не находится на элементе, то и события клавиатуры для него генерироваться не будут.
Чтобы заставить любой элемент на странице принимать фокус и генерировать события клавиатуры, мы должны использовать глобальный HTML-атрибут tabindex. Установив его значение в "0", мы делаем элемент доступным для фокусировки с клавиатуры в естественном порядке навигации.
Выполним это по шагам:
tabindex="0" к основному контейнеру на вашей HTML-странице.Посмотрим на пример реализации разметки и 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, браузерный движок захватывает клавиатурный поток ОС более агрессивно, что позволяет обрабатывать большинство нажатий клавиш без потерь.
Если ваша задача заключается в создании кастомного текстового редактора или поля ввода, лучшим решением будет использование встроенного в браузеры режима редактирования контента. Свойство 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С.
Если вы работаете на относительно старых версиях платформы 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 исчезнут.
Если ваша конечная цель состоит в том, чтобы просто фиксировать изменения в текстовых полях ввода (например, <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С требует понимания специфики работы операционной системы и интеграционных механизмов платформы. Для достижения наилучшего результата рекомендуем придерживаться следующих правил:
contenteditable="true" или назначая tabindex="0".keyup/keydown в пользу высокоуровневого события input.WScript.Shell.