2015-12-11 14 views
5

記事内の選択の開始と終了の文字オフセットを取得しようとしています。しかし、私はいくつかの要素をこのプロセスから無視したいと思います。選択できない要素以外の選択されたテキストを取得

私のアプリケーションでは、JSは動的にいくつかの要素を挿入する前にHTMLで作業しており、テキスト内の文字数がサーバーとクライアントの間で一貫していることが非常に重要です。

と一緒にuser-select: none;と同じくらい単純になることを期待しました。残念ながら、テキストは選択されていないように見えますが、選択範囲にはまだ含まれています。

私は以下の簡単な例を書いています。私は多くの成功なしで回避策としてremoveFromSelectionを書きました。たぶん、私は.unselectableをオーバーラップする範囲を削除し、手動で新しい範囲オブジェクトでギャップを埋める必要があります。これが私が作っているよりも簡単になるはずです。私はどのようにそれをやっていますか?

function findAncestorOffset(container, node, offset) 
 
{ 
 
\t if (node == container) 
 
\t \t return offset; 
 
\t var parent = node.parentNode; 
 
\t var syblings = parent.childNodes; 
 
\t for (var i = 0, len = syblings.length; i < len; i++) 
 
\t { 
 
\t \t if (syblings[i] == node) 
 
\t \t \t break; 
 
\t \t offset += $(syblings[i]).text().length; 
 
\t } 
 
\t return findAncestorOffset(container, parent, offset); 
 
} 
 

 
function removeFromSelection(selector, selection) 
 
{ 
 
\t $(selector).each(function(i, node){ 
 
\t \t var range = document.createRange(); 
 
\t \t range.selectNodeContents(node); 
 
\t \t selection.removeAllRanges(range); 
 
\t }); 
 
} 
 

 
var onSelect = function(){ 
 
    var sel = window.getSelection(); 
 
    //removeFromSelection('.unselectable', sel); 
 
    var text = sel.toString(); 
 
    $('#out').text(text); 
 
    var range = sel.getRangeAt(0).cloneRange(); 
 
    var i = findAncestorOffset($('.article')[0], range.startContainer, range.startOffset); 
 
    $('#from').text(i); 
 
    $('#to').text(i + text.length); 
 
} 
 
$('.article').mouseup(onSelect); 
 
$('.article').focusout(onSelect);
.unselectable { 
 
\t -webkit-touch-callout: none; 
 
\t -webkit-user-select: none; 
 
\t -khtml-user-select: none; 
 
\t -moz-user-select: none; 
 
\t -ms-user-select: none; 
 
\t user-select: none; 
 
} 
 

 
pre, .article { 
 
    border: solid 1px black; 
 
    padding: 12px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<h1>Select This</h1> 
 
<div class="article"> 
 
<p> 
 
    This can be selected. 
 
</p> 
 
<p class="unselectable"> 
 
    This can't. 
 
</p> 
 
<p> 
 
    And this can again. 
 
</p> 
 
</div> 
 

 
<h1>Output</h1> 
 
<div> 
 
    From: <span id="from"></span>, To: <span id="to"></span> 
 
</div> 
 
<pre id="out"> 
 
</pre>

+1

選択したHTMLを取得する必要がありますhttp://stackoverflow.com/questions/5222814/window-getselection-return-htmlその後、あなたはそれをフィルタリングでき、例えばます:http:/を/jsfiddle.net/xpca4fp5/しかし、これはバグかもしれないと思うので、これ以上のテストが必要です –

答えて

0

まあ、それは完全な解決策ではないのですが、それはスタートです。そのアイデアは各段落要素を繰り返し処理することで、unselectableの場合は選択範囲から削除します。私は、選択範囲を文字の配列に変換し、開始時にそれを埋め込んで、索引が文書全体の索引と一致するようにします。

最後のtofromの値には注意を払っていませんでしたが、おそらく正しいとは言えませんが、もっと重要なのは、テキスト全体を選択すると、2番目の選択不可能な文字ブロック。私はそれを試す時間がありませんが、他の人が私がどこを離れたかを知ることができます。

function findAncestorOffset(container, node, offset) 
 
{ 
 
\t if (node == container) 
 
\t \t return offset; 
 
\t var parent = node.parentNode; 
 
\t var syblings = parent.childNodes; 
 
\t for (var i = 0, len = syblings.length; i < len; i++) 
 
\t { 
 
\t \t if (syblings[i] == node) 
 
\t \t \t break; 
 
\t \t offset += $(syblings[i]).text().length; 
 
\t } 
 
\t return findAncestorOffset(container, parent, offset); 
 
} 
 

 
var onSelect = function(){ 
 
    var sel = window.getSelection(); 
 

 
    var textArray = sel.toString().split(''); 
 
    var range = sel.getRangeAt(0).cloneRange(); 
 
    var from = findAncestorOffset($('.article')[0], range.startContainer, range.startOffset); 
 
    var to = from + textArray.length; 
 
    textArray = (new Array(from)).concat(textArray); 
 
    
 
    var i = 0; 
 
    $('.article p').each((_, rawElement) => { 
 
    var element = $(rawElement); 
 
    var sectionStart = i; 
 
    var lengthOfSection = element.text().length; 
 
    if(element.hasClass('unselectable')) { 
 
     textArray.splice(sectionStart, lengthOfSection); 
 
    } else { 
 
     i += lengthOfSection; 
 
    } 
 
    }); 
 
    
 
    var text = textArray.join(''); 
 
    
 
    $('#from').text(from); 
 
    $('#to').text(to); 
 
    $('#out').text(text); 
 
} 
 
$('.article').mouseup(onSelect); 
 
$('.article').focusout(onSelect);
.unselectable { 
 
\t -webkit-touch-callout: none; 
 
\t -webkit-user-select: none; 
 
\t -khtml-user-select: none; 
 
\t -moz-user-select: none; 
 
\t -ms-user-select: none; 
 
\t user-select: none; 
 
} 
 

 
pre, .article { 
 
    border: solid 1px black; 
 
    padding: 12px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<h1>Select This</h1> 
 
<div class="article"> 
 
<p> 
 
    This can be selected. 
 
</p> 
 
<p class="unselectable"> 
 
    This can't. 
 
</p> 
 
<p> 
 
    And this can again. 
 
</p> 
 
<p> 
 
    This can be selected. 
 
</p> 
 
<p class="unselectable"> 
 
    This can't. 
 
</p> 
 
<p> 
 
    And this can again. 
 
</p> 
 
</div> 
 

 
<h1>Output</h1> 
 
<div> 
 
    From: <span id="from"></span>, To: <span id="to"></span> 
 
</div> 
 
<pre id="out"> 
 
</pre>

関連する問題