Comment intégrer le widget Javascript qui dépend de jQuery dans un environnement inconnu

je développe un widget javascript qui dépend de jQuery. Le widget peut ou non être chargé sur une page qui a déjà chargé jQuery. Il y a beaucoup de problèmes qui surgissent dans ce cas...

  1. si la page web n'a pas de jQuery, je dois charger mon propre jQuery. Il semble y avoir un délicat problème de synchronisation quand faire cela, cependant. Par exemple, si mon widget charge et exécute avant que jQuery ne finisse de charger et d'exécuter, je reçois une erreur jQuery is not defined .

  2. si la page web a jQuery, je peux habituellement travailler avec elle. Si la version jQuery est ancienne, cependant, je voudrais charger la mienne. Si je charge le mien, cependant, je dois le faire de manière à ne pas piétiner sur leur variable $ . Si je mets jQuery.noConflict() et que l'un de leurs scripts dépend de $ , alors je viens de casser leur page.

  3. si la page Web utilise une autre bibliothèque javascript (par exemple prototype), j'avais besoin d'être sensible à la variable $ de prototype aussi.

à cause de tout ce qui précède, il semble plus facile de ne pas dépendre de jQuery. Mais avant d'aller dans cette voie, qui impliquera surtout de réécrire mon code widget, je voulais d'abord demander conseil.

le squelette de base de mon code, y compris le bogue temporisateur et parfois les bogues $ , suit:

<script type="text/javascript" charset="utf-8">
// <![CDATA
 if (typeof jQuery === 'undefined') {
  var head = document.getElementsByTagName('head')[0];
  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.src = '{{ URL }}/jquery.js';
  head.appendChild(script);
 }
// ]]>
</script>
<script type="text/javascript" src="{{ URL }}/widget.js"></script>

mon widget a la structure suivante:

(function($) {
 var mywidget = {
  init: function() {
   ...
  }
 };
 $(document).ready(function() {
   mywidget.init();
 });
})(jQuery);

S'il y a des pointeurs ou des ressources pour réaliser un widget qui peut fonctionner dans tous les environnements mentionnés, ils seraient grandement appréciés.

60
demandé sur robhudson 2010-01-31 06:22:32

7 réponses

après avoir passé en revue quelques réponses et conseils, et trouvé quelques hackers jQuery utiles, j'ai fini par quelque chose comme ceci:

(function(window, document, version, callback) {
    var j, d;
    var loaded = false;
    if (!(j = window.jQuery) || version > j.fn.jquery || callback(j, loaded)) {
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.src = "/media/jquery.js";
        script.onload = script.onreadystatechange = function() {
            if (!loaded && (!(d = this.readyState) || d == "loaded" || d == "complete")) {
                callback((j = window.jQuery).noConflict(1), loaded = true);
                j(script).remove();
            }
        };
        (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script);
    }
})(window, document, "1.3", function($, jquery_loaded) {
    // Widget code here
});

cela chargera jQuery s'il n'est pas déjà chargé et l'encapsule dans le callback afin qu'il n'entre pas en conflit avec un jQuery préexistant sur la page. Il vérifie également qu'une version minimale est disponible ou charge une version connue -- dans ce cas, v1.3. Il envoie une valeur booléenne à la callback (mon widget) sur si oui ou non jQuery a été chargé dans le cas où il ya des déclencheurs nécessaires pour être fait. Et ce n'est qu'après que jQuery est chargé qu'il appelle mon widget, passant jQuery dedans.

96
répondu robhudson 2013-08-28 19:03:57

