Подтвердить что ты не робот

Как сделать выполнение script дождитесь загрузки jquery

У меня возникла проблема, когда страница загружается так быстро, что jquery не закончил загрузку до того, как она вызывается последующим script. Есть ли способ проверить наличие jquery, а если он не существует, подождите некоторое время, а затем повторите попытку?


В ответ на ответы/комментарии ниже я размещаю часть разметки.

Ситуация... главная страница asp.net и дочерняя страница.

На главной странице у меня есть ссылка на jquery. Затем на странице содержимого у меня есть ссылка на страницу script. Когда загружается страница script, она жалуется, что "$ is undefined".

Я помещал предупреждения в нескольких точках разметки, чтобы увидеть порядок, в котором они стреляли, и подтвердил, что он срабатывает в следующем порядке:

  • Заголовок главной страницы.
  • Блок содержимого страницы для детей 1 (находится внутри глава главной страницы, но после сценариев мастер-страницы называется).
  • Блок содержимого страницы для детей 2.

Вот разметка в верхней части главной страницы:

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="SiteMaster" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Reporting Portal</title>
    <link href="~/Styles/site.css" rel="stylesheet" type="text/css" />
    <link href="~/Styles/red/red.css" rel="stylesheet" type="text/css" />
    <script type="text/Scripts" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> 
    <script type="text/Scripts" language="javascript" src="../Scripts/jquery.dropdownPlain.js"></script>
    <script type="text/Scripts" language="javascript" src="../Scripts/facebox.js"></script>
    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
    <asp:ContentPlaceHolder ID="head" runat="server">
    </asp:ContentPlaceHolder>
</head>

Затем в теле главной страницы есть дополнительный ContentPlaceHolder:

 <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
                </asp:ContentPlaceHolder>

На дочерней странице это выглядит так:

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Dashboard.aspx.cs" Inherits="Data.Dashboard" %>
<%@ Register src="../userControls/ucDropdownMenu.ascx" tagname="ucDropdownMenu" tagprefix="uc1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
    <link rel="stylesheet" type="text/css" href="../Styles/paserMap.css" />
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
***CONTENT HERE***
    <script src="../Scripts/Dashboard.js" type="text/javascript"></script>
</asp:Content>

Вот содержимое файла "../ Script/Dashboard.js":

    $(document).ready(function () {

    $('.tgl:first').show(); // Show the first div

    //Description: East panel parent tab navigation
    $('.tabNav label').click(function () {
        $('.tabNav li').removeClass('active')
        $(this).parent().addClass('active');

        var index = $(this).parent('li').index();
        var divToggle = $('.ui-layout-content').children('div.tgl');

        //hide all subToggle divs
        divToggle.hide();
        divToggle.eq(index).show();
    });

});
4b9b3361

Ответ 1

изменить

Не могли бы вы попробовать правильный тип для тэгов script? Я вижу, что вы используете text/Scripts, что не соответствует правильному mimetype для javascript.

Используйте это:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> 
<script type="text/javascript" src="../Scripts/jquery.dropdownPlain.js"></script>
<script type="text/javascript" src="../Scripts/facebox.js"></script>

end edit

или вы можете взглянуть на require.js, который является загрузчиком для вашего кода javascript.

в зависимости от вашего проекта, это может быть, однако, немного завышенным

Ответ 2

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

function defer(method) {
    if (window.jQuery) {
        method();
    } else {
        setTimeout(function() { defer(method) }, 50);
    }
}

Он будет рекурсивно вызывать метод отсрочки каждые 50 мс до тех пор, пока window.jQuery не будет существовать, и в это время он выйдет и вызовет method()

Пример с анонимной функцией:

defer(function () {
    alert("jQuery is now loaded");
});

Ответ 3

вы можете использовать атрибут defer для загрузки script на самом конце.

<script type='text/javascript' src='myscript.js' defer='defer'></script>

но обычно загрузка вашего script в правильном порядке должна делать трюк, поэтому обязательно добавьте jquery перед своим script

Если ваш код находится на странице, а не в отдельном файле js, поэтому вы должны выполнить свой script только после того, как документ будет готов и инкапсулировать ваш код, как это должно работать тоже:

$(function(){
//here goes your code
});

Ответ 4

Еще один способ сделать это, хотя метод Darbio defer более гибкий.

(function() {
  var nTimer = setInterval(function() {
    if (window.jQuery) {
      // Do something with jQuery
      clearInterval(nTimer);
    }
  }, 100);
})();

Ответ 5

Вы можете попробовать событие onload. Он поднимался, когда загружались все сценарии:

window.onload = function () {
   //jquery ready for use here
}

Но имейте в виду, что вы можете переопределить другие скрипты, в которых используется window.onload.

Ответ 6

Это обычная проблема, представьте, что вы используете классный PHP-шаблон для шаблонов, поэтому у вас есть базовый макет:

HEADER
BODY ==> dynamic CONTENT/PAGE
FOOTER

И, конечно же, вы читали где-нибудь лучше загружать Javascript внизу страницы, поэтому ваш динамический контент не знает, кто такой jQuery (или $).

Также вы читаете где-нибудь это хорошо для встроенного небольшого Javascript, поэтому представьте, что вам нужно jQuery на странице, бабум, $не определен (.. еще ^^).

Мне нравится решение, которое Facebook предоставляет

window.fbAsyncInit = function() { alert('FB is ready !'); }

