//ирПортативный Перем ирПортативный Экспорт; //ирПортативный Перем ирОбщий Экспорт; //ирПортативный Перем ирСервер Экспорт; //ирПортативный Перем ирКэш Экспорт; //ирПортативный Перем ирКлиент Экспорт; #Если Клиент Тогда Перем мРедакторHTML; // Кэш Перем НачальнаяСтрока, НачальнаяКолонка, КонечнаяСтрока, КонечнаяКолонка; // Временные переменные для всех методов Перем ЛиВнутриУстановкиТекста; Перем мПлатформа; Перем мСлужебнаяФорма; // Получает интерфейс редактора MonacoBSL Функция РедакторHTML() Экспорт Если Истина И мРедакторHTML = Неопределено И ЛиПолеHTMLДокумента() Тогда мРедакторHTML = ЭлементФормы.Документ.defaultView; // COMОбъект Попытка Если Не ЗначениеЗаполнено(мРедакторHTML.version1C) Тогда мРедакторHTML = Неопределено; КонецЕсли; Исключение мРедакторHTML = Неопределено; КонецПопытки; КонецЕсли; Возврат мРедакторHTML; КонецФункции Функция ЛиПолеHTMLДокумента() Результат = Ложь Или ТипЗнч(ЭлементФормы) = Тип("ПолеHTMLДокумента") Или (Истина И ТипЗнч(ЭлементФормы) = Тип("ПолеФормы") И (Ложь Или ЭлементФормы.Вид = ВидПоляФормы.ПолеHTMLДокумента)); Возврат Результат; КонецФункции // Процедура - Установить границы выделения // // Параметры: // НачальнаяСтрокаИлиПозиция - - // НачальнаяКолонкаИлиКонечнаяПозиция - - // КонечнаяСтрока - - // КонечнаяКолонка - - // Активировать - - // ЭтаФорма - Форма - нужно передавать для формы и поля и исправления ошибки платформы 8.3.22 с прокруткой // Процедура УстановитьГраницыВыделения(Знач НачальнаяСтрокаИлиПозиция, Знач НачальнаяКолонкаИлиКонечнаяПозиция, Знач КонечнаяСтрока = Неопределено, Знач КонечнаяКолонка = Неопределено, Знач Активировать = Ложь, Знач ЭтаФорма = Неопределено, Знач ОшибкаПриВыходеЗаКонец = Истина) Экспорт Если Не ОшибкаПриВыходеЗаКонец Тогда Если КонечнаяСтрока = Неопределено Тогда ДлинаТекста = Макс(1, СтрДлина(ПолучитьТекст()) + 1); НачальнаяСтрокаИлиПозиция = Мин(ДлинаТекста, НачальнаяСтрокаИлиПозиция); НачальнаяКолонкаИлиКонечнаяПозиция = Мин(ДлинаТекста, НачальнаяКолонкаИлиКонечнаяПозиция); КонецЕсли; КонецЕсли; Если ЛиПолеHTMLДокумента() Тогда РедакторHTML = РедакторHTML(); Если РедакторHTML = Неопределено Тогда Выделение = Новый Структура; Если КонечнаяСтрока = Неопределено Тогда Выделение.Вставить("Начало", НачальнаяСтрокаИлиПозиция); Выделение.Вставить("Конец", НачальнаяКолонкаИлиКонечнаяПозиция); Иначе Выделение.Вставить("Начало", ОдномернаяПозицияИзДвумерной(НачальнаяСтрокаИлиПозиция, НачальнаяКолонкаИлиКонечнаяПозиция)); Выделение.Вставить("Конец", ОдномернаяПозицияИзДвумерной(КонечнаяСтрока, КонечнаяКолонка)); КонецЕсли; // Для 8.3.13- Выделение.Вставить("НачалоБезПереносов", Выделение.Начало); Выделение.Вставить("КонецБезПереносов", Выделение.Конец); УстановитьВыделениеВДокументеHTML(Выделение); Иначе Если КонечнаяСтрока = Неопределено Тогда РедакторHTML.setSelectionByLength(НачальнаяСтрокаИлиПозиция, НачальнаяКолонкаИлиКонечнаяПозиция); Иначе РедакторHTML.setSelection(НачальнаяСтрокаИлиПозиция, НачальнаяКолонкаИлиКонечнаяПозиция, КонечнаяСтрока, КонечнаяКолонка); КонецЕсли; Если Активировать Тогда РедакторHTML.editor.focus(); КонецЕсли; КонецЕсли; Иначе Если КонечнаяСтрока = Неопределено Тогда ЭлементФормы.УстановитьГраницыВыделения(НачальнаяСтрокаИлиПозиция, НачальнаяКолонкаИлиКонечнаяПозиция); Иначе ЭлементФормы.УстановитьГраницыВыделения(НачальнаяСтрокаИлиПозиция, НачальнаяКолонкаИлиКонечнаяПозиция, КонечнаяСтрока, КонечнаяКолонка); КонецЕсли; Если Истина // Похоже эта проверка не улучшает логику работы, а только лишь немного ускоряет И ЭтаФорма <> Неопределено И ЭтаФорма.ТекущийЭлемент = ЭлементФормы И ирКэш.НомерИзданияПлатформыЛкс() >= "83" // https://www.hostedredmine.com/issues/934802 Тогда // Антибаг платформы https://www.hostedredmine.com/issues/929519 ирКлиент.УстановитьФокусВводаФормеЛкс(); #Если Сервер И Не Сервер Тогда мПлатформа = Обработки.ирПлатформа.Создать() #КонецЕсли Если Истина И мПлатформа.ИспользоватьЭмуляциюНажатияКлавиш() И ирКэш.НомерВерсииПлатформыЛкс() = 803022 Тогда // Антибаг платформы 8.3.22 https://www.hostedredmine.com/issues/958530 ирКлиент.ОтправитьНажатияКлавишЛкс("+{right}"); ирКлиент.ОтправитьНажатияКлавишЛкс("+{left}"); КонецЕсли; КонецЕсли; КонецЕсли; КонецПроцедуры Функция ДвухмернаяПозицияИзОдномерной(Позиция) Результат = Новый Структура("НомерСтроки, НомерКолонки"); // TODO //УстановитьГраницыВыделения(1, Позиция); //Текст = ВыделенныйТекст(); //Результат.НомерСтроки = СтрЧислоВхождений(Текст, Символы.ПС); //Результат.НомерКолонки = СтрДлина(СтрПолучитьСтроку(Текст, Результат.НомерСтроки)); Возврат Результат; КонецФункции Функция ОдномернаяПозицияИзДвумерной(НомерСтроки, НомерКолонки) // TODO Сделать через рег. выражение подсчетом номер вхождения любого разделителя строк Возврат 1; КонецФункции Процедура ПолучитьГраницыВыделения(НачальнаяСтрока, НачальнаяКолонка, КонечнаяСтрока, КонечнаяКолонка) Экспорт Если ЛиПолеHTMLДокумента() Тогда РедакторHTML = РедакторHTML(); Если РедакторHTML = Неопределено Тогда // TODO отличить монако и обычный редакторы //ВыделениеТекста = ПолучитьВыделениеВДокументеHTML(); //КоординатыПозиции = ДвухмернаяПозицияИзОдномерной(ВыделениеТекста.Начало); //НачальнаяСтрока = КоординатыПозиции.НомерСтроки; //НачальнаяКолонка = КоординатыПозиции.НомерКолонки; //КоординатыПозиции = ДвухмернаяПозицияИзОдномерной(ВыделениеТекста.Начало); //КонечнаяСтрока = КоординатыПозиции.НомерСтроки; //КонечнаяКолонка = КоординатыПозиции.НомерКолонки; Иначе ВыделениеТекста = РедакторHTML.getSelection(); НачальнаяСтрока = ВыделениеТекста.startLineNumber; НачальнаяКолонка = ВыделениеТекста.startColumn; КонечнаяСтрока = ВыделениеТекста.endLineNumber; КонечнаяКолонка = ВыделениеТекста.endColumn; КонецЕсли; Иначе ЭлементФормы.ПолучитьГраницыВыделения(НачальнаяСтрока, НачальнаяКолонка, КонечнаяСтрока, КонечнаяКолонка); КонецЕсли; КонецПроцедуры Функция ПолучитьТекст(Знач Сырой = Истина) Экспорт Если ЛиПолеHTMLДокумента() Тогда РедакторHTML = РедакторHTML(); Если Истина И РедакторHTML = Неопределено И ирКэш.ДоступенБраузерWebKitЛкс() И ЭлементФормы.Документ.ЭтоРедактор = Истина Тогда Возврат ""; ИначеЕсли РедакторHTML = Неопределено Тогда Если Истина И Сырой И (Ложь Или ирКэш.ДоступенБраузерWebKitЛкс() Или ЭлементФормы.Документ.ЭтоРедактор <> Истина) Тогда Текст = ЭлементФормы.ПолучитьТекст(); Иначе Если ирКэш.ДоступенБраузерWebKitЛкс() Тогда ДокументHtml = ЭлементФормы.Документ; //Текст = ДокументHtml.body.textContent; Текст = ДокументHtml.body.innerText; Иначе Текст = ЭлементФормы.ПолучитьТекст(); ДокументHtml = ирОбщий.ПолучитьHtmlFileИзТекстаHtmlЛкс(Текст); // Тут переносы строк другое количество символов дают. Скорее всего из-за Символы.ВК Текст = ДокументHtml.body.innerText; КонецЕсли; КонецЕсли; Иначе Текст = РедакторHTML.getText(); КонецЕсли; ИначеЕсли ТипЗнч(ЭлементФормы) = Тип("ПолеВвода") Тогда Текст = ЭлементФормы.Значение; ИначеЕсли ТипЗнч(ЭлементФормы) = Тип("ПолеФормы") Тогда Текст = ирОбщий.ДанныеЭлементаФормыЛкс(ЭлементФормы); Иначе Текст = ЭлементФормы.ПолучитьТекст(); КонецЕсли; Возврат Текст; КонецФункции // Для не редактора устанавливает всегда сырой текст Функция УстановитьТекст(Знач Текст, Активировать = Ложь, НачальныйТекстДляСравнения = Неопределено, СохранитьГраницыВыделения = Ложь) Экспорт Если СохранитьГраницыВыделения Тогда СтруктураВыделения = ВыделениеДвумерное(); КонецЕсли; Если ЛиПолеHTMLДокумента() Тогда РедакторHTML = РедакторHTML(); Если Истина И РедакторHTML = Неопределено И ирКэш.ДоступенБраузерWebKitЛкс() И ЭлементФормы.Документ.ЭтоРедактор = Истина Тогда Возврат Ложь; ИначеЕсли РедакторHTML = Неопределено Тогда ЭлементФормы.УстановитьТекст(Текст); //УстановитьТелоHTML(ирОбщий.КодироватьТекстВXMLЛкс(Текст)); Иначе Если СтрЧислоСтрок(Текст) <> СтрЧислоСтрок(ПолучитьТекст()) Тогда РедакторHTML.removeAllBookmarks(); КонецЕсли; Если Активировать Тогда РедакторHTML.editor.focus(); КонецЕсли; // https://github.com/salexdv/bsl_console/issues/141#issuecomment-852355305 РедакторHTML.updateText(Текст); //РедакторHTML.editor.setValue(Текст); // Так история редактирования сбрасывается и устанавливается модифицированность Если НачальныйТекстДляСравнения <> Неопределено Тогда РедакторHTML.setOriginalText(НачальныйТекстДляСравнения); КонецЕсли; УстановитьДекорации(); КонецЕсли; ИначеЕсли ТипЗнч(ЭлементФормы) = Тип("ПолеВвода") Тогда ЭлементФормы.Значение = Текст; ИначеЕсли ТипЗнч(ЭлементФормы) = Тип("ПолеФормы") Тогда ЭтаФорма = Неопределено; ПутьКДанным = ""; ирОбщий.ДанныеЭлементаФормыЛкс(ЭлементФормы, ПутьКДанным, ЭтаФорма); Если ЗначениеЗаполнено(ПутьКДанным) Тогда Выполнить("ЭтаФорма." + ПутьКДанным + " = Текст"); КонецЕсли; Иначе ЭлементФормы.УстановитьТекст(Текст); КонецЕсли; Если СохранитьГраницыВыделения Тогда УстановитьВыделениеДвумерное(СтруктураВыделения); КонецЕсли; Возврат Истина; КонецФункции Процедура УстановитьДекорации(Знач МассивСтрок = Неопределено) Экспорт Если МассивСтрок = Неопределено Тогда МассивСтрок = Новый Массив; КонецЕсли; РедакторHTML = РедакторHTML(); РедакторHTML.setLineNumbersDecorations(ирОбщий.ОбъектВСтрокуJSONЛкс(МассивСтрок)); КонецПроцедуры Функция ПолучитьСтроку(НомерСтроки) Экспорт Если ТипЗнч(ЭлементФормы) = Тип("ПолеВвода") Тогда ТекстовыйДокумент = Новый ТекстовыйДокумент; ТекстовыйДокумент.УстановитьТекст(ЭлементФормы.Значение); Текст = ТекстовыйДокумент.ПолучитьСтроку(НомерСтроки); ИначеЕсли ЛиПолеHTMLДокумента() Тогда РедакторHTML = РедакторHTML(); Если РедакторHTML = Неопределено Тогда Возврат Неопределено; КонецЕсли; Текст = РедакторHTML.getLineContent(НомерСтроки); Иначе Текст = ЭлементФормы.ПолучитьСтроку(НомерСтроки); КонецЕсли; Возврат Текст; КонецФункции Функция КоличествоСтрок() Экспорт Если ЛиПолеHTMLДокумента() Тогда РедакторHTML = РедакторHTML(); Если РедакторHTML = Неопределено Тогда Возврат Неопределено; КонецЕсли; Текст = РедакторHTML.getLineCount(); Иначе Текст = ЭлементФормы.КоличествоСтрок(); КонецЕсли; Возврат Текст; КонецФункции Функция ВыделенныйТекст(НовыйТекст = Неопределено) Экспорт Если ЛиПолеHTMLДокумента() Тогда РедакторHTML = РедакторHTML(); Если РедакторHTML = Неопределено Тогда Возврат Неопределено; КонецЕсли; Если НовыйТекст = Неопределено Тогда Результат = РедакторHTML.selectedText(); Иначе РедакторHTML.selectedText(НовыйТекст); //// https://github.com/salexdv/bsl_console/issues/64#issue-873784658 //ПолучитьГраницыВыделения(НачальнаяСтрока, НачальнаяКолонка, КонечнаяСтрока, КонечнаяКолонка); //УстановитьГраницыВыделения(КонечнаяСтрока, КонечнаяКолонка, КонечнаяСтрока, КонечнаяКолонка); КонецЕсли; Иначе Если НовыйТекст = Неопределено Тогда Результат = ЭлементФормы.ВыделенныйТекст; Иначе ЭлементФормы.ВыделенныйТекст = НовыйТекст; КонецЕсли; КонецЕсли; Возврат Результат; КонецФункции Функция ТолькоПросмотр(НовыйРежим = Неопределено) Экспорт Если ЛиПолеHTMLДокумента() Тогда РедакторHTML = РедакторHTML(); Если РедакторHTML = Неопределено Тогда Возврат Неопределено; КонецЕсли; Если НовыйРежим = Неопределено Тогда Результат = РедакторHTML.getReadOnly(); Иначе РедакторHTML.setReadOnly(НовыйРежим); КонецЕсли; Иначе Если НовыйРежим = Неопределено Тогда Результат = ЭлементФормы.ТолькоПросмотр; Иначе ЭлементФормы.ТолькоПросмотр = НовыйРежим; КонецЕсли; КонецЕсли; Возврат Результат; КонецФункции Процедура ЗаменитьСтроку(НомерСтроки, Текст) Экспорт Если ЛиПолеHTMLДокумента() Тогда РедакторHTML = РедакторHTML(); Если РедакторHTML = Неопределено Тогда Возврат; КонецЕсли; РедакторHTML.setLineContent(НомерСтроки, Текст); // https://github.com/salexdv/bsl_console/issues/90 //УстановитьГраницыВыделения(НомерСтроки, 1 , НомерСтроки, СтрДлина(ПолучитьСтроку(НомерСтроки)) + 1); //ВыделенныйТекст(Текст); Иначе ЭлементФормы.ЗаменитьСтроку(НомерСтроки, Текст); // Баг платформы. Вызывает выделение всего предшествующего текста на 8.3.18 КонецЕсли; КонецПроцедуры Процедура ВставитьСтроку(НомерСтроки, Текст) Экспорт Если ЛиПолеHTMLДокумента() Тогда РедакторHTML = РедакторHTML(); Если РедакторHTML = Неопределено Тогда Возврат; КонецЕсли; РедакторHTML.insertLine(НомерСтроки, Текст); Иначе ЭлементФормы.ВставитьСтроку(НомерСтроки, Текст); КонецЕсли; КонецПроцедуры Процедура ДобавитьСтроку(Текст) Экспорт Если ЛиПолеHTMLДокумента() Тогда РедакторHTML = РедакторHTML(); Если РедакторHTML = Неопределено Тогда Возврат; КонецЕсли; //ДлинаТекста = СтрДлина(ПолучитьТекст()); //РедакторHTML.setText(Символы.ПС + Текст, ДлинаТекста); РедакторHTML.AddLine(Текст); Иначе ЭлементФормы.ДобавитьСтроку(Текст); КонецЕсли; КонецПроцедуры Процедура УдалитьСтроку(НомерСтроки) Экспорт Если ЛиПолеHTMLДокумента() Тогда РедакторHTML = РедакторHTML(); Если РедакторHTML = Неопределено Тогда Возврат; КонецЕсли; РедакторHTML.deleteLine(НомерСтроки); Иначе ЭлементФормы.УдалитьСтроку(НомерСтроки); КонецЕсли; КонецПроцедуры // Заменяет выделенный текст новым Процедура ВставитьТекст(Знач НовыйТекст, Знач ДобавитьНовуюСтрокуПосле = Истина) Экспорт НачальнаяПозиция = 0; КонечнаяПозиция = 0; ПолучитьГраницыВыделения(НачальнаяПозиция, КонечнаяПозиция, НачальнаяПозиция, КонечнаяПозиция); ВыделенныйТекст(НовыйТекст); Если ДобавитьНовуюСтрокуПосле Тогда // Антибаг 8.3.12 https://partners.v8.1c.ru/forum/t/1719342/m/1719342, http://www.hostedredmine.com/issues/882423 ВыделенныйТекст(Символы.ПС); КонецЕсли; УстановитьГраницыВыделения(НачальнаяПозиция, КонечнаяПозиция, НачальнаяПозиция, КонечнаяПозиция); КонецПроцедуры Процедура Очистить() Экспорт Если ЛиПолеHTMLДокумента() Тогда РедакторHTML = РедакторHTML(); Если РедакторHTML = Неопределено Тогда Возврат; КонецЕсли; РедакторHTML.eraseText(); Иначе ЭлементФормы.Очистить(); КонецЕсли; КонецПроцедуры Процедура ПоказатьОшибку(НомерСтроки, НомерКолонки = 1, ЭтаФорма = Неопределено) Экспорт Если ЛиПолеHTMLДокумента() Тогда РедакторHTML = РедакторHTML(); Если РедакторHTML = Неопределено Тогда Возврат; КонецЕсли; УстановитьГраницыВыделения(НомерСтроки, 1, НомерСтроки, 1,, ЭтаФорма); РедакторHTML.markError(НомерСтроки, НомерКолонки); Иначе УстановитьГраницыВыделения(НомерСтроки, 1, НомерСтроки, 150,, ЭтаФорма); КонецЕсли; КонецПроцедуры Процедура ПолучитьПозициюКаретки(ВКОбщая, Форма, Знач Панель = Неопределено, Знач СмещениеГориз = 0, Знач СмещениеВерт = 0) Экспорт РедакторHTML = РедакторHTML(); Если РедакторHTML <> Неопределено Тогда Если Панель = Неопределено Тогда Панель = Форма.ЭлементыФормы.Найти("ПанельРедактора"); КонецЕсли; Координаты = РедакторHTML.getPositionOffset(); ВременноеПолеВвода = Форма.ЭлементыФормы.Добавить(Тип("ПолеВвода"), "ПолеВвода" + ирОбщий.СуффиксСлужебногоСвойстваЛкс(), Истина, Панель); ВременноеПолеВвода.Лево = 0; ВременноеПолеВвода.Верх = 0; ВременноеПолеВвода.Высота = 20; ВременноеПолеВвода.Ширина = 1; Форма.ТекущийЭлемент = ВременноеПолеВвода; // Стало необходимо в 8.3.19, иначе фокус не переходил в это поле сразу и координаты каретки получались пустые //Форма.Обновить(); Форма.Открыть(); ВКОбщая.ПолучитьПозициюКаретки(Координаты.left + СмещениеГориз, Координаты.top + 8 + СмещениеВерт); Форма.ТекущийЭлемент = ЭлементФормы; Форма.ЭлементыФормы.Удалить(ВременноеПолеВвода); Иначе Если Форма <> Неопределено Тогда Форма.Активизировать(); КонецЕсли; ВКОбщая.ПолучитьПозициюКаретки(СмещениеГориз, СмещениеВерт); КонецЕсли; КонецПроцедуры Функция КоординатыКурсора() Экспорт ПолучитьГраницыВыделения(НачальнаяСтрока, НачальнаяКолонка, КонечнаяСтрока, КонечнаяКолонка); Результат = Новый Структура("НомерСтроки, НомерКолонки", КонечнаяСтрока, КонечнаяКолонка); Возврат Результат; КонецФункции Процедура Инициировать() Экспорт // Настройки шрифта и окна автодополнения тут #Если Сервер И Не Сервер Тогда Обработки.ирПлатформа.Создать().БазовыйФайлРедактораКода(); #КонецЕсли РедакторHTML = ЭлементФормы.Документ.defaultView; ЭлементСтиля = РедакторHTML.document.createElement("style"); ЭлементСтиля.setAttribute("type", "text/css"); ЭлементСтиля.innerHTML = " // Убираем полосы прокрутки 1С |body { | overflow: hidden; |} // Цвета статусной строки |.statusbar-widget { | background: #c2dfef; | color: #000; |} // Окно подсказки по вызову метода |.editor-widget.parameter-hints-widget .code { | font-size: 13px !important; | line-height: 15px; |} |.editor-widget.parameter-hints-widget .docs { | font-size: 13px !important; | line-height: 15px; |} |.editor-widget.parameter-hints-widget.visible { | max-width: 600px; |} |.monaco-editor .parameter-hints-widget > .wrapper { | max-width: 600px; |} |.monaco-editor-hover .monaco-editor-hover-content { | max-width: 600px; |} // Подсказка удержания |.monaco-editor-hover .hover-row { | font-size: 13px !important; | line-height: 15px; |} // Подсказка автодополнения |.monaco-editor .suggest-widget { | width: 500px; |} // Подсказка автодополнения вместе с окном детальной инфы |.monaco-editor .suggest-widget.docs-side { | width: 1000px; |} |.monaco-editor .suggest-widget.docs-side > .details { | width: 60%; | max-height: 800px !important; |} |.monaco-editor .suggest-widget.docs-side > .tree { | width: 40%; | float: left; |}"; РедакторHTML.document.head.appendChild(ЭлементСтиля); РедакторHTML.showStatusBar(Ложь); // параметр Ложь - отображаем снизу справа РедакторHTML.renderWhitespace(Истина); РедакторHTML.setFontSize(13); РедакторHTML.setLineHeight(15); РедакторHTML.disableContextMenu(); РедакторHTML.setOption("autoResizeEditorLayout", Истина); // https://github.com/salexdv/bsl_console/issues/185 //РедакторHTML.setOption("lineHeight", 15); // Высота строки редактора https://github.com/salexdv/bsl_console/issues/195 //РедакторHTML.setOption("suggestFontSize", 13); // шрифт окна автодополнения https://github.com/salexdv/bsl_console/issues/194 //РедакторHTML.setOption("suggestLineHeight", 15); // шрифт окна автодополнения https://github.com/salexdv/bsl_console/issues/194 //ИмяШрифта = ирКэш.ИмяШрифтаРедактораМодуляКонфигуратораЛкс(); //Если ЗначениеЗаполнено(ИмяШрифта) Тогда // РедакторHTML.setFontFamily(ИмяШрифта); //Иначе РедакторHTML.setFontFamily("Lucida Console"); //КонецЕсли; КонецПроцедуры Процедура ИнициироватьПоле(Знач НовыйЭлементФормы) Экспорт Если НовыйЭлементФормы = Неопределено Тогда мСлужебнаяФорма = мПлатформа.ПолучитьФорму("Служебная"); НовыйЭлементФормы = мПлатформа.НовоеСлужебноеПолеТекста(мСлужебнаяФорма); КонецЕсли; ЭтотОбъект.ЭлементФормы = НовыйЭлементФормы; КонецПроцедуры Процедура Перерисовать() Экспорт РедакторHTML = РедакторHTML(); РедакторHTML.editor.layout(); КонецПроцедуры Процедура ЗагрузитьСостояниеИзПоляТекстаЛкс(Знач ПолеИсточник, Знач ИсходныйТекст) Экспорт #Если Сервер И Не Сервер Тогда ПолеИсточник = ЭтотОбъект; #КонецЕсли ПолеИсточник.ПолучитьГраницыВыделения(НачальнаяСтрока, НачальнаяКолонка, КонечнаяСтрока, КонечнаяКолонка); УстановитьТекст(ПолеИсточник.ПолучитьТекст(), Истина, ИсходныйТекст); УстановитьГраницыВыделения(НачальнаяСтрока, НачальнаяКолонка, КонечнаяСтрока, КонечнаяКолонка); ТолькоПросмотр(ПолеИсточник.ТолькоПросмотр()); КонецПроцедуры Функция СостояниеИсторииИзменения() Экспорт РедакторHTML = РедакторHTML(); Результат = РедакторHTML.editor.saveViewState(); Возврат Результат; КонецФункции Процедура ВосстановитьСостояниеИсторииИзменения(Состояние) Экспорт РедакторHTML = РедакторHTML(); РедакторHTML.editor.restoreViewState(Состояние); КонецПроцедуры // Процедура - Показать последнюю строку // // Параметры: // ЭтаФорма - Форма - нужно передавать для активации поля и для исправления ошибки платформы 8.3.22 с прокруткой // Процедура ПоказатьПоследнююСтроку(ЭтаФорма = Неопределено) Экспорт НомерСтроки = Макс(1, КоличествоСтрок()); // https://www.hostedredmine.com/issues/891268 Если НомерСтроки > 1 Тогда УстановитьГраницыВыделения(НомерСтроки, 1, НомерСтроки, 1,, ЭтаФорма); КонецЕсли; КонецПроцедуры Функция ОбработатьКликНаГиперссылке(Событие) Экспорт СобытиеОбработано = Ложь; ЗаголовокГиперссылки = Событие.params.label; ЗначениеГиперссылки = Событие.params.href; Если Ложь Или ЗаголовокГиперссылки = "перейти по ссылке" Или ирОбщий.СтрНачинаетсяСЛкс(ЗначениеГиперссылки, "http") Тогда ЗапуститьПриложение(ЗначениеГиперссылки); СобытиеОбработано = Истина; КонецЕсли; Возврат СобытиеОбработано; КонецФункции Функция НоваяСтруктураДвумерногоВыделения() Экспорт Структура = Новый Структура(); Структура.Вставить("НачальнаяСтрока", 1); Структура.Вставить("НачальнаяКолонка", 1); Структура.Вставить("КонечнаяСтрока", 1); Структура.Вставить("КонечнаяКолонка", 1); Возврат Структура; КонецФункции Функция ВыделениеДвумерное() Экспорт Структура = НоваяСтруктураДвумерногоВыделения(); ПолучитьГраницыВыделения(Структура.НачальнаяСтрока, Структура.НачальнаяКолонка, Структура.КонечнаяСтрока, Структура.КонечнаяКолонка); Возврат Структура; КонецФункции Функция УстановитьВыделениеДвумерное(Знач Структура) Экспорт Если Структура.НачальнаяКолонка <= 0 Тогда Структура.НачальнаяКолонка = 1; КонецЕсли; Если Структура.НачальнаяСтрока <= 0 Тогда Структура.НачальнаяСтрока = 1; КонецЕсли; Если Структура.КонечнаяСтрока <= 0 Тогда Структура.КонечнаяСтрока = 1; КонецЕсли; УстановитьГраницыВыделения(Структура.НачальнаяСтрока, Структура.НачальнаяКолонка, Структура.КонечнаяСтрока, Структура.КонечнаяКолонка); Возврат Неопределено; КонецФункции // Функция - Позиция в поле текста по номеру строки и колонки. Портит текущее незаконченное выделение мышкой! // // Параметры: // КонечнаяСтрока - - // КонечнаяКолонка - - // // Возвращаемое значение: // - Число - начиная с 1 // Функция ПозицияВПолеТекстаПоНомеруСтрокиИКолонки(Знач КонечнаяСтрока, Знач КонечнаяКолонка, Знач СлужебноеПолеТекста = Неопределено) Экспорт Если СлужебноеПолеТекста = Неопределено Тогда СлужебноеПолеТекста = СлужебноеПолеТекста(); КонецЕсли; СлужебноеПолеТекста.УстановитьГраницыВыделения(1, 1, КонечнаяСтрока, КонечнаяКолонка); Результат = СтрДлина(СлужебноеПолеТекста.ВыделенныйТекст) + 1; Возврат Результат; КонецФункции Функция СлужебноеПолеТекста() #Если Сервер И Не Сервер Тогда мПлатформа = Обработки.ирПлатформа.Создать() #КонецЕсли СлужебноеПолеТекста = мПлатформа.СлужебноеПолеТекста; СлужебноеПолеТекста.УстановитьТекст(ПолучитьТекст()); Возврат СлужебноеПолеТекста; КонецФункции Процедура Прочитать(Знач ИмяФайла) Экспорт Если ТипЗнч(ЭлементФормы) = Тип("ТекстовыйДокумент") Тогда ЭлементФормы.Прочитать(ИмяФайла); Иначе ТекстовыйДокумент = Новый ТекстовыйДокумент; ТекстовыйДокумент.Прочитать(ИмяФайла); УстановитьТекст(ТекстовыйДокумент.ПолучитьТекст()); КонецЕсли; КонецПроцедуры // Процедура - Выделение одномерное // // Параметры: // выхНачальнаяПозиция - Число - начиная с 1 // выхКонечнаяПозиция - Число - начиная с 1 // Функция ВыделениеОдномерное(выхНачальнаяПозиция = Неопределено, выхКонечнаяПозиция = Неопределено) Экспорт ПолучитьГраницыВыделения(НачальнаяСтрока, НачальнаяКолонка, КонечнаяСтрока, КонечнаяКолонка); СлужебноеПолеТекста = СлужебноеПолеТекста(); выхНачальнаяПозиция = ПозицияВПолеТекстаПоНомеруСтрокиИКолонки(НачальнаяСтрока, НачальнаяКолонка, СлужебноеПолеТекста); выхКонечнаяПозиция = ПозицияВПолеТекстаПоНомеруСтрокиИКолонки(КонечнаяСтрока, КонечнаяКолонка, СлужебноеПолеТекста); Возврат Новый Структура("Начало, Конец", выхНачальнаяПозиция, выхКонечнаяПозиция); КонецФункции Функция РазметитьТекстРезультатамиПоиска(Знач Текст = "", Знач РезультатыПоиска, Знач ИндексПодгруппы = -1, Знач ПереносСлов = Истина) Экспорт Если Не ЛиПолеHTMLДокумента() Тогда ВызватьИсключение "Доступно только в поле HTML"; КонецЕсли; Если Не ЗначениеЗаполнено(Текст) Тогда Текст = ПолучитьТекст(Ложь); КонецЕсли; ЭтотОбъект.РезультатыПоиска = РезультатыПоиска; #Если Сервер И Не Сервер Тогда РезультатыПоиска = Новый ТаблицаЗначений; #КонецЕсли МаркерКонецПодгруппы = ""; Результат = Новый ЗаписьXML; Результат.УстановитьСтроку(""); Старт = Истина; Финиш = 0; ЗначениеЧередования = Ложь; МаксРаскашиваемыхВхождений = 1000; //МассивЦветов = Новый Массив; //МассивЦветов.Добавить("yellow"); //МассивЦветов.Добавить("cyan"); //МассивЦветов.Добавить("#CCFF66"); // светло-зеленый //МассивЦветов.Добавить("orange"); РаскрашеноВхождений = 0; ЕстьКолонкаГиперссылки = РезультатыПоиска.Колонки.Найти("ЛиГиперссылка") <> Неопределено; Для каждого Группа Из РезультатыПоиска Цикл Если Группа.ПозицияПодгруппы = Неопределено Или РаскрашеноВхождений > МаксРаскашиваемыхВхождений Тогда Продолжить; КонецЕсли; Если ИндексПодгруппы = -1 Тогда ТекстПодгруппы = Группа.Значение; Иначе ТекстПодгруппы = Группа.Подгруппы[ИндексПодгруппы].Значение; КонецЕсли; Если ТекстПодгруппы = Неопределено Тогда Продолжить; КонецЕсли; ПозицияПодгруппы = Группа.ПозицияПодгруппы; ДлинаПодгруппы = Группа.ДлинаПодгруппы; Если Старт Тогда Если Группа.ПозицияПодгруппы <> 0 Тогда Результат.ЗаписатьБезОбработки(ирОбщий.КодироватьТекстВXMLЛкс(Сред(Текст, 1, ПозицияПодгруппы))); КонецЕсли; Старт = Ложь; ИначеЕсли Финиш <> 0 Тогда Результат.ЗаписатьБезОбработки(ирОбщий.КодироватьТекстВXMLЛкс(Сред(Текст, Финиш, ПозицияПодгруппы - Финиш + 1))); КонецЕсли; ЗначениеПодгруппы = ирОбщий.КодироватьТекстВXMLЛкс(ТекстПодгруппы); Если ЗначениеЧередования Тогда ИмяЦвета = "cyan"; Иначе ИмяЦвета = "yellow"; КонецЕсли; Если ЕстьКолонкаГиперссылки И Группа.ЛиГиперссылка Тогда // https://stackoverflow.com/questions/42692953/make-hyperlinks-selectable ТегВхождения = "" + ЗначениеПодгруппы + ""; Иначе ТегВхождения = "" + ЗначениеПодгруппы + ""; КонецЕсли; Результат.ЗаписатьБезОбработки(ТегВхождения); РаскрашеноВхождений = РаскрашеноВхождений + 1; Финиш = ПозицияПодгруппы + ДлинаПодгруппы + 1; ЗначениеЧередования = Не ЗначениеЧередования; КонецЦикла; Результат.ЗаписатьБезОбработки(ирОбщий.КодироватьТекстВXMLЛкс(Сред(Текст, Финиш))); Результат = Результат.Закрыть(); УстановитьТелоHTML(Результат, ПереносСлов); КонецФункции Процедура УстановитьТелоHTML(Знач ТекстHTML, Знач ПереносСлов = Истина) ОформлениеТекста = "
";
	РаскрашенныйТекст = "" + ОформлениеТекста + РаскрашенныйТекст + ТекстHTML + "";
	ДокументHtml = ЭлементФормы.Документ;
	Попытка
		ДокументHtml.documentElement.innerHTML = РаскрашенныйТекст;
	Исключение
		// 8.2
		ДокументHtml.body.innerHTML = РаскрашенныйТекст;
	КонецПопытки; 

