130 votes

Comment faire en sorte que l'exécution de script attende que jquery soit chargé ?

J'ai un problème où la page se charge tellement vite que jquery n'a pas fini de se charger avant d'être appelé par un script ultérieur. Existe-t-il un moyen de vérifier l'existence de jquery et, s'il n'existe pas, d'attendre un moment puis de réessayer ?


En réponse aux réponses/commentaires ci-dessous, je mets en ligne une partie du balisage.

La situation... asp.net masterpage et childpage.

Dans la page principale, j'ai une référence à jquery. Ensuite, dans la page de contenu, j'ai une référence au script spécifique à la page. Lorsque le script spécifique à la page est chargé, il se plaint que "$ est indéfini".

J'ai placé des alertes à plusieurs endroits du balisage pour voir dans quel ordre les choses se déclenchaient, et j'ai confirmé qu'elles se déclenchaient dans cet ordre :

  1. En-tête de la page principale.
  2. Le bloc de contenu 1 de la page enfant (situé à l'intérieur du de la page maîtresse, mais après que les scripts de la page maîtresse sont appelés).
  3. Bloc de contenu de la page enfant 2.

Voici le balisage en haut de la page principale :

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

Ensuite, dans le corps de la page principale, il y a un ContentPlaceHolder supplémentaire :

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

Dans la page de l'enfant, cela se présente comme suit :

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

Voici le contenu du fichier "../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();
    });

});

3voto

mewc Points 184

Développons defer() de Dario pour être plus réutilisable.

function defer(toWaitFor, method) {
    if (window[toWaitFor]) {
        method();
    } else {
        setTimeout(function () { defer(toWaitFor, method) }, 50);
    }
}

qui est ensuite exécuté :

function waitFor() {
    defer('jQuery', () => {console.log('jq done')});
    defer('utag', () => {console.log('utag done')});
}

2voto

jmar777 Points 11681

Je ne pense pas que ce soit votre problème. Le chargement des script est synchrone par défaut, donc à moins que vous n'utilisiez l'option defer ou le chargement de jQuery lui-même via une autre requête AJAX, votre problème est probablement plus proche d'un 404. Pouvez-vous montrer vos balises, et nous faire savoir si vous voyez quelque chose de suspect dans firebug ou web inspector ?

2voto

Arnold Roa Points 563

Vérifier ceci :

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

Il créera un faux objet jQuery, qui vous permettra d'utiliser les méthodes onload de jquery, qui seront exécutées dès que jquery sera chargé.

Il n'est pas parfait.

// 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);

1voto

Richard J Points 826

Une note tangentielle sur les approches ici utilisées par les chargeurs setTimeout o setInterval . Dans ces cas-là, il est possible que lorsque votre contrôle s'exécute à nouveau, le DOM ait déjà été chargé, et que la fonction DOMContentLoaded aura été déclenché, de sorte que vous ne pouvez pas détecter cet événement de manière fiable en utilisant ces approches. Ce que j'ai découvert, c'est que la fonction ready fonctionne toujours, cependant, de sorte que vous pouvez incorporer votre habituelle

jQuery(document).ready(function ($) { ... }

à l'intérieur de votre setTimeout o setInterval et tout devrait fonctionner normalement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X