При разработке интерфейсов в «1С:Предприятие» программисты часто сталкиваются со стандартным поведением платформы, которое не всегда удобно для конечного пользователя. Одной из таких проблем является ввод длинных строк, например, почтовых адресов. В стандартном поле ввода выбор значения из списка автоподбора приводит к немедленному завершению ввода или закрытию списка, что мешает пользователю быстро дописать улицу, дом или квартиру после выбора населенного пункта. Разберем, как обойти это ограничение и реализовать «бесшовный» ввод.
Стандартный механизм АвтоПодбор работает по принципу «выбрал — завершил». Как только пользователь нажимает Enter или кликает мышью по варианту, событие считается завершенным. Если нам нужно, чтобы после выбора слова «Некрасовское» курсор остался в поле и пользователь мог сразу печатать «Гагарина 5а», стандартных свойств текстового поля будет недостаточно. Проанализируем доступные способы решения этой задачи, от простых манипуляций с событиями до создания собственных элементов управления.
Это самый гибкий и современный метод, позволяющий полностью контролировать поведение клавиатуры и списков. Мы можем встроить в управляемую форму ПолеHTMLДокумента и использовать мощь JavaScript для обработки ввода.
Разберем логику реализации по шагам:
ПолеHTMLДокумента.input и выпадающий блок div, имитирующий список.onkeydown. При нажатии стрелок «Вверх» или «Вниз» мы будем программно менять value в input, но не будем закрывать список.window.external.MessageEvent (для новых версий платформы).Пример кода внутри HTML-поля для перехвата клавиш может выглядеть так:
inputElement.addEventListener('keydown', function(e) {
if (e.keyCode === 40) { // Стрелка вниз
let nextValue = getNextListItemValue();
inputElement.value = nextValue;
// Отправляем промежуточное значение в 1С, если нужно
window.external.postMessage(nextValue);
}
});
Этот метод позволяет реализовать именно то «интерактивное» поведение, которое требуется: текст подставляется в поле в момент перемещения курсора по списку, но фокус остается на вводе.
Если мы хотим остаться в рамках стандартных элементов, нам придется «обмануть» логику платформы. Мы можем использовать событие АвтоПодбор, установив параметр СтандартнаяОбработка = Ложь. Рассмотрим, как это реализовать.
Выясним причину, почему это сложно: метод ВыбратьИзСписка обычно перехватывает фокус. Чтобы этого избежать, разработчики часто используют вспомогательную форму, которая позиционируется под полем ввода.
Рассмотрим алгоритм работы через обработчик ожидания:
ПодключитьОбработчикОжидания("ОбновитьПодсказки", 0.3, Истина).ОбновитьПодсказки мы анализируем введенный текст и формируем массив совпадений.ЭтаФорма.ТекущийЭлемент.ВыделенныйТекст или просто изменяя значение реквизита.Пример кода для обработки ввода:
&НаКлиенте
Процедура ПолеВводаАвтоПодбор(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Здесь мы не заполняем ДанныеВыбора, чтобы не открывать стандартное окно
// Вместо этого вызываем свою логику отображения списка
ПоказатьСвойСписокПодсказок(Текст);
КонецПроцедуры
Для задач ввода адресов часто эффективнее использовать специализированные сервисы. Они позволяют реализовать логику «разбора» строки. Когда пользователь вводит часть адреса, сервис возвращает структурированный ответ.
Проанализируем ситуацию: если набрать «некрас гагарина», стандартный ФИАС может не справиться. Сервисы типа DaData поддерживают нечеткий поиск. Мы можем реализовать следующий сценарий:
Это реализуется через метод «склеивания» строк. Проанализируем пример кода, который объединяет уже выбранную часть и новый ввод:
&НаКлиенте
Процедура ОбработкаВыбораИзСписка(ВыбранныйЭлемент)
// Сохраняем уже введенную структуру (например, город)
СтруктураАдреса.Город = ВыбранныйЭлемент.Значение;
// Обновляем поле ввода, добавляя пробел для продолжения
Объект.АдресСтрокой = Строка(ВыбранныйЭлемент.Значение) + " ";
// Устанавливаем курсор в конец строки
// (требует использования WScript.Shell для имитации нажатия клавиши End)
УстановитьКурсорВКонецПоля();
КонецПроцедуры
В некоторых случаях для тонкой настройки поведения текстового поля в тонком клиенте под Windows используют объект WScript.Shell. Это позволяет программно «допечатывать» символы в поле, как будто их нажимает пользователь. Это помогает избежать события ПриИзменении, которое может сработать преждевременно.
Рассмотрим пример, как программно нажать пробел после выбора из списка:
&НаКлиенте
Процедура ДопечататьПробел()
Попытка
Shell = Новый COMОбъект("WScript.Shell");
Shell.SendKeys(" "); // Посылаем нажатие клавиши пробел
Исключение
// Обработка ошибки, если COM-объект недоступен
КонецПопытки;
КонецПроцедуры
Важно: Данный метод является платформозависимым и не будет работать в веб-клиенте или на Linux.
Подведем итог и выберем оптимальный путь в зависимости от условий задачи:
Помните, что в новых версиях платформы (начиная с 8.3.15) работа с адресами через систему ГАР уже предполагает более продвинутые механизмы разбора строк, поэтому перед написанием своего велосипеда проверьте возможности встроенного адресного классификатора в вашей конфигурации.