web-dev-qa-db-fra.com

Détecter l'événement de clic dans l'iframe

J'écris un plugin pour TinyMCE et j'ai un problème avec la détection d'événements de clics dans un iframe. 

De ma recherche, j'ai trouvé ceci:

Chargement d'iframe:

<iframe src='resource/file.php?mode=tinymce' id='filecontainer'></iframe>

HTML à l'intérieur d'iframe:

<input type=button id=choose_pics value='Choose'>

jQuery:

//Detect click
$("#filecontainer").contents().find("#choose_pic").click(function(){
    //do something      
}); 

Les autres articles que j'ai vus ont généralement un problème avec différents domaines (cela n'a pas été le cas). Mais, encore, l'événement n'est pas détecté. 

Peut-on faire quelque chose comme ça?

40
Philip G

Je l'ai résolu en faisant comme ceci:

$('#filecontainer').load(function(){

        var iframe = $('#filecontainer').contents();

        iframe.find("#choose_pics").click(function(){
               alert("test");
        });
});
54
Philip G

Je ne suis pas sûr, mais vous pourrez peut-être simplement utiliser

$("#filecontainer #choose_pic").click(function() {
    // do something here
});

Ou alors vous pouvez simplement ajouter une balise <script> dans l'iframe (si vous avez accès au code à l'intérieur), puis utiliser window.parent.DoSomething() dans le cadre, avec le code

function DoSomething() {
    // do something here
}

dans le parent . Si rien ne fonctionne, essayez window.postMessage. Voici quelques informations à ce sujet .

5
cpdt

Je sais que c'est vieux, mais votre identifiant ne correspond pas dans votre code, l'un est Choose_Pic et l'autre est Choose_pics :

<input type=button id=choose_pics value='Choose'>

$("#filecontainer").contents().find("#choose_pic").click(function(){
    //do something      
}); 
3
KiwisTasteGood

L'API tinymce prend en charge de nombreux événements dans les éditeurs iframe. Je suggère fortement de les utiliser. Voici un exemple pour le gestionnaire de clics

// Adds an observer to the onclick event using tinyMCE.init
tinyMCE.init({
   ...
   setup : function(ed) {
      ed.onClick.add(function(ed, e) {
           console.debug('Iframe clicked:' + e.target);
      });
   }
});
2
Thariama

Dans mon cas, il y avait deux jQuery's , pour le HTML interne et externe. J'ai eu quatre étapes avant que je puisse attacher des événements internes:

  1. attendre que jQuery externe soit prêt 
  2. attendez que iframe soit chargé 
  3. saisir jQuery intérieure
  4. attendre que jQuery interne soit prêt

$(function() {   // 1. wait for the outer jQuery to be ready, aka $(document).ready
    $('iframe#filecontainer').on('load', function() {   // 2. wait for the iframe to load
        var $inner$ = $(this)[0].contentWindow.$;   // 3. get hold of the inner jQuery
        $inner$(function() {   // 4. wait for the inner jQuery to be ready
            $inner$.on('click', function () {   // Now I can intercept inner events.
                // do something
            });
        });
    });
});

L'astuce consiste à utiliser le jQuery interne pour attacher des événements. Remarquez comment je reçois le jQuery intérieur:

        var $inner$ = $(this)[0].contentWindow.$;

J'ai dû sortir jQuery du modèle objet correspondant. L'approche $('iframe').contents() dans les autres réponses ne fonctionnait pas dans mon cas car cela restait avec le jQuery extérieur. (Et au fait, retourne contentDocument.)

1
Bob Stein

Juste poster au cas où cela aiderait quelqu'un. Pour moi, le code suivant a fonctionné parfaitement:

$(document).ready(function(){
     $("#payment_status_div").hide();
     var iframe = $('#FileFrame').contents();
     iframe.find("#take_payment").click(function(){
         $("#payment_status_div").show("slow");
     });
});

Où 'FileFrame' est l'id d'iframe et 'take_payment' est le bouton à l'intérieur d'iframe. Comme mon formulaire à l'intérieur de l'iframe est envoyé dans un domaine différent, lors de l'utilisation de load, j'ai reçu un message d'erreur disant:

Blocage d'un cadre avec Origin " https://www.example.com " pour accéder à un cadre avec Origin " https://secure-test.worldpay.com ". Les protocoles, les domaines et les ports doivent correspondre.

1
Abhijith
$("#iframe-id").load( function() {
    $("#iframe-id").contents().on("click", ".child-node", function() {
        //do something
    });
});
1
Akash gupta

Si quelqu'un est intéressé par une version "rapidement reproductible" de réponse acceptée , voir ci-dessous. Crédits à un ami qui n'est pas sur SO. Cette réponse peut également être intégrée à la réponse acceptée avec une édition, ... (Elle doit être exécutée sur un serveur (local)).

<html>
<head>
<title>SO</title>
<meta charset="utf-8"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>

<style type="text/css">
html,
body,
#filecontainer {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<iframe src="http://localhost/tmp/fileWithLink.html" id="filecontainer"></iframe>

<script type="text/javascript">
$('#filecontainer').load(function(){

  var iframe = $('#filecontainer').contents();

  iframe.find("a").click(function(){
    var test = $(this);
    alert(test.html());
  });
});
</script>
</body>
</html>

fileWithLink.html

<html>
<body>
<a href="https://stackoverflow.com/">SOreadytohelp</a>
</body>
</html>
1
BigDataScientist

Dans mon cas, j'essayais de déclencher un événement personnalisé à partir du document parent et de le recevoir dans l'iframe enfant. Je devais donc procéder comme suit:

var event = new CustomEvent('marker-metrics', {
    detail: // extra payload data here
});
var iframe = document.getElementsByTagName('iframe');
iframe[0].contentDocument.dispatchEvent(event)

et dans le document iframe:

document.addEventListener('marker-metrics', (e) => {
  console.log('@@@@@', e.detail);
});
0
stevenlacerda