КонецПроцедуры

Процедура УстановитьОтображаемыйТекст(Знач Текст, Знач ПереносСлов = Истина) Экспорт 
	
	УстановитьТелоHTML(ирОбщий.КодироватьТекстВXMLЛкс(Текст), ПереносСлов);

КонецПроцедуры

Функция ИдентификаторПодгруппыВРазмеченномТексте(Знач НомерГруппы, Знач ИндексПодгруппы = Неопределено) Экспорт 
	
	Если ИндексПодгруппы < 0 Тогда
		ИндексПодгруппы = "";
	Иначе
		ИндексПодгруппы = XMLСтрока(ИндексПодгруппы);
	КонецЕсли;
	Возврат "Match" + НомерГруппы + "_SubMatch" + ИндексПодгруппы;

КонецФункции

Процедура ВыделитьРезультатПоиска(Знач РезультатПоиска, Знач ИндексПодгруппы = -1) Экспорт 
	
	#Если Сервер И Не Сервер Тогда
		РезультатПоиска = РезультатыПоиска.Добавить();
	#КонецЕсли
	ДокументHtml = ЭлементФормы.Документ;
	ИДНужныйУзел = ИдентификаторПодгруппыВРазмеченномТексте(РезультатПоиска.Номер, ИндексПодгруппы);
	ТегГруппы = Неопределено;
	//ТегГруппы = ДокументHtml.getElementByID(ИДНужныйУзел); // начиная с 8.3.14 так не работает
	ТегГруппы = ДокументHtml.querySelector("[id = " + ИДНужныйУзел + "]");
	ТелоДокумента = ДокументHtml.body;
	Если ТегГруппы <> Неопределено Тогда
		Если ирКэш.ДоступенБраузерWebKitЛкс() Тогда
			ВыделениеВТексте = Новый Структура;
			ВыделениеВТексте.Вставить("Начало", 0);
			ВыделениеВТексте.Вставить("НачалоБезПереносов", 0);
			ВыделениеВТексте.Вставить("Конец", РезультатПоиска.Длина);
			ВыделениеВТексте.Вставить("КонецБезПереносов", 0);
			УстановитьВыделениеВДокументеHTML(ВыделениеВТексте, ТегГруппы);
		Иначе
			Диапазон = ТелоДокумента.createTextRange();
			Диапазон.moveToElementText(ТегГруппы);
			Диапазон.scrollIntoView();
			Диапазон.Select();
		КонецЕсли; 
	КонецЕсли;

