How can I prevent links on click event before jQuery is loaded?
The reason is I have few links that make AJAX calls through jQuery ajax functions and if user click them before jQuery framework is loaded the browser cant trigger jQuery ajax function and will follow links href="..."
.
Edit: Can I use this?
<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>
In jQuery's case, $ is just an alias for jQuery, so all the functionality is available without using $. Run $. noConflict() method to give control of the $ variable back to whichever library first implemented it. This helps us to make sure that jQuery doesn't conflict with the $ object of other libraries.
jQuery ready() MethodThe ready event occurs when the DOM (document object model) has been loaded. Because this event occurs after the document is ready, it is a good place to have all other jQuery events and functions. Like in the example above. The ready() method specifies what happens when a ready event occurs.
$( document ). ready() ready() will only run once the page Document Object Model (DOM) is ready for JavaScript code to execute. Code included inside $( window ). on( "load", function() { ... }) will run once the entire page (images or iframes), not just the DOM, is ready. // A $( document ).
Projects In JavaScript & JQuery It's always a good practice to add jQuery code in footer i.e. just before the closing </body> tag. If you have not done that, then use the defer attribute. The defer attribute is used to specify that the script execution occurs when the page loads.
Four options for you:
Option 0
Go read Sean Hogan's answer, he pointed out that this can be done with delegation (doh!) and I put together an example implementation.
Option 1
You can make the href
of the links "#" until jQuery is loaded, and then (if appropriate) change it to what it really should be. You can store what the href
should be in a data-
attribute, e.g.:
<a href='javascript:;' data-href='realtarget.html'>blah</a>
Then:
jQuery(function($) {
$("a[data-href]").each(function() {
var $this = $(this);
$this.attr("href", $this.attr("data-href"));
});
});
Again, that last bit only if you really need to make the href an href. If you're handling the click via JavaScript, no need to.
If validation is a significant part of your development cycle, it's important to note that attributes in the form data-xyz
are invalid in HTML4 and before (browsers don't actually care, but again, if you use validation...). They become valid as of HTML5.
Option 2
Use inline onclick
attributes to intercept the click prior to jQuery loading and basically say "Sorry, one moment". So in a script
tag at the top of your file:
function sorryLoading() {
alert("Sorry, the page is still loading, one moment please.");
return false;
}
...and then on the links:
<a href='realtarget.html' class='sorry' onclick='return sorryLoading();'>blah</a>
...then remove the onclick
on jQuery load:
jQuery(function($) {
$("a.sorry").removeClass('sorry').attr("onclick", "").click(yourRealClickHandler);
});
(You can leave the last bit — the click
call — off if they don't all have the same click handler.)
I've used a class above to differentiate between these links and others that might have an inline onclick
(otherwise, surprisingly the selector "a[onclick]" actually works on Chrome, Opera, and Firefox for Linux and IE6 and IE8 on Windows).
Option 3
Since it sounds like you want the page to be non-functional until jQuery loads, here's another approach:
head
section of your page (not at the bottom, where I'd normally recommend putting it).body
tag, hook up your click handlers without wrapping them in a jQuery.ready
call (or any of its shortcuts).The reason is this: #1 will ensure that jQuery itself is loaded prior to the page being rendered, and #2 will hook up the handlers as soon as possible. Google recommends using a tag at the end of the page like that (rather than a ready
function or similar) and says that at that point, the DOM elements will be ready to be discovered.
Separately, of course, you want to ensure that the time during which the links don't do what the user expects is absolutely as brief as possible by doing all of the page-load optimization stuff you can. Clicking a link and not having it do what it looks like it does makes for a poor user experience.
You could use event-delegation: the DOM equivalent of jQuery live() and delegate() methods.
The following might work:
<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: This disables the links permanently. They can be re-enabled by removing the event-handler, e.g. document.onclick = null
.
The complete, live example below works on Chrome, Opera, and Firefox for Linux as well as IE6 and IE8 for Windows. It prevents clicks on links with the class "wait" (you could do all links instead if you liked) and remembers the first link clicked. Then it simulates a long load delay (five seconds) and then hooks up jQuery handlers on the links and removes the document-level handler that was preventing clicks, and then triggers the jQuery handler on the link that was clicked (note that this only triggers the handler, not the underlying default behavior — but as you want to trigger your ajax stuff, I figure that's okay). — 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 (wherever your jQuery ready
handler is):
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);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With