最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Preventing Links before jQuery is Loaded - Stack Overflow

programmeradmin2浏览0评论

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>

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>
Share Improve this question edited Apr 15, 2022 at 15:26 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Sep 28, 2010 at 9:45 AliAli 611 silver badge3 bronze badges 2
  • You can try a UI approach. maybe create a preloader. – gianebao Commented Sep 28, 2010 at 9:49
  • I've updated Sean Hogan's answer with an example. He's absolutely right about how to go about this. – T.J. Crowder Commented Sep 28, 2010 at 14:21
Add a ment  | 

3 Answers 3

Reset to default 9

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 bee 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:

  1. Make sure that the script tag for jQuery is in the head section of your page (not at the bottom, where I'd normally remend putting it).
  2. At the very bottom of your page, just before closing the 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 remends 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 plete, 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./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./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.' 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.'>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);

});​

I haven't tried it, but in theory, add an event handler without jquery to all a elements that prevents the default action (opening the link) as long as jquery is undfinied?

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

评论列表(0)

  1. 暂无评论