КонецПроцедуры

Функция ПолучитьВыделениеВДокументеHTML(выхТекст = "") Экспорт  
	
	ВыделениеВТексте = Новый Структура;
	ДокументHtml = ЭлементФормы.Документ;
	ТелоДокумента = ДокументHtml.body;
	Если ирКэш.ДоступенБраузерWebKitЛкс() Тогда
		ТекущееВыделение = ДокументHtml.getSelection();
		Диапазон = ДокументHtml.createRange();
		Диапазон.setStart(ДокументHtml.body, 0); // !!! Без этой строки начало диапазона может захватывать какой то мусор. Видимо ошибка платформы
		Диапазон.setEnd(ТекущееВыделение.anchorNode, ТекущееВыделение.anchorOffset);
		ТекстВыделения = Диапазон.toString();
		Начало = СтрДлина(ТекстВыделения);
		ТекстВыделения = СтрЗаменить(ТекстВыделения, Символы.ПС, "");
		НачалоБезПереносов = СтрДлина(ТекстВыделения);
		Диапазон = ДокументHtml.createRange();
		Диапазон.setStart(ТекущееВыделение.anchorNode, ТекущееВыделение.anchorOffset);
		Диапазон.setEnd(ТекущееВыделение.focusNode, ТекущееВыделение.focusOffset);
		ТекстВыделения = Диапазон.toString();
		Конец = Начало + СтрДлина(ТекстВыделения);
		выхТекст = ТекстВыделения;
		ТекстВыделения = СтрЗаменить(ТекстВыделения, Символы.ПС, "");
		КонецБезПереносов = НачалоБезПереносов + СтрДлина(ТекстВыделения);
		ВыделениеВТексте.Вставить("Начало", Начало);
		ВыделениеВТексте.Вставить("НачалоБезПереносов", НачалоБезПереносов);
		ВыделениеВТексте.Вставить("Конец", Конец);
		ВыделениеВТексте.Вставить("КонецБезПереносов", КонецБезПереносов);
	Иначе
		ТекущееВыделение = ДокументHtml.Selection.createRange();
		Диапазон = ТелоДокумента.createTextRange();
		Диапазон.setEndPoint("EndToStart", ТекущееВыделение);
		ВыделениеВТексте.Вставить("Начало", СтрДлина(Диапазон.Text));
		ВыделениеВТексте.Вставить("НачалоБезПереносов", СтрДлина(СтрЗаменить(Диапазон.Text, Символы.ПС, "")));
		Диапазон.setEndPoint("EndToEnd", ТекущееВыделение);
		ВыделениеВТексте.Вставить("Конец", СтрДлина(Диапазон.Text));
		ВыделениеВТексте.Вставить("КонецБезПереносов", СтрДлина(СтрЗаменить(Диапазон.Text, Символы.ПС, "")));
		выхТекст = Диапазон.Text;
	КонецЕсли;
	Возврат ВыделениеВТексте;

