2012-08-01 74 views
2

我可以設置一個事件監聽器來告訴我什麼時候在HTML文檔中的某處發生了鼠標點擊。但是如果點擊發生在某些文本上,我需要知道文本中的哪個字符發生了點擊。有沒有辦法做到這一點?如何確定被點擊的textnode中的字符?

我可以想到一些真正討厭的解決方案。例如,對於文檔中的每個字符,我都可以將它用自己的事件包裝在一個單獨的元素中。或者,因爲我可以知道點擊發生在哪個文本節點上,所以我可以執行某種計算(基本上類似於模擬文本的渲染),可能使用clientWidth來確定點擊發生在哪個字符中。

當然必須是更容易?

+0

檢查的位置插入符http://blog.vishalon.net/index.php/javascript-getting-and-setting-caret-position-in-textarea/ – 2012-08-01 03:49:59

+1

這不是一個textarea – Michael 2012-08-01 03:53:39

+1

*您應該*能夠爲每個字符創建一個文本節點,然後讓相關事件引用該節點。但是,我所知道的只有一個瀏覽器實現了該模型,現在它符合只允許元素成爲事件目標的更普遍模型。 – RobG 2012-08-01 04:17:37

回答

7

,拆分元素中的文本轉換成兩個獨立的跨越。看看每個跨度的偏移量,以確定事件發生的。現在拆分跨度兩年再進行比較。重複,直到你有一個單一的字符,其座標包含鼠標點擊的座標跨度。由於這實質上是一個二進制搜索這整個過程會相當快,和跨度的總數相比低替代。一旦找到角色,跨度可以被解散,所有文本都會返回到原始元素。

2

你做什麼,不幸的是,有包裝的每一個字符中的一個元素,但你不必事件偵聽器附加到每個之一。當元素觸發click事件時,它會冒泡給其父母。然後,您可以檢索實際使用情況的target財產點擊的元素。

說,我們已經得到了在一個名爲textElement元素一些文字。它包含每個角色的span。如果我們希望能夠點擊字符刪除它們,我們可以使用此代碼:一旦鼠標事件被捕獲

textElement.addEventListener('click', function(e) { 
    textElement.removeChild(e.target); 
}, false); 

Try it out.

+0

嗯,好吧。我想我的這種方法主要關注的是記憶,我想這是要採取原始文件大小的某一倍數來包裝每一個字符在一個單獨的文本元素,也許10倍? 20倍?並且可能這可能會導致性能問題,儘管這可能不太可能。 – Michael 2012-08-01 04:08:25

+0

這些都是有效的擔憂。不幸的是,我不知道這種方法對這些方法有什麼影響。 – icktoofay 2012-08-01 04:09:51

+0

的在Firefox 14 10,000個字符快速測試顯示約50萬的初始頁面內存增加,另一3.5MB包裹在跨度的一切,與約2秒鐘做包裝。新運行的副本爲每個字符顯示大約170字節的RAM。 – Michael 2012-08-01 04:26:12

0

將每個字符放在文檔模型對象中並不像它聽起來那樣討厭。 HTML解析,DOM表示,和事件處理是在現代瀏覽器的內存和處理方面非常有效。類似的機制也用於低級別來渲染角色。模擬瀏覽器在該級別上所做的工作需要很多工作。

  • 大多數文件構造有可變寬度的字符
  • 包裝可以是合理的或以多種方式排列
  • 沒有字符之間的一對一的映射和字節
  • 要成爲一個真正的國際化和強大的解決方案,替代對必須得

這個例子是輕量級的快速支持,負載,並且是端口能夠跨越常見的瀏覽器。它的優雅並不一目瞭然,通過建立國際角色和事件聽衆之間的一對一對應關係,獲得了很多可靠性。

<!DOCTYPE html> 
    <html lang="en"> 
    <head> 
     <meta charset="utf-8"> 
     <title>Character Click Demo</title> 
     <script type='text/javascript'> 
      var pre = "<div onclick='charClick(this, "; 
      var inf = ")'>"; 
      var suf = "</div>"; 
      function charClick(el, i) { 
       var p = el.parentNode.id; 
       var s = "para '" + p + "' idx " + i + " click"; 
       ele = document.getElementById('result'); 
       ele.innerHTML = s; } 
      function initCharClick(ids) { 
       var el; var from; var length; var to; var cc; 
       var idArray = ids.split(" "); 
       var idQty = idArray.length; 
       for (var j = 0; j < idQty; ++ j) { 
        el = document.getElementById(idArray[j]); 
        from = unescape(el.innerHTML); 
        length = from.length; 
        to = ""; 
        for (var i = 0; i < length; ++ i) { 
         cc = from.charAt(i); 
         to = to + pre + i + inf + cc + suf; } 
        el.innerHTML = to; } } 
     </script> 
     <style> 
      .characters div { 
       padding: 0; 
       margin: 0; 
       display: inline } 
     </style> 
    </head> 
    <body class='characters' onload='initCharClick("h1 p0 p2")'> 
     <h1 id='h1'>Character Click Demo</h1> 
     <p id='p0'>&#xE6;&#x20AC; &ndash; &#xFD7;&#xD8; &mdash;</p> 
     <p id='p1'>Next E para.</p> 
     <p id='p2'>&copy; 2017</p> 
     <hr> 
     <p id='result'>&nbsp;</p> 
    </body> 
    </html> 

[1]這個簡單的例子不具有用於處理代理對,但這樣可能會在i循環體被加入。

相關問題