2010-09-28 19 views
6


Comment puis-je empêcher les liens sur un événement click avant le chargement de jQuery?
La raison en est que j'ai peu de liens qui font AJAX appels via jQuery ajax fonctions et si l'utilisateur cliquez dessus avant jQuery framework est chargé le navigateur ne peut pas déclencher jQuery ajax fonction et suivra les liens href = "..." Merci.Prévention des liens avant le chargement de jQuery

Editer: Puis-je l'utiliser?

<head> 
... 
    <script type="text/javascript"> 
    window.onload = prevCl(); 
    function prevCl() { 
    var links = document.links[]; 
    links.onclick = check(); 
    } 
    function check() { 
    if (typeof jQuery == 'undefined') { 
    return false; 
    } 
    } 
    </script> 
</head> 
+0

Vous pouvez essayer une approche de l'interface utilisateur. peut-être créer un préchargeur. – sheeks06

+0

J'ai mis à jour la réponse de Sean Hogan avec un exemple. Il a absolument raison sur la façon de s'y prendre. –

Répondre

9

Quatre options pour vous:

Option 0

Allez lire Sean Hogan's answer, il a souligné que cela peut être fait avec la délégation et moi avons mis sur pied un exemple (doh!) la mise en oeuvre.

Option 1

Vous pouvez faire le href des liens « # » jusqu'à ce que jQuery est chargé, puis (le cas échéant) changer à ce qu'il devrait vraiment être. Vous pouvez stocker ce que le href doit être dans un attribut data-, .: par exemple

<a href='javascript:;' data-href='realtarget.html'>blah</a> 

Puis:

jQuery(function($) { 
    $("a[data-href]").each(function() { 
     var $this = $(this); 
     $this.attr("href", $this.attr("data-href")); 
    }); 
}); 

Encore une fois, ce dernier bit seulement si vous avez vraiment besoin de faire le href un href. Si vous manipulez le clic via JavaScript, inutile de le faire. Si la validation est une partie importante de votre cycle de développement, il est important de noter que les attributs sous la forme data-xyz ne sont pas valides dans HTML4 et avant (les navigateurs ne se soucient pas vraiment, mais encore une fois, si vous utilisez la validation ...) . Ils deviennent valables dès HTML5.

Option 2

utilisation en ligne onclick attributs pour intercepter le clic avant le chargement jQuery et dire essentiellement "Désolé, un moment". Donc, dans une balise script au haut de votre fichier:

function sorryLoading() { 
    alert("Sorry, the page is still loading, one moment please."); 
    return false; 
} 

... puis sur les liens:

<a href='realtarget.html' class='sorry' onclick='return sorryLoading();'>blah</a> 

... puis retirez la onclick la charge jQuery:

jQuery(function($) { 
    $("a.sorry").removeClass('sorry').attr("onclick", "").click(yourRealClickHandler); 
}); 

(Vous pouvez laisser le dernier bit   — l'appel click   — off si elles n'ont pas tous le même gestionnaire de clic.)

