Как найти выделение в документе HTML, который содержит iframe или просто фреймы - PullRequest
4 голосов
/ 30 апреля 2009

Есть ли способ найти выделенный текст в документе 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

Так что это работает кросс-браузер (хотя и не очень красиво).

Проблема в том, что документ содержит фреймы или фреймы. У фреймов есть собственный документ, поэтому простого использования приведенного выше кода недостаточно. Можно потенциально перебирать дерево фреймов и искать выбранный текст в одном из них, однако в общем случае фреймы могут содержать контент из разных доменов, поэтому даже если бы мне пришлось перебирать все фреймы и все подкадры и т. Д. Корневого документа в поиске выбранного текста у меня не было бы права доступа к их HTML, верно? Поэтому я не смогу получить их выбранный текст.

Существует ли (простой) надежный способ поиска выделенного текста на веб-странице, даже если страница содержит фреймы?

Спасибо

Ответы [ 2 ]

3 голосов
/ 07 мая 2009

Чтобы ответить на мой собственный вопрос, после еще большего расследования: Таким образом, если фреймы принадлежат разным доменам, вы ничего не можете с этим поделать, так как у вас нет прав доступа к их доменам. Однако в общем случае, когда все фреймы находятся в одном домене (например, 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);
})()
0 голосов
/ 11 апреля 2012

@ Ран Отличный ответ на свой вопрос. Однако, если документ 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();
}
...