Имя: Пароль:
1C
 
Тупой обход всех 1000 узлов HTML документа занимает 400мс
0 TormozIT
 
гуру
12.09.22
18:55
Изначальная задача у меня - получить количество символов текста от начала документа позиции каретки.
В IE был быстрый способ получить ответ
        ТекущееВыделение = ДокументHtml.Selection.createRange();
        Диапазон = ТелоДокумента.createTextRange();
        Диапазон.setEndPoint("EndToStart", ТекущееВыделение);
        ВыделениеВТексте.Вставить("Начало", СтрДлина(Диапазон.Text));
Но с приходом webKit этот способ исчез.
Я нашел только способ путем перебора всех улов и сложения длин их текстов.
Однако меня ждала большая плата по скорости - Тупой обход всех 1000 узлов HTML документа занимает 400мс
https://i.imgur.com/MD3Ynfu.png
Функция ТекстовыеУзлыHTMLВнутриЛкс(Узел, ТекстовыеУзлы = Неопределено) Экспорт
    Если ТекстовыеУзлы = Неопределено Тогда
        ТекстовыеУзлы = Новый Массив;
    КонецЕсли;
    Если Узел.nodeType = 3 Тогда
        ТекстовыеУзлы.Добавить(Узел);
    Иначе
        Потомки = Узел.childNodes;
        Для Каждого Потомок Из Потомки Цикл
            ТекстовыеУзлыHTMLВнутриЛкс(Потомок, ТекстовыеУзлы);
        КонецЦикла;
    КонецЕсли;
    Возврат ТекстовыеУзлы;
КонецФункции

1. Подскажите почему обхов всех узлов занимает так много времени?
2. Есть ли какой то еще способ решить изначальную задачу подсчета количества символов в тексте документа до позиции каретки?
2 TormozIT
 
гуру
12.09.22
19:07
(1) Зато createTextRange() куда то делась
4 TormozIT
 
гуру
12.09.22
19:09
(3) Не могу. А ты можешь?
5 H A D G E H O G s
 
12.09.22
19:11
(0) Вынеси во внешнюю компоненту
6 Злопчинский
 
12.09.22
19:16
(5) неспортивно
8 TormozIT
 
гуру
12.09.22
19:30
(7) Ловко ты ушел от ответа.
10 TormozIT
 
гуру
12.09.22
19:48
(9) Получается ты тоже не можешь как. Даже на чистом JavaScript пример не показал. Так что твои "отцовские" поучения выглядят слабенько.
11 Garykom
 
гуру
12.09.22
20:52
Функцию JS вставить и выполнить.
12 Garykom
 
гуру
12.09.22
20:57
13 TormozIT
 
гуру
12.09.22
21:06
Получить с применением cloneContents()

        ТекущееВыделение = ДокументHtml.getSelection();
        Диапазон = ДокументHtml.createRange();
        Диапазон.setEnd(ТекущееВыделение.focusNode, ТекущееВыделение.focusOffset);
        ТекстовыйУзел = Диапазон.cloneContents();
        Начало = СтрДлина(ТекстовыйУзел.textContent);
        Диапазон = ДокументHtml.createRange();
        Диапазон.setStart(ТекущееВыделение.anchorNode, ТекущееВыделение.anchorOffset);
        Диапазон.setEnd(ТекущееВыделение.focusNode, ТекущееВыделение.focusOffset);
        ТекстовыйУзел = Диапазон.cloneContents();
        Конец = Начало + СтрДлина(ТекстовыйУзел.textContent);
        ТекстВыделения = ТекстовыйУзел.textContent;
14 TormozIT
 
гуру
12.09.22
21:15
Теперь более сложная задача. Нужно восстановить выделение в документе по полученным в (13) смещениям.
15 TormozIT
 
гуру
12.09.22
21:30
(13) Немного попутал в 3-й строке

        ТекущееВыделение = ДокументHtml.getSelection();
        Диапазон = ДокументHtml.createRange();
        Диапазон.setEnd(ТекущееВыделение.anchorNode, ТекущееВыделение.anchorOffset); // Тут неверный узел был в старой версии
        ТекстовыйУзел = Диапазон.cloneContents();
        ТекстВыделения = ТекстовыйУзел.textContent;
        Начало = СтрДлина(ТекстВыделения);
        Диапазон = ДокументHtml.createRange();
        Диапазон.setStart(ТекущееВыделение.anchorNode, ТекущееВыделение.anchorOffset);
        Диапазон.setEnd(ТекущееВыделение.focusNode, ТекущееВыделение.focusOffset);
        ТекстовыйУзел = Диапазон.cloneContents();
        ТекстВыделения = ТекстовыйУзел.textContent;
        Конец = Начало + СтрДлина(ТекстВыделения);
