|   |   | 
| 
 | Тупой обход всех 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)+ И работать будет намного быстрее.
 А то вот от этого 
Плакать хочется. В 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-функциями. | 
 
 | Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |