Как работать с вложенными элементами body и selection в скрипте Google Apps

При работе с телом или выделением документа Google может быть трудно понять, как перемещаться по элементам для изменения текста определенным образом, не нарушая форматирования. Эта статья описывает процесс шаг за шагом, чтобы помочь вам понять, как работать с этими вложенными элементами.

Когда у вас есть Selection, .getRangeElements() возвращает массив RangeElements. Элемент диапазона — это объект-оболочка, который помогает нам работать с частичным выбором. Мы можем вызвать .getElement() для каждого элемента в этом массиве, чтобы получить объект элемента, который является очень общим объектом, который может представлять практически любую часть тела документа Google. Элементы имеют метод .getType(), который возвращает перечисление ElementType, и их много! Документ Google, который я использовал, выглядит следующим образом:

Давайте воспользуемся тем, что мы уже знаем, чтобы создать сценарий, чтобы увидеть, какие возможные типы есть в Google Doc.

Ах-ха! Похоже, нам нужно иметь дело только с типами элементов PARAGRAPH, LIST_ITEM и TABLE пока, но давайте сохраним их потомки в виду тоже (Узнаем, что эти 3 из 5 с детьми). Это похоже на работу рекурсивной функции, которая будет постоянно копаться в дочерних элементах, пока мы не найдем решение для них всех.

Давайте попробуем это сделать. Следующая часть может показаться запутанной, но, по сути, это поиск элемента, проверка наличия у него дочерних элементов, а затем проверка этих элементов на наличие у них дочерних элементов, и так далее. Мы также хотим проверить, есть ли у нас новые типы элементов для работы…

Итак, каждая строка журнала — это цепочка Элементов и их дочерних элементов. У нас есть несколько новых типов элементов (HORIZONTAL_RULE, TABLE_ROW и TEXT). Если цепочка представляет собой только PARAGRAPH и не имеет дочерних элементов, мы можем игнорировать ее, так как это пустая строка. Мы также можем игнорировать HORIZONTAL_RULE, так как это очевидно не будет содержать текста.

Если мы добрались до элемента TEXT, это означает, что мы можем выполнять свою функцию так же, как мы сделали с LIST_ITEM и PARAGRAPH. Однако нам по-прежнему приходится иметь дело с Объектами TableRow (которые регистрируются следующим образом: TABLE.TABLE_ROW). Этот тип объекта похож на наши основные 3 элемента и может использоваться с нашим if(elemType == “TABLE” || elemType == “LIST_ITEM” || elemType == “PARAGRAPH”), который меняется на if(elemType == “TABLE” || elemType == “LIST_ITEM” || elemType == “PARAGRAPH” || elemType == “TABLE_ROW”).

Это дает нам еще один новый элемент в нашей цепочке; TableCell (записывается как: TABLE.TABLE_ROW.TABLE_CELL), который мы можем снова добавить в наш оператор if, сделав его: if(elemType == “TABLE” || elemType == “LIST_ITEM” || elemType == “PARAGRAPH” || elemType == “TABLE_ROW” || elemType == “TABLE_CELL”)

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

Это здорово! Мы проникли в глубины каждого родительского элемента и достигли либо Текстового элемента, либо пустого абзаца! Отсюда мы можем немного изменить наш код, чтобы добавить функции, которые мы хотим выполнять, сохраняя при этом структуру документа:

БУМ! Готово. Я знаю, что это очень длинный пост, но я разбил каждый раздел решения на части, чтобы помочь новым кодировщикам сценариев приложений понять структуру выделения (и тела документа, я полагаю) и то, как изменить его, когда структура очень сложная (много вложенных элементов). Я очень надеюсь, что это было полезно. Если кто-нибудь увидит часть, которую можно улучшить, дайте мне знать.

— — — — —

Примечание. Имейте в виду, что это не обязательно связано с частичным выбором элемента, но с этим можно легко справиться, немного изменив первую функцию, чтобы проверить наличие isPartial() в RangeElement.