2017-03-11 15 views
7

クライアントブラウザでWebソケットを使用してRange()オブジェクトを再構築しようとしています。ノード、startOffsetおよびendOffsetで範囲を再構築する

var range = window.getSelection().getRangeAt(0); 
var node = range.startContainer 

私は、クライアント上の範囲ビルダー機能にWebSocketを介して3つのパラメータを渡しています:

https://jsfiddle.net/k36goyec/

まず私は私のブラウザでRangeオブジェクトと範囲がで始まりNodeを取得していますブラウザ。

var text  = node.parentNode.textContent; 
var startOffset = range.startOffset 
var endOffset = range.endOffset 

このデータは私のbuildRange関数に渡されます:あなたは以下を参照することができたよう

/** 
* 
*/ 
buildRange: function(text, startOffset, endOffset){ 
    var node = this.getNodeByText(text); // get the Node by its contents 

    var range = document.createRange(); 
    range.setStart(node, startOffset); 
    range.setEnd(node, endOffset); 

    span = document.createElement('span'); 
    span.style.backgroundColor = this.color; 
    $(span).addClass('hl'); 
    range.surroundContents(span); 
}, 

、私は、ページ上のすべての要素をループしてそのを比較することにより、クライアントブラウザ上のノードを取得していますテキストのコンテンツ:

/** 
* 
*/ 
getNodeByText: function(text){ 
    var all = document.getElementsByTagName("*"); 
    for (var i = 0; i < all.length; i++) { 
     if (all[i].textContent === text) { 
      return all[i]; 
     } 

    } 
}, 

私はsetStart()とsetEnd()を使用して、ノードでの選択範囲を設定しています。

問題があります。

range.startOffset/endOffsetスペックは以下の言葉:

If the startNode is a Node of type Text, Comment, or CDATASection, then startOffset is the number of characters from the start of startNode. For other Node types, startOffset is the number of child nodes between the start of the startNode.

私は、テキストの範囲を選択すると、私は次のエラーを取得する:

IndexSizeError: Index or size is negative or greater than the allowed amount 

私のようなのオフセットを渡していますので、これは、 0,10(10文字選択)がノードはテキストノードではない要素ノードです。私は確実にテキストノードを取得するように見えることはできません

が、私は唯一の要素ノード自体を取得することができ

...

Q:私は確実にノードと範囲を再構築するにはどうすればよい

とオフセット?

+0

あなたは要素を返すgetElementsByTagNameを使用しています。 https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodesとhttps://developer.mozilla.org/en/docs/Web/API/を見てみることをお勧めしますノード/ノードタイプ – Orangesandlemons

答えて

2

あなたが直面している直面している問題は、範囲データを保存するとテキストノードにオフセットが発生することですが、範囲を再作成しようとすると、オフセットとしてインデックスを使用する要素が見つかり、クラッシュします。これを修正すると、すぐに問題が解決されます。

しかし、あなたの全体的なアプローチは脆弱です。

はこれでドキュメントを考えてみましょう:

<p>Farmer John has a thousand <b>goats</b></p> 
<p>and his <b>goats</b> ate all his oats.</p> 

いくつかの問題を、私の頭の上から:あなたが第二「ヤギ」を選択した場合

  1. は、あなたのアルゴリズムは、範囲を再作成します元の範囲と同じテキストを持つ要素のみを検索するため、最初の「ヤギ」では

  2. あなたが開始する範囲を選択した場合「と」2行目で、あなたの起源の範囲から取得するオフセットは二つの異なるテキストノードにインデックス化され、「食べた」で終わる:1つのテキストノードテキストand hisとテキストate all his oats.を含む2番目のテキストノードが含まれています。アルゴリズムでは、宛先で回復するメモが1つのみであることが前提です。複数あるかもしれません。

    太字の単語の1つで始まり外側で終了する選択肢がある場合、同じ問題が発生します。

堅牢なものを持って、あなたは先の正確な直列化復元を確保するのに十分な情報を記録原点に範囲の直列化を実行する必要があります。

これにはさまざまな方法があります。 1つの方法は、元と宛先に同じDOM構造が存在することを保証し、Rangyライブラリのserialization moduleを使用してシリアライズとデシリアライズを実行することです。両方のDOM構造を同じにすることができれば、これは私が使用するものです。

両端で同じDOM構造を確保できない場合は、独自のロールを作成する必要があります。両端で同じ基準点を特定し、参照点を基準にした範囲の開始ノード/オフセットと終了ノード/オフセットを特定する必要があります。

1

この問題に対処する:

I just can't seem to reliably get the text node, I can only get the element node itself...

を実際のテキストノードを取得するには、要素の.childnodesプロパティを使用することができます。複数のノードがある場合は、nodeTypeをテストして、どれがテキストノードであるかを調べることができます。 テキストノードの内容を調べるには、nodeValueプロパティをチェックしてください。

関連する問題