在加载jQuery之前防止链接

时间:2010-09-28 09:45:25

标签: javascript jquery ajax javascript-events onclick


如何在加载jQuery之前阻止点击事件的链接?
原因是我有很少的链接通过jQuery ajax函数调用AJAX,如果用户在加载jQuery框架之前单击它们,浏览器无法触发jQuery ajax函数并将跟随链接href =“...” 感谢。

编辑:我可以使用它吗?

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

3 个答案:

答案 0 :(得分:9)

四种选择:

选项0

阅读Sean Hogan's answer,他指出这可以通过委托( doh!)完成,并且我将一个示例实现放在一起。

选项1

你可以使链接的href“#”直到加载jQuery,然后(如果合适的话)将其更改为它应该是什么。您可以存储href属于data-属性的内容,例如:

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

然后:

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

同样,只有当你真的需要将href设为href时才是最后一位。如果您通过JavaScript处理点击,则无需。

如果验证是开发周期的重要部分,请务必注意data-xyz形式的属性在HTML4及之前是无效的(浏览器实际上并不关心,但如果使用验证,则再次。 ..)。它们从HTML5开始有效。

选项2

使用内联onclick属性在jQuery加载之前拦截点击,并基本上说“抱歉,一刻”。因此,在您文件的顶部script标记中:

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

...然后在链接上:

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

...然后删除jQuery load上的onclick

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

(如果他们没有相同的点击处理程序,你可以留下最后一位 - click来电。)

我使用上面的一个类来区分这些链接和其他可能具有内联onclick的链接(否则,令人惊讶的是选择器“a [onclick]”实际上适用于Chrome,Opera和Firefox for Linux和Windows上的IE6和IE8。)

选项3

因为听起来你希望页面在jQuery加载之前不起作用,所以这是另一种方法:

  1. 确保jQuery的脚本标记位于页面的head部分(不在底部,我通常建议放在其中)。
  2. 在页面的最底部,在关闭body代码之前,将> >的点击处理程序与jQuery.ready调用(或其中的任何一个)挂钩快捷方式)。
  3. 原因是:#1将确保在呈现页面之前加载jQuery本身,而#2将尽快连接处理程序 。 Google建议在页面末尾使用标记(而不是ready函数或类似标记),并说在那时,DOM元素就可以被发现了。


    另外,当然,您希望通过执行所有页面加载优化的内容,确保链接不能达到用户期望的时间绝对尽可能简短您可以。点击一个链接而没有它看起来像它确实会导致糟糕的用户体验。

答案 1 :(得分:4)

您可以使用事件委派:相当于jQuery live()delegate()方法的DOM。

以下可能有效:

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

编辑:这会永久禁用链接。可以通过删除事件处理程序来重新启用它们,例如, document.onclick = null


下面的complete, live example适用于Chrome,Opera和Firefox for Linux以及适用于Windows的IE6和IE8。它会阻止点击“等待”类的链接(如果您愿意,可以改为完成所有链接),并记住点击的第一个链接。然后它模拟一个长的加载延迟(五秒),然后在链接上挂钩jQuery处理程序并删除阻止点击的文档级处理程序,然后在单击的链接上触发jQuery处理程序(请注意,这只会触发处理程序,而不是底层的默认行为 - 但是当你想触发你的ajax时,我认为没关系)。 - T.J.克劳德

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(无论你的jQuery 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);

});​

答案 2 :(得分:1)

我还没有尝试过,但理论上,只要jquery未完成,就可以向所有阻止默认操作(打开链接)的元素添加一个没有jquery的事件处理程序?

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