КонецФункции

Процедура УстановитьВыделениеВДокументеHTML(Знач ВыделениеВТексте, РодительскийУзел = Неопределено) Экспорт 
	
	ДокументHtml = ЭлементФормы.Документ;
	ТелоДокумента = ДокументHtml.body;
	Если РодительскийУзел = Неопределено Тогда
		РодительскийУзел = ТелоДокумента;
	КонецЕсли; 
	Если ирКэш.ДоступенБраузерWebKitЛкс() Тогда
		//ВыделенныйТекст = Диапазон.toString(); // Для отладки
		РодительскийУзел.scrollIntoViewIfNeeded();
		Диапазон = ДокументHtml.createRange();
		Диапазон.selectNodeContents(РодительскийУзел);
		ТекстовыеУзлы = ТекстовыеУзлыHTMLВнутри(РодительскийУзел);
		НачалоНайдено = Ложь;
		СчетчикСимволов = 0;
		СчетчикУзлов = 0;
		Для Каждого ТекстовыйУзел Из ТекстовыеУзлы Цикл 
			endCharCount = СчетчикСимволов + СтрДлина(ТекстовыйУзел.textContent);
			Если Истина
				И Не НачалоНайдено 
				И ВыделениеВТексте.Начало >= СчетчикСимволов
				И (Ложь
					Или ВыделениеВТексте.Начало < endCharCount 
					Или (ВыделениеВТексте.Начало = endCharCount И СчетчикУзлов <= ТекстовыеУзлы.Количество()))
			Тогда 
				Диапазон.setStart(ТекстовыйУзел, ВыделениеВТексте.Начало - СчетчикСимволов);
				НачалоНайдено = Истина;
			КонецЕсли; 
			Если НачалоНайдено И ВыделениеВТексте.Конец <= endCharCount Тогда 
				Диапазон.setEnd(ТекстовыйУзел, ВыделениеВТексте.Конец - СчетчикСимволов);
				Прервать;
			КонецЕсли; 
			СчетчикСимволов = endCharCount;
			СчетчикУзлов = СчетчикУзлов + 1;
		КонецЦикла; 
		ТекущееВыделение = ДокументHtml.getSelection();
		ТекущееВыделение.removeAllRanges();
		ТекущееВыделение.addRange(Диапазон);
	Иначе
		Диапазон = РодительскийУзел.createTextRange();
		Диапазон.Collapse();
		Диапазон.moveStart("character", ВыделениеВТексте.НачалоБезПереносов);
		Диапазон.moveEnd("character", ВыделениеВТексте.КонецБезПереносов - ВыделениеВТексте.НачалоБезПереносов);
		Диапазон.select();
	КонецЕсли;

