Как отловить клик и изменение позиции курсора в Поле форматированного документа или Поле HTML?

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

При разработке сложных интерфейсов в 1С, таких как конструкторы документов или редакторы контента с иерархической структурой, часто возникает задача синхронизации текста с другими элементами формы. Например, когда пользователь кликает на абзац в текстовом поле, программа должна автоматически выделить соответствующий элемент в дереве структуры документа. Однако стандартный объект Поле форматированного документа имеет существенные ограничения в событийной модели.

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

Проблема стандартного Поля форматированного документа

Основная сложность заключается в том, что у объекта Поле форматированного документа отсутствует событие "При изменении позиции курсора" или "При нажатии". Событие ПриИзменении срабатывает только тогда, когда текст был отредактирован и поле потеряло фокус. Это делает невозможным оперативное отслеживание перемещений пользователя по документу.

Рассмотрим первый, наиболее очевидный, но не самый оптимальный способ решения — использование обработчика ожидания.


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    ПодключитьОбработчикОжидания("ПроверитьПозициюКурсора", 0.5, Ложь);
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьПозициюКурсора()
    // Проверяем, что фокус находится в нужном поле
    Если ЭтаФорма.ТекущийЭлемент = Элементы.ПолеТекстаДокумента Тогда
        Границы = Элементы.ПолеТекстаДокумента.ПолучитьГраницыВыделения();
        // Далее следует логика анализа позиции и поиска в дереве
    КонецЕсли;
КонецПроцедуры

Такой подход называют "некошерным", так как он создает лишнюю нагрузку на клиентское приложение, постоянно выполняя код, даже если пользователь ничего не делает. Поэтому проанализируем более профессиональное решение.

Решение через Поле HTML документа

Для реализации полноценного отклика на действия пользователя рекомендуется заменить Поле форматированного документа на Поле HTML документа. Это открывает доступ к объектной модели документа (DOM) и позволяет использовать возможности JavaScript.

Разберем по шагам, как настроить отслеживание клика в HTML-поле:

  1. Подготовим HTML-текст, обернув значимые части документа (абзацы, разделы) в теги <span> или <div> с уникальными идентификаторами.
  2. Используем событие ПриНажатии поля HTML для перехвата данных.

Пример формирования структуры текста:


ТекстHTML = "<div id='Раздел_1'>Заголовок первого раздела</div>"
          + "<div id='Абзац_1_1'>Текст первого абзаца...</div>";
Элементы.ПолеHTML.УстановитьТекст(ТекстHTML);

Теперь проанализируем ситуацию с обработкой клика. В событии ПриНажатии мы можем получить объект события и извлечь из него идентификатор элемента, на который нажал пользователь.

Идентификация элементов и работа с выделением

Если в документе много повторяющихся слов, простой поиск по тексту не даст точного результата. Для надежной идентификации фрагментов текста лучше использовать data-атрибуты. Это позволяет хранить служебную информацию прямо в тегах, не отображая ее пользователю.

Рассмотрим пример HTML-разметки с использованием служебных меток:


<p data-id="Node_001">Это фрагмент текста, связанный с узлом дерева 001</p>
<p data-id="Node_002">А это текст второго узла</p>

Для того чтобы 1С узнала об изменении позиции, мы можем внедрить в HTML небольшой скрипт на языке JavaScript. Начиная с версии платформы 8.3.14 (с переходом на WebKit), взаимодействие между JS и 1С стало значительно стабильнее.

Рассмотрим использование события selectionchange, которое срабатывает каждый раз, когда курсор перемещается или текст выделяется:


document.addEventListener('selectionchange', function() {
    var selection = window.getSelection();
    if (selection.rangeCount > 0) {
        var parentElement = selection.anchorNode.parentElement;
        var elementId = parentElement.getAttribute('data-id');
        if (elementId) {
            // Передаем ID обратно в 1С через механизм сообщений или изменение URL
            window.external.Message(elementId);
        }
    }
});

Нюансы двусторонней синхронизации

При работе с Полем HTML документа важно помнить о сохранении данных. Если вы планируете не только отображать, но и редактировать текст, вам придется реализовать механизм обратной конвертации HTML в структуру данных 1С. В качестве готового решения можно использовать расширяемый редактор форматированного текста на базе поля HTML.

Важные моменты:

Итоги

Выясним, какой метод выбрать. Если задача простая и точность в доли секунды не важна — ПодключитьОбработчикОжидания с анализом ПолучитьГраницыВыделения() вполне применим как быстрое решение. Однако для создания профессионального и отзывчивого интерфейса "редактора-конструктора" единственным верным путем является использование Поля HTML документа с внедрением JavaScript-обработчиков событий onclick или selectionchange.

← На главную