2009-09-23 12 views
2

Dans ce code, Firefox voit 'ceci' comme l'élément qui a été cliqué et transmet l'attribut href de la bonne façon.La compréhension d'IE de 'ceci'

IE semble penser que 'ceci' comme [fenêtre d'objet] à la place. Comment est-ce que je ferais fonctionner ceci de la même manière dans les deux navigateurs?

Note: jQuery serait belle, mais pas une option pour ce projet

var printElem = getElementsByClassName('print', 'a'); 
for(i in printElem){ 
    ObserveEvent(printElem[i], 'click', function(e){ 
     window.open(this.href, '', 'location=0,menubar=1,resizable=1,scrollbars=1,width='+810+',height='+700); 
     cancelEvent(e); 
    }); 
} 
+0

Ce vit code dans un gestionnaire d'événements? – n8wrl

+1

Quelle est votre fonction 'ObserveEvent'? –

+0

Si oui, il doit être <1,6. Dans Prototype, à partir de la version 1.6, Prototype s'assure que l'élément que vous avez regardé correspond à ce que 'this' référence (qui peut être différent de celui sur lequel l'événement s'est déclenché, car la plupart des événements sont très intéressants). –

Répondre

3

J'ajoute mes deux cents ici car je pense que vous pouvez l'utiliser.

Il y avait un contest 4 years ago pour voir qui pourrait écrire la meilleure implémentation addEvent. L'un des principaux problèmes qu'il a tenté de résoudre était de conserver this dans le gestionnaire d'événements.

Voici one contest entry écrit par le créateur de jQuery:

function addEvent(obj, type, fn) { 
    if (obj.attachEvent) { 
    obj['e'+type+fn] = fn; 
    obj[type+fn] = function(){obj['e'+type+fn](window.event);} 
    obj.attachEvent('on'+type, obj[type+fn]); 
    } else 
    obj.addEventListener(type, fn, false); 
} 

(Et bien sûr, d'être symétrique):

function removeEvent(obj, type, fn) { 
    if (obj.detachEvent) { 
    obj.detachEvent('on'+type, obj[type+fn]); 
    obj[type+fn] = null; 
    } else 
    obj.removeEventListener(type, fn, false); 
} 

Renommer à "ObserveEvent" si vous le souhaitez.

Là vous l'avez, une implémentation de 8 lignes que vous pouvez déposer dans votre code - Pas de bibliothèques, pas de frameworks. Et votre référence this à l'intérieur de votre gestionnaire fonctionne très bien.

+0

Cool, merci! J'aimerais toujours passer à un cadre pour ajouter un peu plus de cohérence au code. – SeanJA

+0

+1 de moi :) le prototype ne dépend pas de la méthode, cependant? c'est-à-dire que le patching est sûr? –

+0

@Alexander: très gentil de votre part :) Je pense que je sais ce que vous voulez dire. Je ne tolère pas de patcher la bibliothèque prototype, non. Cependant, quand j'ai lu la question, je pense qu'ils ont juste déchiré le code des entrailles du prototype, auquel cas ils peuvent patcher leur propre code au contenu de leur coeur. –

4

Vous pouvez utiliser le event target, comme ceci:

ObserveEvent(printElem[i], 'click', function(e){ 
      var target = e.target || e.srcElement; 
      window.open(target.href, '', 'location=0,menubar=1,resizable=1,scrollbars=1,width='+810+',height='+700); 
      cancelEvent(e); 
    }); 
+0

Merde ... J'étais la plupart du temps là-bas, j'avais l'impression qu'il me manquait la partie e.srcElement. Merci – SeanJA

+2

Rappelle-nous des jours avant jQuery, hein –

+0

Cela échouera si 'printElem [i]' contient des enfants et l'un de * ceux * est cliqué. –

3

Le problème vient certainement du ObserveEvent fonction utilisant la méthode attachEvent d'IE, qui (contrairement à addEventListener dans d'autres navigateurs) ne définit pas this à l'objet observé dans le gestionnaire d'événements.

2

Une autre option: Créer une fermeture à portée l'élément du gestionnaire pour chaque élément:

var printElem = getElementsByClassName('print', 'a'); 
for(var i in printElem){ 
    (function(elem) { // elem === printElem[i] at time of execution later 
    ObserveEvent(elem, 'click', function(e){ 
     window.open(elem.href, '', 'location=0,menubar=1,resizable=1,scrollbars=1,width='+810+',height='+700); 
     cancelEvent(e); 
    }); 
    })(printElem[i]); // immediately call the temp function with our element 
} 
Questions connexes