2

对于那些没有使用过 Google Docs 编辑器的人,这里简要解释一下它的工作原理:

  • Google Docs 没有可见的可编辑 textarea 或 contentEditable 元素。
  • Google Docs 在单独的 iFrame 中侦听 keydown/press/up,它们将 OS 光标放置在其中以进行事件侦听。
  • 当 iFrame 捕获事件时,Google 通过对可见文档执行等效操作来处理它。
  • Google Docs 中的“插入符号”是一个 DIV,其样式和脚本看起来和行为都像 OS 光标。

顺便说一句,这是我的要求:

我正在开发一个与 Google Doc 交互的插件,我需要能够做两件事:

  • 使用不透明的叠加 DIV 突出显示单词。
  • 确定单词内的光标位置。

关于如何处理这个问题,我已经用尽了很多想法,但到目前为止,我只设法为后一个问题找到了一个错误的解决方案(我执行退格,确定文本更改的位置并撤消退格)。

我正在寻找你能想出的所有最好的想法来解决这些问题。它们不需要是跨浏览器,但它们确实需要能够变成强大的东西,也可以处理诸如字体大小更改中线之类的事情。

一些额外的信息解释了 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>
4

2 回答 2

4

经过更多的修补后,我得出的结论是,尝试以编程方式确定光标位置相对于 a 中的字母是非常麻烦的(如果不是不可能的话)<span>,仅仅是因为<span>是可测量的最小元素(如果我错了,请纠正我)。

那么如何解决问题呢?这就是我最终做的事情:

  • 我创建了一个屏幕外定位<div>
  • 我得到了当前段落的文本 ( <div class="kix-paragraphrenderer">) - 我可以得到整个文本,但想限制计算负载。
  • 我通过以下方式循环遍历其子级来提取段落的每个单个字符:
    • 循环遍历段落的 linveviews ( <div class="kix-lineview">)
    • 获取 lineview 内容 ( <div class="kix-lineview-content">)
    • 循环浏览 lineview 内容的文本块 ( <span class="kix-lineview-text-block">)
    • 循环遍历<span>文本块
    • 循环 innerText通过<span>
    • 我在屏幕外<div> 添加了从当前应用中提取的当前应用样式的style.cssText每个字符<span>
    • 对于附加的每个字符,我测量它的宽度<div>并将其保存在一个数组中。我现在有每个角色的位置。
  • 我测量光标相对于我的宽度的位置,瞧——我知道光标在文本中的位置。

这显然有点简单(我省略了有关不同元素的边距和填充的细节),但它涵盖了如何获得光标位置的想法。

它工作得很好,但有很多陷阱和需要大量的测量。最重要的是,如果您想将其用于任何内容,还需要对文本进行后解析,因为制表符、空格和换行符并不总是包含在innerText其中(取决于这些在文本中的位置,Google 可能会或可能不会他们通过新元素的定位)。

于 2012-05-18T08:23:57.197 回答
0

两年前我制作了类似 Kix 的 Google Docs。对于任何 HTML 设计,是的,也适用于 IE6 :-) 怎么样?我们只需要计算字母的绝对位置。如何?用没有布局的内联元素替换 textNode,这很重要,然后使用 Element.getClientRects 我记得我还需要只包装字母并通过快速可靠的https://developer.mozilla.org/en-US/docs/Web计算其位置/API/Element.getBoundingClientRect

如何检测 home 键和 end 键的行和换行的技巧是基于一些垂直的启发式字母位置变化。就像基线不同,而不是停止插入符号行走。它非常快,有任何标记,没有任何缓存。圣杯:)

唯一无法解决的问题是合理的文本,因为字母是随机分布的,它们之间的空格是不可计算的。

那个项目现在已经死了http://webeena.com。糟糕的管理杀死了它(我几乎也是)。

于 2014-01-29T23:56:42.580 回答