Как вставлять виджет Javascript, который зависит от jQuery в неизвестной среде
Я разрабатываю виджет javascript, который зависит от jQuery. Виджет может быть загружен или не загружен на страницу, на которой уже загружен jQuery. В этом случае есть много проблем...
-
Если на веб-странице нет jQuery, я должен загрузить свой собственный jQuery. Тем не менее, кажется, что есть тонкая проблема времени при выполнении этого. Например, если мой виджет загружается и выполняется до того, как jQuery завершит загрузку и выполнение, я получаю ошибку jQuery is not defined
.
-
Если веб-страница имеет jQuery, я обычно могу с ней работать. Однако, если версия jQuery устарела, я бы хотел загрузить свою собственную. Однако, если я загружаю свои собственные, мне нужно сделать это так, чтобы не топать в их переменной $
. Если я установил jQuery.noConflict()
, и любой из их сценариев зависит от $
, то я только что сломал их страницу.
-
Если веб-страница использует другую библиотеку javascript (например, прототип), мне также нужно быть чувствительным к прототипу $
.
Из-за всего вышеизложенного, кажется, легче не зависеть от 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);
Если есть какие-либо указатели или ресурсы для достижения виджета, который может работать во всех упомянутых средах, они будут очень признательны.
Ответы
Ответ 1
После просмотра некоторых ответов и указателей и поиска полезных хакеров 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 в него.
Ответ 2
Смотрите Как создать веб-виджет (используя 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
Ответ 3
Что делать, если вы также хотите использовать некоторые плагины 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
});
Ответ 4
ВИДЕТЬ Можно ли использовать несколько версий jQuery на одной странице?
Ответ 5
Можно ли использовать document.write(), чтобы добавить jQuery script на страницу? Это должно заставить 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 внутри вашего виджета script, то я считаю, что следующие действия кросс-браузер:
(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);
}
})()
Ответ 6
Я знаю, что это старая тема... но у меня есть что-то быстрее, чем ваш хак.
Попробуйте в своем виджетах
"init": function()
что устранит проблему
Ответ 7
Я бы загрузил источник jQuery и изменил объект jQuery на другой (jQueryCustom).
И затем найдите экземпляр, который устанавливает символ $
как объект jQuery и комментирует эту процедуру.
Я не знаю, насколько это было бы легко или сложно, но я бы наверняка попробовал.
(Кроме того, проверьте свой второй вариант, так как это неплохо, сайт, на котором будет выполняться виджет, может иметь версию jQuery старше той, которая вам нужна).
EDIT: Я только что проверил источник. Вам просто нужно заменить jQuery
на другую строку (например, jQcustom
). Затем попробуйте прокомментировать эту строку:
_$ = window.$
И вы делаете ссылку на пользовательский jQuery следующим образом:
jQcustom("#id").attr(...)