КонецПроцедуры

Функция ТекстовыеУзлыHTMLВнутри(Узел, ТекстовыеУзлы = Неопределено)
	Если ТекстовыеУзлы = Неопределено Тогда
		ТекстовыеУзлы = Новый Массив;
	КонецЕсли; 
	Если Узел.nodeType = 3 Тогда 
		ТекстовыеУзлы.Добавить(Узел);
	Иначе
		Потомки = Узел.childNodes;
		Для Каждого Потомок Из Потомки Цикл
			ТекстовыеУзлыHTMLВнутри(Потомок, ТекстовыеУзлы);
		КонецЦикла;
	КонецЕсли; 
	Возврат ТекстовыеУзлы;
КонецФункции

#КонецЕсли

//ирПортативный лФайл = Новый Файл(ИспользуемоеИмяФайла);
//ирПортативный ПолноеИмяФайлаБазовогоМодуля = Лев(лФайл.Путь, СтрДлина(лФайл.Путь) - СтрДлина("Модули\")) + "ирПортативный.epf";
//ирПортативный #Если Клиент Тогда
//ирПортативный 	Контейнер = Новый Структура();
//ирПортативный 	Оповестить("ирПолучитьБазовуюФорму", Контейнер);
//ирПортативный 	Если Не Контейнер.Свойство("ирПортативный", ирПортативный) Тогда
//ирПортативный 		ирПортативный = ВнешниеОбработки.ПолучитьФорму(ПолноеИмяФайлаБазовогоМодуля);
//ирПортативный 		ирПортативный.Открыть();
//ирПортативный 	КонецЕсли; 
//ирПортативный #Иначе
//ирПортативный 	ирПортативный = ВнешниеОбработки.Создать(ПолноеИмяФайлаБазовогоМодуля, Ложь); // Это будет второй экземпляр объекта
//ирПортативный #КонецЕсли
//ирПортативный ирОбщий = ирПортативный.ОбщийМодульЛкс("ирОбщий");
//ирПортативный ирКэш = ирПортативный.ОбщийМодульЛкс("ирКэш");
//ирПортативный ирСервер = ирПортативный.ОбщийМодульЛкс("ирСервер");
//ирПортативный ирКлиент = ирПортативный.ОбщийМодульЛкс("ирКлиент");

мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
	ФиксированноеВыделениеДвумерное = НоваяСтруктураДвумерногоВыделения();
#КонецЕсли