Как встроить виджет 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);
если таковые имеются указатели или ресурсы для достижения виджета, который может работать во всех упомянутых средах, они были бы весьма признательны.
7 ответов:
после просмотра некоторых ответов и указателей и поиска некоторых полезных хакеров 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.
посмотреть Как построить веб-виджет (с помощью jQuery) Алекс Марандон.
(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
Что делать, если вы также хотите использовать некоторые плагины 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 });
вы можете использовать документ.написать (), чтобы дополнительно добавить скрипт 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); } })()
Я знаю, что это старая тема... но у меня есть кое-что быстрее, чем твой Хак. Попробуйте в вашем виджете
"init": function()
это исправит проблему
Я бы загрузил источник jQuery и изменил объект jQuery на другой (jQueryCustom).
а затем найти экземпляр, который устанавливает
$
символ как объект jQuery и прокомментируйте эту процедуру.Я не знаю, насколько легко или трудно это может быть, но я бы, конечно, дать ему попробовать.
(кроме того, проверьте свой второй вариант, так как это неплохо, сайт, на котором будет выполняться виджет, может иметь версию jQuery старше той, которую вы потребность.)
EDIT: я только что проверил источник. Вы просто должны заменить
jQuery
С другой строкой (jQcustom
например). Затем попробуйте прокомментировать эту строку:_$ = window.$
и вы ссылаетесь на пользовательский jQuery следующим образом:
jQcustom("#id").attr(...)