16 TormozIT
 
гуру
12.09.22
23:43
(12) Спасибо. Полезная статья.
Еще поймал беду. Оказалось, что объект Range сразу после создания может началом указывать на какие то мусорные данные (перед началом body). Такое случалось у меня только в одном месте.
Поэтому я все таки добавил setStart на начало body.
Еще удалил вызовы cloneContents(), т.к. выяснил что toString() у меня не работал из-за ошибки в тесте, а я думал что это просто ограниченная реализация в 1С.
В итоге проверил уже в 2-х формах
        ТекущееВыделение = ДокументHtml.getSelection();
        Диапазон = ДокументHtml.createRange();
        Диапазон.setStart(ДокументHtml.body, 0); // !!! Без этой строки начало диапазона может захватывать какой то мусор
        Диапазон.setEnd(ТекущееВыделение.anchorNode, ТекущееВыделение.anchorOffset);
        ТекстВыделения = Диапазон.toString();
        Начало = СтрДлина(ТекстВыделения);
        Диапазон = ДокументHtml.createRange();
        Диапазон.setStart(ТекущееВыделение.anchorNode, ТекущееВыделение.anchorOffset);
        Диапазон.setEnd(ТекущееВыделение.focusNode, ТекущееВыделение.focusOffset);
        ТекстВыделения = Диапазон.toString();
        Конец = Начало + СтрДлина(ТекстВыделения);
17 Garykom
 
гуру
12.09.22
23:44
Бывает более интересна задача которая простым способом не решается.
Например получить слово под курсором мышки.

Суть в том что некоторые задачи без модификации HTML страниц никак.
В некоторых случаях требуется модификация браузера.
18 Garykom
 
гуру
12.09.22
23:46
(16) Лучше не использовать подобный извращенный код.
Не надо мешать французский с нижегородским.
Делай цельные функции на JS, вставляй их в страницу и вызывай.

В этом случае намного легче будет в будущем с переиспользованием кода.
19 Asmody
 
12.09.22
23:49
(18) я так понимаю, ему надо без модификации исходной страницы
20 Garykom
 
гуру
12.09.22
23:49
(18)+ И работать будет намного быстрее.
А то вот от этого

ТекстВыделения = Диапазон.toString();
Конец = Начало + СтрДлина(ТекстВыделения);

Плакать хочется. В JS есть Диапазон.toString().length
21 Garykom
 
гуру
12.09.22
23:49
(19) Эээ это же html! Там нет проблем с модификациями.
22 TormozIT
 
гуру
12.09.22
23:51
Проблему скорости выполнения я решил. Дальше ускорять в ущерб удобству сопровождения - мне не нужно.
А вот (14) было бы интересно решить.
23 Garykom
 
гуру
12.09.22
23:53
(22) Смотри.
Когда у тебя отдельные законченные функции на одном ЯП их может в будущем сопровождать один спец по одному этому ЯП.
А вот в случае подобного междукода любые доработки или исправления это мрак.
Особенно для новых прогов.

Ладно еще когда через COM в 1С извращаются, хотя это тоже не але но там хотя бы один ЯП!
24 TormozIT
 
гуру
12.09.22
23:55
(20) Мне нужна длина такая, как ее считает 1С. JS и 1С вполне могут заковыристые и непечатные символы считать по-разному. Поверить в обратное можно только проведя тщательное тестирование или набрав приличный опыт, которого у меня в JS нет.
Опять же не вижу смысла вносить лишнюю ненадежность в код.
25 Garykom
 
гуру
12.09.22
23:56
Это примерно как "Ъ" не взлетело от Serginio1
Где такая же хрень со смешением разных ЯП
Ибо намного проще на чистом C# писать, компилить и запускать/вызывать из 1С
26 Garykom
 
гуру
12.09.22
23:58
(24) У тебя код изначально ненадежен.
Ибо любые изменения в 1с или в браузере ie->webkit->... и с этим индусским кодом будет ахтунг
27 dmpl
 
13.09.22
08:08
(26) Со сторонними html в принципе ненадежно работать: на той стороне что-то поменяют - у тебя всё полетит.
28 Garykom
 
гуру
13.09.22
08:12
(27) Так и я о чем.
Но можно уменьшить проблемы если правильно делать отдельными JS-функциями.