Как встроить виджет Javascript, который зависит от jQuery, в неизвестную среду - PullRequest
61 голосов
/ 31 января 2010

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

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

  2. Если на веб-странице есть jQuery, я обычно могу с ней работать. Однако, если версия jQuery старая, я бы хотел загрузить свою. Однако, если я загружаю свою собственную, мне нужно сделать это так, чтобы не топать их переменную $. Если я установлю jQuery.noConflict() и любой из их сценариев будет зависеть от $, то я просто сломаю их страницу.

  3. Если веб-страница использует другую библиотеку javascript (например, prototype), мне нужно было также быть чувствительным к переменной $ прототипа.

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

Ниже приведен основной скелет моего кода, включая ошибку синхронизации и иногда $ ошибки:

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

Мой виджет имеет следующую структуру:

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

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

Ответы [ 7 ]

97 голосов
/ 01 февраля 2010

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

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

Это загрузит jQuery, если он еще не загружен, и инкапсулирует его в обратный вызов, чтобы он не конфликтовал с уже существующим jQuery на странице. Он также проверяет, доступна ли минимальная версия, или загружает известную версию - в данном случае v1.3. Он отправляет логическое значение в обратный вызов (мой виджет) о том, был ли загружен jQuery в случае необходимости каких-либо триггеров. И только после загрузки jQuery он вызывает мой виджет, передавая ему jQuery.

5 голосов
/ 11 декабря 2011

См. Как создать веб-виджет (используя jQuery) . Автор 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
2 голосов
/ 20 мая 2011

Что делать, если вы также хотите использовать некоторые плагины jQuery? Безопасно ли создавать один файл с минимизированными версиями плагинов, а также загружать их, как показано ниже? (Загружен из S3, в этом конкретном примере.)

(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
});
1 голос
/ 31 января 2010

Можете ли вы использовать document.write (), чтобы по желанию добавить скрипт jQuery на страницу? Это должно заставить JQuery загружаться синхронно. Попробуйте это:

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

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

(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 голос
0 голосов
/ 05 декабря 2013

Я знаю, что это старая тема ... но я получил кое-что быстрее, чем твой взлом. Попробуйте в своем виджете

"init": function()

это исправит проблему

0 голосов
/ 31 января 2010

Я бы скачал исходный код jQuery и изменил бы объект jQuery на другой (jQueryCustom).

А затем найдите экземпляр, который устанавливает символ $ в качестве объекта jQuery, и прокомментируйте эту подпрограмму.

Я не знаю, насколько это легко или сложно, но я бы обязательно попробовал.

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

РЕДАКТИРОВАТЬ: Я только что проверил источник. Вам просто нужно заменить jQuery другой строкой (например, jQcustom). Затем попробуйте комментировать эту строку:

_$ = window.$

И вы делаете ссылку на пользовательский jQuery следующим образом:

jQcustom("#id").attr(...)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...