Jak osadzić widżet Javascript, który zależy od jQuery w nieznanym środowisku

Rozwijam widżet javascript, który zależy od jQuery. Widżet może zostać załadowany lub nie na stronę, na której jest już załadowany jQuery. Istnieje wiele problemów, które pojawiają się w tym przypadku...

  1. Jeśli strona nie ma jQuery, muszę załadować własny jQuery. Wydaje się jednak, że jest to delikatna kwestia czasu. Na przykład, jeśli mój widżet ładuje się i wykonuje przed zakończeniem ładowania i wykonywania jQuery, dostaję jQuery is not defined błąd.

  2. Jeśli strona ma jQuery, zazwyczaj mogę z nią pracować. Jeśli jednak wersja jQuery jest stara, chciałbym załadować własną. Jeśli jednak załaduję własną, muszę to zrobić w taki sposób, aby nie deptać ich zmiennej $. Jeśli ustawiłem jQuery.noConflict() i któryś z ich skryptów zależy od $, to właśnie złamałem ich stronę.

  3. Jeśli strona używa innej biblioteki javascript (np. prototype), musiałem być wrażliwy na zmienną $ prototype również.

Z powodu wszystkich powyższych, wydaje się, że łatwiej jest nie polegać na jQuery. Ale zanim pójdę w dół tej drogi, która będzie obejmować głównie przepisywanie mojego kodu widget, chciałem poprosić o radę pierwszy.

Podstawowy szkielet mojego kodu, w tym błąd pomiaru czasu i czasami błędy $, następuje:

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

Mój widget ma następującą strukturę:

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

Jeśli istnieją jakieś wskaźniki lub zasoby do osiągnięcia widżetu, który może działać we wszystkich wymienionych środowiska, byliby bardzo mile widziani.

Author: robhudson, 2010-01-31

7 answers

Po przejrzeniu kilku odpowiedzi i wskazówek i znalezieniu pomocnych hakerów jQuery, skończyłem z czymś takim:

(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
});

Spowoduje załadowanie jQuery, jeśli nie jest już załadowany i zamknie go w wywołaniu zwrotnym, aby nie był sprzeczny z istniejącym wcześniej jQuery na stronie. Sprawdza również, czy dostępna jest minimalna wersja lub wczytuje znaną wersję-w tym przypadku v1.3. Wysyła wartość logiczną do wywołania zwrotnego (mój widget), czy jQuery został załadowany, czy nie na wypadek, gdyby potrzebne były jakieś wyzwalacze. I dopiero po załadowaniu jQuery wywołuje mój widget, przekazując do niego jQuery.

 96
Author: robhudson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-28 19:03:57

Zobacz Jak zbudować widget www (używając jQuery) by 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
Author: Pavel Chuchuva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-11 00:54:03

Co zrobić, jeśli chcesz również użyć niektórych wtyczek jQuery? Czy można zrobić sobie pojedynczy plik z minifikowanymi wersjami wtyczek, a także załadować te, jak poniżej? (Załadowany z S3, w tym konkretnym przykładzie.)

(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
Author: cailinanne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-19 22:13:46
 1
Author: micahwittman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:30:50

Czy można użyć dokumentu.write() aby opcjonalnie dodać skrypt jQuery do strony? To powinno zmusić jQuery do synchronicznego ładowania. Spróbuj tego:

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

Jeśli chcesz zrobić jQuery sprawdzić wewnątrz skryptu widget następnie wierzę, że następujące działa 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
Author: Sean Hogan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-31 11:01:22

Wiem, że to stary temat... ale mam coś szybszego niż twój hack. Spróbuj w widgecie

"init": function()

To naprawi problem

 0
Author: Cristian Hernández,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-05 07:22:49

Pobrałbym źródło jQuery i zmodyfikował obiekt jQuery na inny (jQueryCustom).

A następnie znajdź instancję, która ustawia symbol {[2] } jako obiekt jQuery i skomentuj tę procedurę.

Nie wiem, czy to łatwe czy trudne, ale na pewno spróbuję.

(Sprawdź również drugą opcję, ponieważ nie jest źle, strona, na której będzie wykonywany widget, może mieć wersję jQuery starszą niż ta, której potrzebujesz).

EDIT: ja tylko sprawdziłem źródło. Wystarczy zastąpić jQuery innym ciągiem znaków (jQcustom na przykład). Następnie spróbuj skomentować ten wiersz:

_$ = window.$

I odwołujesz się do niestandardowego jQuery tak:

jQcustom("#id").attr(...)
 -1
Author: metrobalderas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-31 03:32:22