Предотвращение ссылок перед загрузкой jQuery - PullRequest
6 голосов
/ 28 сентября 2010


Как я могу предотвратить ссылки на событие щелчка перед загрузкой jQuery?
Причина в том, что у меня мало ссылок, которые делают вызовы AJAX через функции jQuery 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 ]

9 голосов
/ 28 сентября 2010

Четыре варианта для вас:

Вариант 0

Перейти читать Ответ Шона Хогана , он указал, что это можно сделать с делегированием( doh! ) и я собрал пример реализации.

Вариант 1

Вы можете сделать href из ссылок "#msgstr "до тех пор, пока не будет загружен 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 в top вашего файла:

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>

...затем удалите onclick при загрузке jQuery:

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

(Вы можете оставить последний бит - вызов click off, если у них не все имеют одинаковый обработчик кликов.)

Я использовал вышеупомянутый класс, чтобы различать эти ссылки и другие, которые могут иметь встроенный onclick (в противном случае, к удивлению, селектор «a [onclick]» фактически работает в Chrome, Opera и Firefox для Linux и IE6и IE8 в Windows).

Опция 3

Поскольку кажется, что вы хотите, чтобы страница не работала до загрузки jQuery, вот другой подход:

  1. Убедитесь, что тег script для jQuery находится в разделе head вашей страницы (не внизу, где я обычно рекомендую его размещать).
  2. В самом низувашей страницы, непосредственно перед закрытием тега body, подключите ваши обработчики кликов без , завернув их в jQuery.ready call (или любой из его ярлыков).

Причина в следующем: # 1 обеспечит загрузку самого jQuery до отображения страницы, а # 2 подключит обработчики как можно скорее .Google рекомендует использовать такой тег в конце страницы (вместо функции ready или аналогичной) и говорит, что в этот момент элементы DOM будут готовы к обнаружению.


Отдельно, конечно, вы хотите, чтобы время, в течение которого ссылки не выполняли то, чего ожидает пользователь, было абсолютно максимально коротким , выполняя все возможные действия по оптимизации загрузки страницы.Нажатие на ссылку и ее отсутствие делает то, что выглядит, как это делает для плохого пользовательского опыта.

4 голосов
/ 28 сентября 2010

Вы можете использовать делегирование события: DOM-эквивалент jQuery live () и делегат () методы.

Может работать следующее:

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


Полный живой пример , приведенный ниже, работает на Chrome, Opera и Firefox для Linux, а также на IE6 и IE8 для Windows. Он предотвращает клики по ссылкам с классом «ждать» (вы можете делать все ссылки, если хотите) и запоминает первую нажатую ссылку. Затем он имитирует длительную задержку загрузки (пять секунд), затем подключает обработчики jQuery к ссылкам и удаляет обработчик уровня документа, который предотвращал щелчки, а затем запускает обработчик jQuery для ссылки, по которой щелкнули (обратите внимание, что это только вызывает обработчик, а не базовое поведение по умолчанию & mdash; но, поскольку вы хотите запускать ваши AJAX-файлы, я думаю, это нормально). & Mdash; 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 (где находится ваш обработчик 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);

});​
1 голос
/ 28 сентября 2010

Я не пробовал, но теоретически добавить обработчик событий без jquery для всех элементов, которые предотвращают действие по умолчанию (открытие ссылки), пока jquery не определен?

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