2012-04-10 51 views
2

對於那些誰沒有與谷歌文檔編輯器,在這裏工作是它如何工作的一個簡短的解釋:如何在Google文檔中衡量單詞/插入符的位置?

  • 谷歌文檔是不可見的可編輯的文本區域或CONTENTEDITABLE元素。
  • 谷歌文檔在單獨的iFrame中監聽keydown/press/up,在這裏他們放置OS光標以進行事件監聽。
  • 當iFrame通過對可見文檔執行等效操作來捕獲Google處理它的事件時。
  • Google Docs中的「caret」是一個DIV,它的樣式和腳本可以像OS遊標一樣進行查看和操作。

有了這樣的方式,這是我的要求:

我的工作是與谷歌文檔進行交互的插件,我需要能夠做兩件事情:

  • 用不透明疊加DIV突出顯示單詞。
  • 確定單詞內的光標位置。

我已經用盡了很多關於只是如何處理這種想法,但到目前爲止,我只弄到後面的問題(我執行回退一車解決方案,確定在文本改變並撤消退格)。

我正在尋找所有可以提出來解決這些問題的最佳創意。他們不需要跨瀏覽器,但他們確實需要能夠變成強大的東西,以處理諸如字體大小改變中線等事情。

的額外的信息解釋谷歌文檔看起來像在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">
    • 循環:
    • 我通過其子以下列方式循環提取款的每一個字符所述lineview含量(<span class="kix-lineview-text-block">
    • 環路的塊通過<span>的文本塊
    • 循環通過的
    • 我追加的每個字符在我的屏幕外<div>與從當前<span>
    • style.cssText提取對於每個字符所附我測量<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 2014-01-30 16:11:29

相關問題