J'ai utilisé une classe ci-dessus pour la différence entre ces liens et d'autres qui pourraient avoir une ligne onclick (sinon, de façon surprenante le sélecteur « un [onclick ] "fonctionne en fait sur Chrome, Opera et Firefox pour Linux et IE6 et IE8 sous Windows).

Option 3

Comme il semble que vous voulez que la page soit des charges non fonctionnel jusqu'à ce que jQuery, voici une autre approche:

  1. Assurez-vous que la balise de script pour jQuery est dans le head section de votre page (pas en bas, où je recommande normalement de le mettre).
  2. Au bas de la page, juste avant la fermeture de la balise body, accrochez vos gestionnaires de clic sans les envelopper dans un appel jQuery.ready (ou l'un de ses raccourcis).

La raison est la suivante: # 1 veillera à ce que jQuery est lui-même chargé avant la page en cours rendus et # 2 accrochera les gestionnaires le plus tôt possible. Google recommande d'utiliser une balise à la fin de la page comme cela (plutôt qu'une fonction ready ou similaire) et dit qu'à ce stade, les éléments DOM seront prêts à être découverts.


séparément, bien sûr, vous voulez vous assurer que le temps pendant lequel les liens ne font pas ce que l'utilisateur attend est absolument aussi bref que possible en faisant tous les trucs d'optimisation de chargement des pages que vous pouvez. Cliquer sur un lien et ne pas l'avoir fait ce à quoi il ressemble fait une mauvaise expérience utilisateur.

+1

Merci, mais c'est une énorme manipulation DOM et ont des problèmes propres au référencement et à la vitesse de chargement de la page. :) – Ali

+0

@Ali: Bon point sur le référencement. J'ajoutais une autre option comme vous l'avez souligné. –

+0

merci T. J. mais j'ai des liens feeeeeeeeeeew, je pense que javascript peut le faire mais je ne suis pas bon au javascript sans frameworks j'ai essayé d'écrire une fonction, mais n'a pas fonctionné. (pouvez-vous regarder cette fonction dans ma question? J'ai édité cela) – Ali

1

Je ne l'ai pas essayé, mais en théorie, ajoutez un gestionnaire d'événements sans jquery à tous les éléments qui empêchent l'action par défaut (ouverture du lien) tant que jquery est indéfini?

getElementsByTagNames('a').addEventListener('click',function (event) { 
    if (typeof jQuery == 'undefined') { 
    event.preventDeafault(); 
    } 
},false) 
4

Vous pouvez utiliser la délégation de-événement: l'équivalent DOM de jQuery live() et delegate() méthodes.

Ce qui suit pourrait fonctionner:

<head> 

<script> 
function linkMatcher(node) { // modify this if not all links are disabled 
if (node.href) return true; 
else return false; 
} 

document.onclick = function(e) { 
e = e || window.event; 
var target = e.target || e.srcElement; 
for (var node=target; node!=document; node=node.parentNode) { 
    if (node.tagName == "A") return !linkMatcher(node); 
} 
} 
</script> 
</head> 

EDIT: Ceci désactive les liens de façon permanente. Ils peuvent être réactivés en supprimant le gestionnaire d'événements, par ex. document.onclick = null.


Le complete, live example ci-dessous fonctionne sur Chrome, Opera et Firefox pour Linux ainsi que IE6 et IE8 pour Windows. Il empêche les clics sur les liens avec la classe "wait" (vous pouvez faire tous les liens à la place si vous le souhaitez) et se souvient du premier lien cliqué. Ensuite, il simule un long délai de chargement (cinq secondes), puis connecte les gestionnaires jQuery sur les liens et supprime le gestionnaire de niveau document qui empêchait les clics, puis déclenche le gestionnaire jQuery sur le lien cliqué (notez que cela ne déclenche que le gestionnaire, pas le comportement par défaut sous-jacent   — mais comme vous voulez déclencher votre truc ajax, je me dis que ça va).   — T.J.Crowder

HTML:

<!DOCTYPE html> 
<html> 
<head> 
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> 
<meta charset=utf-8 /> 
<title>Link Click Delay Test Page</title> 
<!--[if IE]> 
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> 
<![endif]--> 
<style> 
    article, aside, figure, footer, header, hgroup, 
    menu, nav, section { display: block; } 
    body { 
    font-family: sans-serif; 
    } 
    p { 
    margin: 0px; 
    } 
</style> 
<script type='text/javascript'> 
    // A scoping function to avoid creating global symbols 
    (function() { 
    // Figure out what to hook clicks on 
    var container = 
     document.body || 
     document.documentElement || 
     document; 

    // Hook clicks that reach the bottom level 
    hookClicks(); 
    function hookClicks() { 
     if (container.attachEvent) { 
     container.attachEvent("onclick", handleClick); 
     } 
     else if (document.addEventListener) { 
     container.addEventListener("click", handleClick, false); 
     } 
    } 

    // Set up an unhook function for jQuery to call 
    window.unhookClicks = unhookClicks; 
    function unhookClicks() { 
     if (container.attachEvent) { 
     container.detachEvent("onclick", handleClick); 
     } 
     else if (document.addEventListener) { 
     container.removeEventListener("click", handleClick, false); 
     } 
    } 

    // Handle clicks 
    function handleClick(event) { 
     var target; 

     // Handle Microsoft vs. W3C event passing style 
     event = event || window.event; 

     // Get the target (again handling Microsoft vs. W3C style) 
     target = event.target || event.srcElement; 

     // Do we have a target that's an A with the class "wait"? 
     if (target && 
      target.tagName.toUpperCase() === "A" && 
      (" " + target.className + " ").indexOf(" wait ") >= 0 
     ) { 
     // It's a link we want to prevent for the moment 
     // Remember the element that was clicked if there 
     // isn't already one (or replace it, depends on the 
     // UX you want to provide 
     if (!window.pendingLink) { 
      window.pendingLink = target; 
     } 

     // Prevent it from being processed 
     if (event.preventDefault) { // If W3C method... 
      event.preventDefault(); 
     } 

     // This should work if preventDefault doesn't 
     return false; 
     } 
    } 
    })(); 
</script> 
</head> 
<body> 
    <p><a href='http://www.google.com' class='wait'>Google</a> 
    - This one waits 
    <br><a href='http://news.bbc.co.uk' class='wait'>BBC News</a> 
    - This one also waits 
    <br><a href='http://www.cnn.com'>CNN</a> 
    - This one doesn't wait, it goes immediately 
    </p> 
</body> 
</html>​ 

JavaScript (où votre gestionnaire jQuery est ready):

jQuery(function($) { 

    // Use setTimeout to fake a long delay loading 
    setTimeout(function() { 

    // Hook up our proper click handling 
    // Obviously, replace this with whatever does the ajax 
    $("a.wait").click(function(event) { 
     alert("The jQuery handler for " + this.href + " link was triggered."); 
    }); 

    // If we have clicks disabled, enable them 
    if (window.unhookClicks) { 
     window.unhookClicks(); 
     window.unhookClicks = undefined; 
    } 

    // Do we have a pending link to follow? 
    if (window.pendingLink) { 
     // Yes, grab it and clear it 
     var $link = $(window.pendingLink); 
     window.pendingLink = undefined; 

     // Trigger any jQuery event handlers on it. 
     // Note that this will NOT follow the link, 
     // just trigger jQuery event handlers that 
     // are on the link. 
     $link.click(); 
    } 

    // We've loaded! 
    $("<p>Finally loaded!</p>").appendTo(document.body); 

    // End of fake delay function 
    }, 5000); 

});​ 
+0

** Doh! ** Bien sûr, attraper les clics au niveau du document pendant que la page est en cours de rendu est le moyen de le faire. J'ai pris la liberté d'ajouter un exemple complet, en direct (et en utilisant 'attachEvent' /' addEventListener' plutôt que 'onclick'). –