2009-12-20 8 views
0

Je suis victime d'un kerfuffle Javascript qui va au-delà de ma connaissance de la langue.Portée variable du gestionnaire d'événements externes

Je crée un plugin personnalisé pour CKEditor. Le plugin est un IFrame qui s'ouvre dans un DIV généré par CKEditor.

A l'intérieur du IFrame, je suis l'affichage d'un certain nombre d'images. Si l'utilisateur sélectionne l'une de ces images, le code HTML nécessaire pour afficher cette image est inséré dans le CKEditor.

font c'est là Dynamiquement je suis coincé. Je me connecte à l'instance CKEditor à l'intérieur du Iframe comme ceci:

var CKEDITOR = window.parent.CKEDITOR;  

CKEditor offre un « auditeur OK » qui se déclenche lorsque le bouton OK (rendu par ckeditor) est cliqué. Cet écouteur OK est en dehors de l'IFrame.

Définition d'un auditeur OK qui fonctionne avec des valeurs statiques fonctionne:

var okListener = function(ev) { 
    this._.editor.insertHtml('<img class="symbol" src="my_static_symbol.gif">'); 
    CKEDITOR.dialog.getCurrent().removeListener("ok", okListener); 
}; 

// Assign OK listener 
CKEDITOR.dialog.getCurrent().on("ok", okListener); 

Mais je ne sais pas ma valeur de retour mais quand j'attribue l'auditeur OK, donc je besoin de faire quelque chose comme ceci:

var okListener = function(ev) { 
    this._.editor.insertHtml('<img class="symbol" src="'+my_dynamic_value()+'">'); 
    CKEDITOR.dialog.getCurrent().removeListener("ok", okListener); 
}; 

// Assign OK listener 
CKEDITOR.dialog.getCurrent().on("ok", okListener); 

Mais cela ne fonctionne pas parce que my_dynamic_value est en dehors de la portée de la fonction au moment où il est tiré par le bouton « OK » de CKEditor.

Je pourrais bien sûr, chaque fois que l'utilisateur sélectionne une image différente dans la liste, mettre à jour la fonction okListener et coder en dur la valeur actuelle en utilisant eval dedans. Mais cela ressemble à un horrible gaspillage de ressources pour moi.

Y a-t-il un truc de portée que je peux utiliser pour pouvoir accéder à des choses de mon Iframe depuis okListener()?

J'espère que cela est assez clair. Si ce n'est pas le cas, commentez et je vais clarifier.

+0

Bonjour Pekka, pouvez-vous donner accès à un échantillon? – Diadistis

+0

Malheureusement non, tout ce travail est exécuté localement et représenterait un énorme travail à télécharger (l'éditeur est intégré dans un gros CMS). Y a-t-il quelque chose que je puisse faire pour le rendre plus clair? –

+0

Est-ce que 'okListener' est défini dans l'iframe ou le parent? L'iframe est-il créé/visité une seule fois, ou chaque fois que l'utilisateur a besoin de sélectionner une image? – outis

Répondre

4

Mais cela ne fonctionne pas parce my_dynamic_value est en dehors du champ de la fonction au moment où elle est tirée par bouton « OK » de CKEditor.

OK. Peut-être que ça ne marche vraiment pas, mais l'explication est fausse. En JavaScript, les variables ont une portée lexicale. Cela signifie que si my_dynamic_value est dans la portée lorsque votre fonction (handler) est déclarée, alors elle reste là pour toujours. Quel message d'erreur obtenez-vous?

+0

Aaaaargh. Tu as raison. L'erreur que j'ai faite ne déclarait pas la variable * avant * j'ai déclaré la fonction, en pensant que cela n'a pas d'importance * quand * je le déclare aussi longtemps que cela arrive dans la même portée. Ça fonctionne maintenant. Merci. –

+0

Étrange. L'ordre n'a vraiment pas d'importance. Par exemple, cette sortie de code "5": (function() { setTimeout (function() { alerte (a); }, 2000); var a = 5; })(); – thorn

1

Vous pouvez écrire une fonction qui crée l'auditeur, en passant la valeur dynamique (en fonction ou une chaîne, selon la façon dont est écrit le reste du script).

function createOKListener(imgURLFunc) { 
    return function(ev) { 
     this._.editor.insertHtml('<img class="symbol" src="'+imgURLFunc()+'">'); 
     CKEDITOR.dialog.getCurrent().removeListener("ok", okListener); 
    }; 
}; 

// Assign OK listener 
CKEDITOR.dialog.getCurrent().on("ok", createOKListener(function() {iframeRef.path.to.imageURL})); 

Ou:

function createOKListener(imgURL) { 
    return function(ev) { 
     this._.editor.insertHtml('<img class="symbol" src="'+imgURL+'">'); 
     CKEDITOR.dialog.getCurrent().removeListener("ok", okListener); 
    }; 
}; 

// Assign OK listener 
CKEDITOR.dialog.getCurrent().on("ok", createOKListener(path.to.imageURL)); 

je soupçonne que ce qui se passe est que la fonction est en cours d'exécution dans le cadre de la fenêtre de niveau supérieur; que cela soit vrai ou non dépend de l'implémentation de l'événement CKEditor. Si tel est le cas, vous pouvez essayer d'accéder aux variables globales de l'iframe via la fenêtre iframe (comme indiqué dans la version imgURLFunc) ou de lier la valeur à une variable locale (comme avec createOKListener).

Qu'est-ce qui se passe est que les variables globales (autres que window) sont résolus en tant que propriétés de window (imaginez qu'il ya un with (window) {...} autour de blocs de code). Lorsque CKEditor déclenche un événement, il le fait dans le contexte de CKEDITOR, qui est window.parent (à partir de l'iframe).

+0

Salutations et merci pour votre temps. Il s'avère que c'était mon erreur. Voir mon commentaire à la réponse ci-dessus. –