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

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

De ma recherche j'ai trouvé ceci:

Chargement de l'iframe:

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

HTML dans iframe:

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

JQuery:

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

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

Quelque chose comme ça peut-il être fait?

35
demandé sur BigDataScientist 2012-11-18 14:28:58

9 réponses

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

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

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

        iframe.find("#choose_pics").click(function(){
               alert("test");
        });
});
51
répondu Philip G 2012-12-08 21:26:39

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

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

Soit cela, soit 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 aucun de ceux-ci ne fonctionne, essayez window.postMessage. Voici quelques informations à ce sujet .

6
répondu cpdt 2012-11-19 08:07:59

Je sais que c'est vieux, mais l'ID ne correspond pas à votre code est choose_pic et on est choose_pics:

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

$("#filecontainer").contents().find("#choose_pic").click(function(){
    //do something      
}); 
3
répondu KiwisTasteGood 2016-03-30 10:43:40

L'API tinymce prend en charge de nombreux événements dans les éditeurs iframe. Je vous 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
répondu Thariama 2012-11-19 09:30:12

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 iframe et 'take_payment' est le bouton dans iframe. Puisque mon formulaire à l'intérieur de l'iframe est posté dans un domaine différent, lorsqu'il est utilisé, j'ai reçu un message d'erreur disant:

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

1
répondu Abhijith 2015-08-20 13:54:13
$("#iframe-id").load( function() {
    $("#iframe-id").contents().on("click", ".child-node", function() {
        //do something
    });
});
1
répondu Akash gupta 2016-12-27 11:36:08

Dans mon cas, il y avait deux jquery , pour le HTML interne et externe. J'ai eu quatre étapes avant de pouvoir attacher des événements intérieurs:

  1. attendez que jQuery externe soit prêt
  2. attendez que iframe charge
  3. saisir jQuery intérieure
  4. attendez 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 interne:

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

J'ai dû sortir de jQuery dans le modèle objet pour il. L'approche $('iframe').contents() dans les autres réponses n'a pas fonctionné dans mon cas car cela reste avec la jQuery externe. (Et en passant retourne contentDocument.)

1
répondu Bob Stein 2017-06-02 17:25:26

Si quelqu'un est intéressé par une version "reproductible rapide" de la réponse acceptée, Voir ci-dessous. Crédits à un ami qui N'est pas si. Cette réponse peut également être intégrée dans la réponse acceptée avec une édition,... (Il doit fonctionner 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>
0
répondu BigDataScientist 2017-09-07 10:39:21

Dans mon cas, j'essayais de déclencher un événement personnalisé à partir du document parent, et de le recevoir dans l'iframe enfant, donc je devais faire ce qui 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
répondu stevelacerda7 2018-07-19 16:42:43