Voir Comment créer un widget web (à l'aide de jQuery) par Alex Marandon.

(function() {

// Localize jQuery variable
var jQuery;

/******** Load jQuery if not present *********/
if (window.jQuery === undefined || window.jQuery.fn.jquery !== '1.4.2') {
    var script_tag = document.createElement('script');
    script_tag.setAttribute("type","text/javascript");
    script_tag.setAttribute("src",
        "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js");
    if (script_tag.readyState) {
      script_tag.onreadystatechange = function () { // For old versions of IE
          if (this.readyState == 'complete' || this.readyState == 'loaded') {
              scriptLoadHandler();
          }
      };
    } else { // Other browsers
      script_tag.onload = scriptLoadHandler;
    }
    // Try to find the head, otherwise default to the documentElement
    (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);
} else {
    // The jQuery version on the window is the one we want to use
    jQuery = window.jQuery;
    main();
}

/******** Called once jQuery has loaded ******/
function scriptLoadHandler() {
    // Restore $ and window.jQuery to their previous values and store the
    // new jQuery in our local jQuery variable
    jQuery = window.jQuery.noConflict(true);
    // Call our main function
    main(); 
}

/******** Our main function ********/
function main() { 
    jQuery(document).ready(function($) { 
        // We can use jQuery 1.4.2 here
    });
}

})(); // We call our anonymous function immediately
5
répondu Pavel Chuchuva 2011-12-11 00:54:03

et si vous voulez aussi utiliser des plugins jQuery? Est-il sûr de faire un seul fichier avec les versions miniaturisées des plugins, et aussi de les charger, comme ci-dessous? (Chargé à partir de S3, dans cet exemple particulier.)

(function(window, document, version, callback) {
  var j, d;
  var loaded = false;
  if (!(j = window.jQuery) || version > j.fn.jquery || callback(j, loaded)) {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = "http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js";
    script.onload = script.onreadystatechange = function() {
        if (!loaded && (!(d = this.readyState) || d == "loaded" || d == "complete")) {
            window.jQuery.getScript('http://mydomain.s3.amazonaws.com/assets/jquery-plugins.js', function() {
              callback((j = window.jQuery).noConflict(1), loaded = true);
              j(script).remove();
            });
        }
    };
    document.documentElement.childNodes[0].appendChild(script)
  }
})(window, document, "1.5.2", function($, jquery_loaded) {
  // widget code goes here
});
2
répondu cailinanne 2011-05-19 22:13:46

pouvez-vous utiliser le document.write() pour éventuellement ajouter le script jQuery pour la page? Ça devrait forcer jQuery à se charger en même temps. Essayez ceci:

<script type="text/javascript" charset="utf-8">
// <![CDATA
 if (typeof jQuery === 'undefined') {
  document.write('<script src="{{ URL }}/jquery.js"><' + '/script>');
 }
// ]]>
</script>
<script type="text/javascript" src="{{ URL }}/widget.js"></script>

si vous voulez faire le jquery vérifier à l'intérieur de votre script widget alors je crois que les travaux suivants cross-browser:

(function() {
 function your_call($) {
  // your widget code goes here
 }
 if (typeof jQuery !== 'undefined') your_call(jQuery);
 else {
  var head = document.getElementsByTagName('head')[0];
  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.src = '{{ URL }}/jquery.js';
  var onload = function() {
   if (!script.readyState || script.readyState === "complete") your_call(jQuery);
  }
  if ("onreadystatechange" in script) script.onreadystatechange = onload;
  else script.onload = onload;
  head.appendChild(script);
 }
})()
1
répondu Sean Hogan 2010-01-31 11:01:22

je sais que c'est un vieux sujet... mais j'ai quelque chose de plus rapide que ton piratage. Essayez votre widget

"init": function()

qui va résoudre le problème

0
répondu Cristian Hernández 2013-12-05 07:22:49

je vais télécharger la source jQuery et modifier l'objet jQuery à un autre (jQueryCustom).

et ensuite trouver l'instance qui définit le symbole $ comme un objet jQuery et commenter cette routine.

Je ne sais pas si c'est facile ou difficile, mais j'essaierais.

(aussi, cochez votre deuxième option, car il n'est pas mauvais, le site où le widget sera exécuté, pourrait avoir une version jQuery plus vieux que celui dont vous avez besoin).

EDIT: je viens de vérifier la source. Il suffit de remplacer jQuery par une autre chaîne ( jQcustom par exemple). Puis, essayez de commenter cette ligne:

_$ = window.$

et vous faites référence à la coutume jQuery comme ceci:

jQcustom("#id").attr(...)
-1
répondu metrobalderas 2010-01-31 03:32:22