如果文本可能位于 HTML 文档的某个框架(或 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 时。框架有自己的文档,因此仅使用上面的代码是不够的。人们可能会迭代框架树并在其中之一中搜索选定的文本,但是一般来说框架可以包含来自不同域的内容,因此即使我要迭代搜索中根文档的所有框架和所有子框架等所选文本的我将无权访问其 HTML,对吧?所以我无法获得他们选择的文本。

即使页面包含框架,是否有一种(简单)可靠的方法可以在网页上查找所选文本?

谢谢

有帮助吗?

解决方案

经过更多调查后回答我自己的问题:因此,如果框架属于不同的域,那么您无能为力,因为您没有访问它们的 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 == '') && 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();
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top