2010-09-28 21 views
6


W jaki sposób mogę zapobiec łączeniu w zdarzeniu kliknięcia przed załadowaniem jQuery? Powodem jest to, że mam kilka linków, które wywołują połączenia AJAX za pomocą funkcji ajax jQuery i jeśli użytkownik kliknie je przed załadowaniem frameworka jQuery, przeglądarka nie może wywołać funkcji ajax jQuery i będzie podążać za linkami href = "..." Dzięki.Zapobieganie łączom przed załadowaniem jQuery

Edytuj: Czy mogę tego użyć?

<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

Można spróbować podejścia UI. może utworzyć preloader. – sheeks06

+0

Zaktualizowałem odpowiedź Seana Hogana na przykładzie. Ma absolutną rację, jak to zrobić. –

Odpowiedz

9

cztery opcje dla Ciebie:

opcja 0

Go czytać Sean Hogan's answer, zwrócił uwagę, że można to zrobić z delegacji i ułożyła przykład (doh!) realizacja.

Wariant 1

Można dokonać href powiązań „#” aż jQuery jest załadowany, a następnie (jeśli dotyczy), aby zmienić to, co naprawdę powinno być. Można przechowywać co href powinny być atrybutem data-, np .:

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

Następnie:

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

Ponownie, że ostatni kawałek tylko jeśli naprawdę potrzebujesz, aby href href. Jeśli obsługujesz klikanie za pomocą JavaScript, nie musisz.

Jeśli walidacja jest istotną częścią cyklu rozwojowego, należy pamiętać, że atrybuty w postaci data-xyz są nieprawidłowe w HTML4 i wcześniej (przeglądarki faktycznie nie obchodzi, ale ponownie, jeśli używasz sprawdzania poprawności ...) . Stają się one ważne od HTML5.

Wariant 2

Użyj inline onclick atrybuty przechwycić kliknij jQuery przed załadunkiem i po prostu powiedzieć: "Niestety, jeden moment". Więc w script tag w górnym z pliku:

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

... a potem na linki:

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

... następnie wyjąć onclick obciążenia jQuery:

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

(Możesz zostawić ostatni bit   — z click zadzwoń pod numer   — off jeśli nie wszystkie mają taką samą kliknij obsługi.)

Użyłem klasę wyżej odróżnić tych linków i innych, które mogłyby mieć inline onclick (inaczej zaskakująco selektor „a [onclick ] "faktycznie działa w przeglądarce Chrome, Opera i Firefox dla systemu Linux oraz IE6 i IE8 w systemie Windows).

Wariant 3

Ponieważ brzmi to jak chcesz, aby strona się niefunkcjonalne aż jQuery ładunku, tu jest inne podejście:

  1. Upewnij się, że tag skrypt jQuery jest w head sekcja twojej strony (nie na dole, gdzie normalnie polecałbym ją wstawić).
  2. Na samym dole strony, tuż przed zamknięciem znacznika body, podłącz komunikatory bez konieczności zawijania ich, zawijając je w wywołanie jQuery.ready (lub dowolnym z jego skrótów).

Powód jest następujący: 1 zapewnia, że ​​sam jQuery załadowano przed stronie, która jest wygenerowana i # 2 będzie podłączyć do obsługi jak najszybciej. Google zaleca używanie tagu na końcu strony (zamiast funkcji ready lub podobnej) i mówi, że w tym momencie elementy DOM będą gotowe do odkrycia.


Oddzielnie, oczywiście, chcesz mieć pewność, że czas, w którym linki nie rób tego, co oczekuje użytkownik absolutnie jak najkrótszy wykonując wszystkie rzeczy strona optymalizacji obciążenia ty mogą. Kliknięcie linku i jego brak powoduje, że wygląda na słabszy.

+1

Dzięki, ale to ogromna manipulacja DOM i masz własne problemy z SEO i szybkością ładowania strony. :) – Ali

+0

@Ali: Dobra strona o SEO. Dodałem kolejną opcję, gdy to wskazałeś. –

+0

dziękuję T. J., ale mam linki feeeeeeeeew, myślę, że javascript może to zrobić, ale nie jestem dobry w javascript bez frameworks próbowałem napisać funkcję, ale nie działa. (możesz zobaczyć tę funkcję w moim pytaniu? redagowałem to) – Ali

1

Nie próbowałem go, ale teoretycznie dodać obsługę zdarzeń bez jquery do wszystkich elementów, które uniemożliwiają domyślną akcję (otwarcie łącza), o ile jquery nie jest niedokończone?

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

Można użyć zdarzeń delegacji: równowartość DOM jQuery live() i delegate() metod.

Poniższa może działać:

<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: To wyłącza łącza stałe. Można je ponownie włączyć, usuwając moduł obsługi zdarzeń, np. document.onclick = null.


complete, live example poniżej działa w Chrome, Opera i Firefox dla systemu Linux, jak również IE6 i IE8 dla Windows. Zapobiega klikaniu linków z klasą "czekaj" (możesz zrobić wszystkie linki zamiast tego, jeśli ci się spodobało) i zapamiętuje pierwsze kliknięcie linku. Następnie symuluje długie opóźnienie obciążenia (pięć sekund), a następnie łączy funkcje obsługi jQuery w łączach i usuwa mechanizm obsługi poziomu dokumentu, który blokował kliknięcia, a następnie uruchamia procedurę obsługi jQuery dla klikniętego łącza (pamiętaj, że to tylko uruchamia Handler, a nie podstawowe domyślne zachowanie, ale jak chcesz wywołać twoje rzeczy z ajaxem, myślę, że to w porządku).   — 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 (gdziekolwiek obsługi jQuery ready jest):

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! ** Oczywiście, przechwytywanie kliknięć na poziomie dokumentu podczas renderowania strony jest sposobem na zrobienie tego. Wolałem dodawać kompletny przykład na żywo (i używając 'attachEvent' /' addEventListener' zamiast 'onclick'). –

Powiązane problemy