Итак, как ленивый программист (я должен сказать, хороший программист ^^), вы можете использовать эквивалент (на своей странице):

window.jqReady = function() {}

И добавьте в нижней части вашего макета, после включения jQuery

if (window.hasOwnProperty('jqReady')) $(function() {window.jqReady();});

Ответ 7

Использование:

$(document).ready(function() {
    // put all your jQuery goodness in here.
});

Ознакомьтесь с этим для получения дополнительной информации: http://www.learningjquery.com/2006/09/introducing-document-ready

Примечание. Это должно работать до тех пор, пока импорт script для вашей библиотеки JQuery выше этого вызова.

Обновление:

Если по какой-то причине ваш код не загружается синхронно (какой я никогда не сталкивался, но, по-видимому, возможно, из комментария ниже не должно произойти), вы можете закодировать его следующим образом.

function yourFunctionToRun(){
    //Your JQuery goodness here
}

function runYourFunctionWhenJQueryIsLoaded() {
    if (window.$){
        //possibly some other JQuery checks to make sure that everything is loaded here

        yourFunctionToRun();
    } else {
        setTimeout(runYourFunctionWhenJQueryIsLoaded, 50);
    }
}

runYourFunctionWhenJQueryIsLoaded();

Ответ 8

Вместо того, чтобы "ждать" (обычно это делается с помощью setTimeout), вы также можете использовать определение объекта jQuery в самом окне как крючок для выполнения вашего кода, который опирается на него. Это достигается с помощью определения свойства, определенного с помощью Object.defineProperty.

(function(){
  var _jQuery;
  Object.defineProperty(window, 'jQuery', {
    get: function() { return _jQuery; },
    set: function($) {
      _jQuery = $;

      // put code or call to function that uses jQuery here

    }
  });
})();

Ответ 9

Я не думаю, что твоя проблема. Script загрузка по умолчанию синхронна, поэтому, если вы не используете атрибут defer или не загружаете сам jQuery через другой запрос AJAX, ваша проблема, вероятно, больше похожа на 404. Можете ли вы показать свою разметку и сообщить нам, если вы видите что-нибудь подозрительное в firebug или веб-инспекторе?

Ответ 10

Проверьте это:

https://jsfiddle.net/neohunter/ey2pqt5z/

Он создаст фальшивый объект jQuery, который позволит вам использовать методы onload jquery, и они будут выполнены, как только загрузится jquery.

Это не идеально.

// This have to be on <HEAD> preferibly inline
var delayed_jquery = [];
jQuery = function() {
  if (typeof arguments[0] == "function") {
    jQuery(document).ready(arguments[0]);
  } else {
    return {
      ready: function(fn) {
        console.log("registering function");
        delayed_jquery.push(fn);
      }
    }
  }
};
$ = jQuery;
var waitForLoad = function() {
  if (typeof jQuery.fn != "undefined") {
    console.log("jquery loaded!!!");
    for (k in delayed_jquery) {
      delayed_jquery[k]();
    }
  } else {
    console.log("jquery not loaded..");
    window.setTimeout(waitForLoad, 500);
  }
};
window.setTimeout(waitForLoad, 500);
// end



// now lets use jQuery (the fake version)
jQuery(document).ready(function() {
  alert('Jquery now exists!');
});

jQuery(function() {
  alert('Jquery now exists, this is using an alternative call');
})

// And lets load the real jquery after 3 seconds..
window.setTimeout(function() {
  var newscript = document.createElement('script');
  newscript.type = 'text/javascript';
  newscript.async = true;
  newscript.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js';
  (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(newscript);
}, 3000);

Ответ 11

Самый простой и безопасный способ - использовать что-то вроде этого:

    var waitForJQuery = setInterval(function () {
    if (typeof $ != 'undefined') {

        // place your code here.

        clearInterval(waitForJQuery);
    }
}, 10);

Ответ 12

Я не очень люблю интервалы. Когда я хочу отложить jquery или что-то на самом деле, обычно это происходит примерно так.

Начните с:

<html>
 <head>
  <script>var $d=[];var $=(n)=>{$d.push(n)}</script>
 </head>

Тогда:

 <body>
  <div id="thediv"></div>

  <script>
    $(function(){
       $('#thediv').html('thecode');
    });
  </script>

  <script src="http://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>

Тогда, наконец,

  <script>for(var f in $d){$d[f]();}</script>
 </body>
<html>

Или менее умная версия:

<script>var def=[];function defer(n){def.push(n)}</script>
<script>
defer(function(){
   $('#thediv').html('thecode');
});
</script>
<script src="http://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>
<script>for(var f in def){def[f]();}</script>

А в случае async вы можете выполнить push-функции при загрузке jquery.

<script async onload="for(var f in def){def[f]();}" 
src="jquery.min.js" type="text/javascript"></script>

В качестве альтернативы:

function loadscript(src, callback){
  var script = document.createElement('script');
  script.src = src
  script.async = true;
  script.onload = callback;
  document.body.appendChild(script);
};
loadscript("jquery.min", function(){for(var f in def){def[f]();}});

Ответ 13

Я обнаружил, что предлагаемое решение работает только при асинхронном коде. Вот версия, которая будет работать в любом случае:

document.addEventListener('DOMContentLoaded', function load() {
    if (!window.jQuery) return setTimeout(load, 50);
    //your synchronous or asynchronous jQuery-related code
}, false);