開始位置と終了位置で示される特定のテキスト範囲を強調表示(cssを適用)したいと思います。テキスト内に無視する必要のある他のタグがある可能性があるため、これは見た目よりも困難です。
例:
<div>abcd<em>efg</em>hij</div>
highlight(2, 6)
"cdef
タグを削除せずに「」を強調表示する必要があります。
すでにTextRangeオブジェクトを使用しようとしましたが、成功しませんでした。
前もって感謝します!
開始位置と終了位置で示される特定のテキスト範囲を強調表示(cssを適用)したいと思います。テキスト内に無視する必要のある他のタグがある可能性があるため、これは見た目よりも困難です。
例:
<div>abcd<em>efg</em>hij</div>
highlight(2, 6)
"cdef
タグを削除せずに「」を強調表示する必要があります。
すでにTextRangeオブジェクトを使用しようとしましたが、成功しませんでした。
前もって感謝します!
以下は、特定の要素内の文字オフセットのペアに選択を設定する関数です。<script>
これは素朴な実装です: (CSS によって、または要素内にあることによって) 非表示にされる可能性のあるテキストは考慮されず、改行で<style>
ブラウザーの不一致 (IE とその他すべて) が発生する可能性があります。折りたたまれた空白の説明はありません (2 つ以上の連続するスペース文字がページ上の 1 つの表示スペースに折りたたまれるなど)。ただし、すべての主要なブラウザーの例では機能します。
他の部分であるハイライトについては、そのために使用することをお勧めしdocument.execCommand()
ます。以下の関数を使用して選択を設定し、 を呼び出すことができますdocument.execCommand()
。コマンドを機能させるには、IE 以外のブラウザでドキュメントを一時的に編集可能にする必要があります。コードについては、ここで私の回答を参照してください: getSelection & SurroundContents across multiple tags
すべての主要なブラウザーで動作する、すべてを示す jsFiddle の例を次に示します: http://jsfiddle.net/8mdX4/1211/
そして、選択設定コード:
function getTextNodesIn(node) {
var textNodes = [];
if (node.nodeType == 3) {
textNodes.push(node);
} else {
var children = node.childNodes;
for (var i = 0, len = children.length; i < len; ++i) {
textNodes.push.apply(textNodes, getTextNodesIn(children[i]));
}
}
return textNodes;
}
function setSelectionRange(el, start, end) {
if (document.createRange && window.getSelection) {
var range = document.createRange();
range.selectNodeContents(el);
var textNodes = getTextNodesIn(el);
var foundStart = false;
var charCount = 0, endCharCount;
for (var i = 0, textNode; textNode = textNodes[i++]; ) {
endCharCount = charCount + textNode.length;
if (!foundStart && start >= charCount
&& (start < endCharCount ||
(start == endCharCount && i <= textNodes.length))) {
range.setStart(textNode, start - charCount);
foundStart = true;
}
if (foundStart && end <= endCharCount) {
range.setEnd(textNode, end - charCount);
break;
}
charCount = endCharCount;
}
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (document.selection && document.body.createTextRange) {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(true);
textRange.moveEnd("character", end);
textRange.moveStart("character", start);
textRange.select();
}
}
複数の DOM 要素の選択をサポートするこの強力な JavaScript ユーティリティがどのように機能するかを確認できます。
MASHA (Mark & Share の略)を使用すると、Web ページのコンテンツの興味深い部分をマークして共有できます
http://mashajs.com/index_eng.html
GitHub にもありますhttps://github.com/SmartTeleMax/MaSha
Mobile Safari や IE でも動作します。
次のソリューションは IE では機能しません。そのためには TextRange オブジェクトなどを適用する必要があります。これは選択を使用してこれを実行するため、通常の場合、HTML を壊すことはありません。次に例を示します。
<div>abcd<span>efg</span>hij</div>
とhighlight(3,6);
出力:
<div>abc<em>d<span>ef</span></em><span>g</span>hij</div>
スパン外の最初の文字を にラップし、em
次に 内の残りの文字span
を新しいものにラップする方法に注意してください。文字 3 で開き、文字 6 で終了する場合、次のような無効なマークアップが表示されます。
<div>abc<em>d<span>ef</em>g</span>hij</div>
コード:
var r = document.createRange();
var s = window.getSelection()
r.selectNode($('div')[0]);
s.removeAllRanges();
s.addRange(r);
// not quite sure why firefox has problems with this
if ($.browser.webkit) {
s.modify("move", "backward", "documentboundary");
}
function highlight(start,end){
for(var st=0;st<start;st++){
s.modify("move", "forward", "character");
}
for(var st=0;st<(end-start);st++){
s.modify("extend", "forward", "character");
}
}
highlight(2,6);
var ra = s.getRangeAt(0);
var newNode = document.createElement("em");
newNode.appendChild(ra.extractContents());
ra.insertNode(newNode);
例: http://jsfiddle.net/niklasvh/4NDb9/
編集少なくとも私のFF4にはいくつかの問題があったようです
s.modify("move", "backward", "documentboundary");
同時に、それがなくても機能するように見えるので、変更しました
if ($.browser.webkit) {
s.modify("move", "backward", "documentboundary");
}
edit Tim が指摘したように、modify は FF4 以降でのみ利用可能です。そのため、ブラウザーとの互換性をもう少し高めることを期待して、modify メソッドを必要としない選択を取得する別のアプローチを取りました (IE にはまだ独自の解決)。
コード:
var r = document.createRange();
var s = window.getSelection()
var pos = 0;
function dig(el){
$(el).contents().each(function(i,e){
if (e.nodeType==1){
// not a textnode
dig(e);
}else{
if (pos<start){
if (pos+e.length>=start){
range.setStart(e, start-pos);
}
}
if (pos<end){
if (pos+e.length>=end){
range.setEnd(e, end-pos);
}
}
pos = pos+e.length;
}
});
}
var start,end, range;
function highlight(element,st,en){
range = document.createRange();
start = st;
end = en;
dig(element);
s.addRange(range);
}
highlight($('div'),3,6);
var ra = s.getRangeAt(0);
var newNode = document.createElement("em");
newNode.appendChild(ra.extractContents());
ra.insertNode(newNode);