2010-07-19 11 views
3

J'utilise jQuery pour lier tous les liens de la page (j'utilise l'événement 'click', mais j'ai essayé différentes combinaisons de 'mousedown' et 'mouseup', avec bind() et live() pour pas disponible).javascript Comment déclencher l'action de clic natif (événement de relecture) plus tard?

Je peux intercepter le clic sans problème (avec toutes les méthodes ci-dessus). Ce que j'essaie de faire est d'envoyer des données via une requête GET, et quand elle se termine, permettre l'action de clic par défaut pour continuer.

Depuis que je communique à travers le domaine, je dois utiliser GET plutôt que POST, et ne peut donc pas faire un appel synchrone.

Par conséquent, je dois retourner 'faux' de l'événement de clic intercepté, stocker l'événement pour plus tard, puis le renvoyer manuellement une fois la communication terminée. Si je renvoie true, la communication est coupée à mi-chemin lorsque l'emplacement de la page change.

Le problème est, je ne peux pas trouver un moyen de déclencher l'événement de clic natif plus tard.

var storedEvent; 
$("#wrapper a").bind('click', function(event, processed) { 
    $(event.target).unbind('click'); // temporary to make code branching easier 
    storedEvent = event.target; 
    event.stopPropagation(); 

    $.ajax({ 
     dataType: 'jsonp', 
     data: linkData, 
     jsonp: 'cb', 
     url: 'xxx', 
     cache: false, 
     complete: function(response) { 
      // How do I now go back and fire the native click event here? 
      $(storedEvent).click(); 
     } 
    }); 
    return false; 
} 

J'ai essayé d'utiliser click() et trigger() à l'endroit indiqué, mais aucun n'a fonctionné.

Je sais que la soumission est réussie, et le code se branche correctement - j'ai débogué aussi loin. Je ne semble pas être capable de rejouer l'événement.

Notez que je ne peux pas faire quelque chose de simple, comme stocker le href et définir window.location plus tard - certains des liens ont leurs propres onClicks ensemble, tandis que d'autres ont spécifié des cibles varius. J'aimerais idéalement rejouer l'événement que j'ai arrêté plus tôt.

J'ai commencé à utiliser la délégation d'événements avec live() et j'avais tout mis en œuvre, en dehors de cela - je l'ai simplifié jusqu'à un bind() afin de simplifier le problème.

+1

À quoi ressemble l'événement de clic d'origine? Est-ce différent pour tout? – spinon

+0

Parfois, il s'agit d'un clic spécifique, parfois d'un clic lié (par exemple pour thickbox/colorbox), parfois aucun événement - juste un lien, mais peut avoir plusieurs cibles (par exemple _top). J'ai réussi à obtenir le dispatching JavScript natif dans firefox - mais j'ai besoin de travailler dans IE. Dois-je inspecter l'élément et déterminer manuellement s'il faut déclencher un événement lié ou définir l'emplacement (cible). – Jhong

+0

Je crois que vous auriez à travailler par vous-même oui – redsquare

Répondre

0

Vous ne pouvez pas déclencher un événement de clic sur une ancre et l'amener à suivre le navigateur croisé href.

+0

J'ai plus loin. Je n'ai pas réalisé qu'il y avait une fonction JS() native dans IE. Cela semble fonctionner. Donc pour FF je peux faire dispatchEvent(). Pour IE je dois if (hassomethingbound) puis fireEvent() sinon cliquez sur(). Alors - comment trouver si quelque chose est déjà lié? – Jhong

+0

Si un événement inline est spécifié, vous pouvez vérifier avec 'if (element.onclick)' – Anurag

+0

oui, mais ce n'est pas mon problème - et si cet élément est déjà lié à jquery's bind(), live(), ou similaire? Il ne semble y avoir aucun moyen de savoir ce qui se passera sans énumérer tous les événements sur la page ... – Jhong

0

Il s'avère que redsquare est fondamentalement correct - il ne fonctionne pas sans vous arracher les cheveux.

IE est le problème. dispatchEvent() fonctionne correctement dans FireFox. Dans IE, vous pouvez choisir fireEvent pour déclencher tous les événements associés (mais pas le clic), ou cliquez sur() (pour les clics mais pas les événements), mais vous ne pouvez pas faire les deux correctement. Je l'ai obtenu "presque fonctionnant" en changeant temporairement les hrefs et les cibles de liens de sorte qu'ils aient chargé une page blanche dans un iframe. J'ai ensuite écouté les événements "load" de iframe pour déterminer si l'action par défaut du lien avait eu lieu. Dans IE, je pourrais alors déclencher "click" si nécessaire, ou "fireEvent" sinon, après avoir changé le href et la cible en retour.

Cependant, il s'agissait d'un hack - et si l'un des liens avait un événement lié qui reposait sur l'attribut href? (thickbox semblait continuer à travailler, mais je suppose que c'était une condition de course).

En fin de compte, je n'avais pas besoin de le faire de toute façon (JavaScript/jQuery: How to make sure cross-domain click tracking event succeeds before the user leaves the page?), donc je suis soulagé. Il s'avère que j'ai dû utiliser POST dans ce cas.

1

À jour réponse: oui, vous pouvez (en supposant que vous ne supporte plus IE8).

Utilisez dispatchEvent() pour déclencher une copie de l'événement original.

Tout d'abord vous avez besoin d'une fonction d'utilité pour cloner l'événement (comme les navigateurs permettent uniquement les événements qui doivent être envoyés une fois, pour des raisons de sécurité):

var cloneNativeMouseEvent = function (original) { 
    var copy; 
    try { 
     copy = new MouseEvent(original.type, original); 
    } catch (stupidInternetExplorer) { 
     copy = document.createEvent('MouseEvent'); 
     copy.initMouseEvent(original.type, original.bubbles, original.cancelable, original.view, 
      original.detail, original.screenX, original.screenY, original.clientX, original.clientY, 
      original.ctrlKey, original.altKey, original.shiftKey, original.metaKey, original.button, 
      original.relatedTarget) 
    } 
    return copy; 
}; 

Dans votre gestionnaire de clic stocker une référence à l'événement jQuery pour plus tard Replay:

$("#wrapper a").bind('click', function (event) { 
    event.preventDefault(); 
    storedEvent = event; 
    ... 
} 

Et enfin, dans le rappel où vous voulez déclencher le clic à nouveau, faites comme suit:

var originalEventClone = cloneNativeMouseEvent(storedEvent.originalEvent); 
storedEvent.target.dispatchEvent(originalEventClone); 

Veuillez noter qu'en général, les événements créés ou modifiés par JavaScript sont marqués comme «non approuvés» par les agents utilisateurs, de sorte qu'ils ne peuvent pas déclencher d'actions par défaut. Heureusement cliquez sur événements sont la seule exception. (1)