2009-03-08 10 views
3

J'essaie de créer un script greasemonkey qui va créer dynamiquement des tables de données basées sur l'interaction de l'utilisateur avec ... autre dynamiquement créé des tables de données. Mon problème est que je dois faire deux passes chaque fois que je crée une table: une pour créer la table, et une autre pour aller chercher tous les objets dans la table que je veux ajouter aux gestionnaires d'événements (par id) et ajouter les différents gestionnaires d'événements pour eux.Comment enregistrer un gestionnaire d'événement javascript pour un élément qui n'a pas encore été ajouté à la page

Si j'essaie d'ajouter, par exemple, un événement onClick à une table td avant d'avoir créé la table et de l'avoir insérée dans le code HTML, j'obtiens une exception «composant non disponible».

Ceci est incroyablement lourd, car je dois soit maintenir, séparément, une liste des ID et ce que je devrais faire à ces éléments lorsque je fais ma deuxième passe pour ajouter les gestionnaires, ou développer une convention de nommage par laquelle je savoir, sur la base de la carte d'identité, ce que je devrais faire avec l'élément.

Il doit y avoir une meilleure façon de procéder. Je ne l'ai pas encore compris. Quelqu'un a des idées?

Répondre

5

jQuery 1.3+ a une fonction nouvelle en direct() qui peut mettre en place des gestionnaires d'événements pour les éléments qui n'existent pas encore .. check it out

1

Vous devez attendre l'élément à ajouter à la page, puis ajoutez le gestionnaire d'événement alors.

Il n'y a pas de manière facile de dire "ajoutez ceci à tous les éléments de ce type, maintenant et dans le futur".

Il est possible d'avoir une minuterie périodiquement vérifier la page pour de nouveaux éléments, en appliquant une file d'événements (ou d'autres propriétés) à eux comme ils apparaissent, tous dans les coulisses. Cela peut être extrait et réutilisé, par exemple Jquery peut faire ce genre de chose.

+0

+1 pour la première partie de la réponse. Je n'aime pas vraiment la minuterie, mais je vois ce que tu veux dire. Je reste loin de jQuery. C'est une surcharge dans les applications exigeant des performances supérieures. – theoutlander

+0

Depuis que j'ai écrit cette réponse, il peut y avoir de nouvelles façons pour que votre code soit notifié lorsque de nouveaux éléments apparaissent sur le DOM autre que l'interrogation périodique, je ne sais pas. Mais la meilleure réponse dans la plupart des cas serait d'utiliser le bouillonnement d'événement à la place. Cela dépend de la chaîne d'éléments pour transmettre l'événement à un parent commun. – thomasrutter

11

Tout d'abord, j'aimerais savoir pourquoi vous avez besoin d'un ID différent pour chaque TD. L'ID contient-elle des informations importantes, telles qu'un index? Dans cette situation, il pourrait être préférable de créer chaque TD dans une boucle. En outre, vous ne pouvez évidemment pas attacher un gestionnaire d'événements à un élément DOM qui n'existe pas! Il n'a pas besoin d'être injecté dans le DOM, mais il DOIT exister dans une certaine mesure. JQuery live() n'est pas un mystère magique, il utilise simplement la délégation d'événements, il associe donc l'événement à un élément parent, tel que la table, puis décide de ce qui se passe en fonction de la cible du clic. Voici un exemple rudimentaire. J'enregistre un gestionnaire à l'élément « corps », puis je teste chaque fois pour voir ce que la cible est, si elle est un élément TD I doSomething() ->

document.body.onclick = function(e) { 

    var realTarget = e ? e.target : window.event.srcElement; 

    if (realTarget.nodeName.toLowerCase() === 'td') { 
     doSomething(); 
    } 

}; 

délégation de l'événement repose sur bouillonnement d'événement appelé quelque chose (ou "propogation") qui est la manière dont les navigateurs modernes implémentent le modèle d'événement. Chaque événement déclenché se déplace vers le haut à travers le DOM jusqu'à ce qu'il ne puisse pas aller plus loin. Donc, si vous cliquez sur une ancre dans un paragraphe, l'événement 'click' de l'ancre se déclenchera et ALORS l'événement 'click' tirera, etc.

+0

Oui, l'ID contient des informations. Pour chacun de ces TD, je veux que l'événement onclick appelle la même fonction, mais avec des paramètres différents dans l'appel. Mon hack était de bourrer les paramètres en une seule chaîne et de laisser la méthode que j'appelle l'analyser pour les 5 nombres différents dont elle a besoin. –

1

Comme JimmyP l'a fait remarquer, votre problème peut facilement être résolu en utilisant event bubbling. Vous pourriez envisager d'écrire une fonction wrapper pour contourner les incohérences du navigateur - ma propre version can be found here et serait utilisé comme ceci:

capture('click', '#element-id', function(event) { 
    // `this` will be the originating element 
    // return `false` to prevent default action 
});