iframeまたはフレームのみを含むHTMLドキュメントで選択範囲を見つける方法
-
03-07-2019 - |
質問
テキストがそのフレーム(またはiframe)のいずれかにある可能性がある場合、HTMLドキュメントで選択したテキストを見つける方法はありますか?
ドキュメントにフレームがない場合は簡単です:
var text;
if (document.getSelection) {
// Firefox and friends
text = document.getSelection();
} else if (document.selection) {
// IE
text = document.selection.createRange();
}
if (text == undefined || text == '') {
// Iterate over all textarea elements and see if one of them has selection
var areas = document.getElementsByTagName('textarea');
for(var i = 0; i = areas.length; i++) {
if(areas[i].selectionStart != undefined &&
areas[i].selectionStart != areas[i].selectionEnd){
text = areas[i].value.substring(areas[i].selectionStart, a[i].selectionEnd);
break;
}
}
}
// Now if document has selected text, it's in text
したがって、これはクロスブラウザで動作します(あまりきれいではありません)。
問題は、ドキュメントにフレームまたはiframeが含まれている場合です。 フレームには独自のドキュメントがあるため、上記のコードを使用するだけでは十分ではありません。 フレームツリーを反復処理し、そのうちの1つで選択したテキストを検索することもできますが、一般的にフレームは異なるドメインのコンテンツを持つことができるので、検索中のルートドキュメントのすべてのフレームとすべてのサブフレームなどを反復する場合でも選択したテキストのうち、HTMLにアクセスする権限がなかったでしょうか?そのため、選択したテキストを取得できません。
ページにフレームが含まれている場合でも、Webページで選択されたテキストを見つける(簡単な)信頼できる方法はありますか?
ありがとう
解決
もう少し調査した後、自分の質問に答えるには: したがって、フレームのドメインが異なる場合、domにアクセスする権限がないため、それに対してできることは何もありません。ただし、すべてのフレームが同じドメイン(例:gmail)にある一般的なケースでは、テーマをすべてツリーのように繰り返します。これを実現するコードは次のとおりです。
以下のコードは、選択したテキストの文字と単語をカウントするブックマークレット用です:
javascript:(function(){
// Function: finds selected text on document d.
// @return the selected text or null
function f(d){
var t;
if (d.getSelection) t = d.getSelection();
else if(d.selection) t = d.selection.createRange();
if (t.text != undefined) t = t.text;
if (!t || t=='') {
var a = d.getElementsByTagName('textarea');
for (var i = 0; i < a.length; ++i) {
if (a[i].selectionStart != undefined && a[i].selectionStart != a[i].selectionEnd) {
t = a[i].value.substring(a[i].selectionStart, a[i].selectionEnd);
break;
}
}
}
return t;
};
// Function: finds selected text in document d and frames and subframes of d
// @return the selected text or null
function g(d){
var t;
try{t = f(d);}catch(e){};
if (!t || t == '') {
var fs = d.getElementsByTagName('frame');
for (var i = 0; i < fs.length; ++i){
t = g(fs[i].contentDocument);
if(t && t.toString() != '') break;
}
if (!t || t.toString() == '') {
fs = d.getElementsByTagName('iframe');
for (var i = 0; i < fs.length; ++i){
t = g(fs[i].contentDocument);
if(t && t.toString() != '') break;
}
}
}
return t;
};
var t= g(document);
if (!t || t == '') alert('please select some text');
else alert('Chars: '+t.toString().length+'\nWords: '+t.toString().match(/(\S+)/g).length);
})()
他のヒント
@Ranあなた自身の質問に対する優れた答え。ただし、iframeドキュメントが未定義の場合、関数は失敗します。これをチェックする条件を追加しました。Gmailを含めて試したすべてのサイトで機能するようになりました。 if((!t || t == '')&amp;&amp; d)
すばらしいコードをありがとう。
var getSelectedText = function(){
// Function: finds selected text on document d.
// @return the selected text or null
function f(d){
var t;
if (d.getSelection) t = d.getSelection();
else if(d.selection) t = d.selection.createRange();
if (t.text != undefined) t = t.text;
if (!t || t=='') {
var a = d.getElementsByTagName('textarea');
for (var i = 0; i < a.length; ++i) {
if (a[i].selectionStart != undefined && a[i].selectionStart != a[i].selectionEnd) {
t = a[i].value.substring(a[i].selectionStart, a[i].selectionEnd);
break;
}
}
}
return t;
};
// Function: finds selected text in document d and frames and subframes of d
// @return the selected text or null
function g(d){
var t;
try{t = f(d);}catch(e){console.log('ERROR: ',e);};
if ((!t || t == '') && d){
var fs = d.getElementsByTagName('frame');
for (var i = 0; i < fs.length; ++i){
t = g(fs[i].contentDocument);
if(t && t.toString() != '') break;
}
if (!t || t.toString() == '') {
fs = d.getElementsByTagName('iframe');
for (var i = 0; i < fs.length; ++i){
t = g(fs[i].contentDocument);
if(t && t.toString() != '') break;
}
}
}
return t;
};
var t= g(document);
if (!t || t == '') ;
else return t.toString();
}