Comment trouver une sélection dans un document HTML contenant iframe ou seulement des cadres

StackOverflow https://stackoverflow.com/questions/808744

  •  03-07-2019
  •  | 
  •  

Question

Existe-t-il un moyen de rechercher le texte sélectionné dans un document HTML si celui-ci se trouve dans l'un de ses cadres (ou iframes)?

Si le document n'a pas de cadre, c'est simple:

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

Cela fonctionne donc sur plusieurs navigateurs (bien que pas très joli).

Le problème se pose lorsque le document contient des cadres ou des iframes. Les cadres ont leur propre document, il ne suffit donc pas d'utiliser le code ci-dessus. On peut potentiellement parcourir l’arborescence des cadres et rechercher le texte sélectionné dans l’un d’eux. Toutefois, en général, les cadres peuvent avoir un contenu de différents domaines. Même si je devais itérer sur tous les cadres et toutes les sous-images, etc., du document racine dans la recherche du texte sélectionné, je n'aurais pas eu la permission d'accéder à leur code HTML, non? Je ne pourrais donc pas obtenir le texte sélectionné.

Existe-t-il un moyen (simple) fiable de rechercher le texte sélectionné sur une page Web, même si la page contient des cadres?

Merci

Était-ce utile?

La solution

Pour répondre à ma propre question, après un peu plus d'investigation: Donc, si les cadres sont de domaines différents, vous ne pouvez rien y faire car vous n’avez pas la permission d’accéder à leur domaine. Toutefois, dans le cas habituel où tous les cadres se trouvent sur le même domaine (par exemple, gmail), il vous suffit d’itérer le thème comme un arbre. Voici le code qui accomplit cela:

Le code ci-dessous concerne un bookmarklet qui compte les caractères et les mots du texte sélectionné:

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);
})()

Autres conseils

@Ran Excellente réponse à votre propre question. Cependant, si le document iframe n'est pas défini, la fonction échoue. J'ai ajouté une condition pour vérifier cela, maintenant cela fonctionne sur tous les sites que j'ai essayés, y compris Gmail. if ((! t || t == '') & amp; & amp; d) Merci encore pour l'excellent code.

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();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top