2012-04-10 3 views
2

Для тех, кто не работал с редактором Google Docs здесь краткое объяснение того, как это работает:Как измерить положение слова/каретки в Документах Google?

  • Google Docs не имеет видимых редактируемой или текстовое поле contentEditable элементов.
  • Документы Google прослушивают keydown/press/up в отдельном iFrame, где они размещают курсор OS для прослушивания событий.
  • Когда iFrame ловит событие, которое Google обрабатывает, выполняя эквивалентные операции над видимым документом.
  • «Карет» в Документах Google - это DIV, который оформлен и написан сценарием, чтобы выглядеть и действовать как курсор ОС.

С этим из пути, вот мой запрос:

Я работаю на плагин, который взаимодействует с Google Doc, и мне нужно, чтобы быть в состоянии сделать две вещи:

  • Выделите слова с непрозрачным наложением DIV.
  • Определить позицию курсора внутри слова.

Я исчерпываю много идей о том, как с этим справиться, но до сих пор мне удавалось получить только багги-решение для последней проблемы (я выполняю обратное пространство, определяю, где текст был изменен и отменить backspace).

Я ищу все лучшие идеи, которые вы можете решить, чтобы решить эти проблемы. Им не нужно быть перекрестным браузером, но они должны быть способны превратиться во что-то надежное, которое также будет обрабатывать такие вещи, как размер шрифта, измененный в середине строки.

Немного дополнительной информации, объясняющей, что выглядит Google Doc, как в HTML:

<wrapper> // Simplified wrapper containing margins, pagination and similar 
    <div class="kix-paragraphrenderer"> // single DIV per page wrapping all content 
    // Multiple paragraphs separated by linebreak created by Enter key: 
    <div class="kix-paragraphrendeder">...</div> 
    <div class="kix-paragraphrendeder">...</div> 
    <div class="kix-paragraphrendeder"> 
     // Multiple wrapper divs created by Google's word wrapping: 
     <div class="kix-lineview">...</div> 
     <div class="kix-lineview">...</div> 
     <div class="kix-lineview"> 
     // Single inner wrapper, still full width of first wrapper paragraph: 
     <div class="kix-lineview-content"> 
      // Single wrapper SPAN containing full text of the line, but not display:block 
      <span class="kix-lineview-text-block"> 
      // Multiple spans, one per new font change such as normal/bold text, 
       // change in font size, indentation and similar: 
      <span>This is normal text</span> 
      <span style="font-size:40px; padding-left:4px;">This larger text.</span> 
      <span style="font-weight:bold; padding-left:10px;">This is bold text</span> 
      <span style="padding-left:4px;">More normal text</span> 
      </span> 
     </div> 
     </div> 
    </div> 
    </div> 
</wrapper> 

ответ

3

После еще мастерить я пришел к выводу, что это крайне хлопотно - если не невозможно - чтобы попытаться программно определить курсора в отношении буквы внутри <span>, просто потому, что <span> является наименьшим элементом, который является измеримым (исправьте меня, если я ошибаюсь).

Как решить проблему? Вот то, что я в конечном итоге делает:

  • я создать закадровый позиционируется <div>
  • Я получаю текст текущего пункта (<div class="kix-paragraphrenderer">) - я мог бы получить весь текст, но хотел, чтобы ограничить вычислительную нагрузку.
  • извлечь каждый отдельный символ абзаца, обернув через своих детей следующим образом:
    • Петля через linveviews абзаца (<div class="kix-lineview">)
    • Получить содержание lineview (<div class="kix-lineview-content">)
    • Loop через текст блоки содержания lineview (<span class="kix-lineview-text-block">)
    • петля через <span> «с текстовым блоком
    • петли через innerText из <span>
    • прилагает каждый символ в моем закадровом <div>с приложенным текущим стилем извлеченного из style.cssText текущего <span>
    • Для каждого символа приложенных измерить ширину <div> и сохранить это в массиве. Теперь у меня есть позиция каждого отдельного персонажа.
  • Я измеряю положение курсора относительно моей ширины и вуаля - я знаю, где находится курсор в тексте.

Это, очевидно, немного упрощено (я оставлял детали о полях и прокладках разных элементов), но он охватывает идею о том, как можно получить позицию курсора.

Это работает очень хорошо, но есть много подводных камней и требуется много измерений. Кроме того, требуется также повторить анализ текста, если вы хотите использовать его для чего-либо, поскольку вкладки, пробелы и разрывы строк не всегда включаются в innerText (в зависимости от того, где они находятся в тексте, Google может или не может сделать их путем позиционирования новых элементов).

0

Я сделал что-то вроде Kix два года назад Google Docs. И для любого HTML-дизайна и да, для IE6 тоже :-) Как? Все, что нам нужно, это вычислить абсолютное положение буквы. Как? Замените textNode встроенным элементом без макета, это важно, а затем используйте Element.getClientRects. Я помню, что мне также понадобилось обернуть только букву и вычислить ее позицию через быстрый и надежный https://developer.mozilla.org/en-US/docs/Web/API/Element.getBoundingClientRect

Фокус на том, как обнаружить линии и обертки для дома и для конца ключи были основаны на изменении вертикальной эвристической позиции. Что-то вроде, если базовая линия отличается, чем остановка ходьбы. Это было довольно быстро и с любой разметкой и без кэширования. Святой Грааль :)

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

Этот проект мертв http://webeena.com сейчас. Плохое управление убило его (и меня почти тоже).

+0

Не уверен, что я следую тому, что вы подразумеваете под заменой 'textNode', но после моего ответа я обновил свой код, чтобы сделать что-то похожее на вас, что вы предлагаете. В отличие от изменения любого HTML, я создаю объект «Range» и манипулирую стартовым и конечным узлами, пока 'Range.getBoundingClientRect()' не сможет указать мне, где находится курсор, сравнивая с 'cursor.getBoundingClientRect()'. – Woodgnome