Динамическое подключение jQuery

С целью дальнейшего развития моего сервиса-скрипта Share42.com я искал способ динамического подключения фреймворка jQuery непосредственно в коде JavaScript.

Нашел красивое решение, которое выполняет одновременно 2 задачи:

  1. Проверяет, подключен ли уже на странице jQuery.
  2. Если не подключен, то подключает его с Гугла.

Таким образом, предотвращается двойная загрузка jQuery на странице, и, соответственно, экономится трафик, если jQuery на сайте уже подключен.

Код скрипта, который реализует вышесказанное, выглядит следующим образом:

var jQ = false;
function initJQ() {
	if (typeof(jQuery) == 'undefined') {
		if (!jQ) {
			jQ = true;
			document.write('<scr' + 'ipt type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></scr' + 'ipt>');
		}
		setTimeout('initJQ()', 50);
	} else {
		(function($) {
		$(function() {

			// здесь пишем jQuery код

		})
		})(jQuery)
	}
}
initJQ();

Благодаря этому скрипту, у меня теперь появилась возможность прикрутить к Share42.com функцию сокращения ссылки, которую просят пользователи, а также можно реализовать и вариант с плавающей панелью.

* * *

Профессиональное рекламное агентство полного цикла Промолидер предоставляет весь спектр рекламных услуг, связанных как с изготовлением рекламной продукции, так и непосредственной рекламой товаров и услуг.

Комментарии (58)

  1. aktuba
    2 декабря 2010 г. в 14:54

    Если не ошибаюсь, этот код с одного из постов хабра. Я тоже брал оттуда, но потом переделал под себя, чтобы можно было загружать не только js, но и css… Кстати, на themeforest.net видел отличную технику, когда js и css (например, плагины к jquery) подгружаются только тогда, когда они нужны.

    1. 2 декабря 2010 г. в 15:09 / ответ на коммент aktuba

      Нет, не с Хабра. Я подобные штуки, как правило, в зарубежном Инете ищу.

  2. marazmiki
    2 декабря 2010 г. в 15:07

    Может, лучше так?

    var getJQuery = function(){
        if (typeof(jQuery) == 'undefined') {
            var s = document.createElement('SCRIPT');
            s.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js';
            s.type = 'text/javascript';
            document.getElementsByTagName('HEAD')[0].appendChild(s);
        }
        return jQuery;
    }

    Потом в теле скрипта написать myJQuery = getJQuery(); и быть уверенным, что в переменной myJQuery (которую, кстати, можно и $ обозвать при желании) уже находится jQuery?

    1. 2 декабря 2010 г. в 18:01 / ответ на коммент marazmiki

      Я такой вариант пробовал, но у меня он не заработал. Видимо, не все правильно сделал. Если он короче варианта из моего поста, тогда можно будет использовать. Спасибо за комментарий.

    2. 3 декабря 2010 г. в 11:16 / ответ на коммент marazmiki

      Приведите, пожалуйста, пример непосредственно с jQuery кодом. У меня почему-то не работает.

  3. Evgeny Zhlobo
    2 декабря 2010 г. в 15:48

    А для чего используется такое разделение:

    <scr' + 'ipt
    1. 2 декабря 2010 г. в 18:06 / ответ на коммент Evgeny Zhlobo

      Так и думал, что кто-то об этом спросит =)

      Сказать точно “для чего” я не могу, т.к. в таких делах я не спец, но факт в том, что если так не разделять, то скрипт не сработает, и на экран выведется хтмл-код тега script.

      1. deleted
        3 декабря 2010 г. в 06:11 / ответ на коммент Dimox

        Все банально – если браузер наткнетса на … – то он так и распарсит. Несмотря на то что код находится внути скрипта.

        1. deleted
          3 декабря 2010 г. в 06:12 / ответ на коммент deleted

          форма съела

  4. 2 декабря 2010 г. в 16:20

    А вот не станет ли этот скрипт грузить jQuery повторно, если он уже есть в кэше браузера? По-моему, совершенно ненужный велосипед. Если ты изначально ставишь в link ссылку на гугловское хранилище фреймворка, оно лучше отработать должно. Хотя я не специалист, но размышления меня приводят к такому выводу.

    1. 2 декабря 2010 г. в 18:14 / ответ на коммент Тормоз

      А вот не станет ли этот скрипт грузить jQuery повторно, если он уже есть в кэше браузера?

      Не станет.

      По-моему, совершенно ненужный велосипед.

      Для тебя может и велосипед, а для меня – решение конкретной задачи.

      Если ты изначально ставишь в link ссылку на гугловское хранилище фреймворка, оно лучше отработать должно.

      Суть в том, что на чужом сайте подключается мой скрипт социальных сервисов, и я заранее не знаю, подключает ли jQuery владелец сайта. А вышеобозначенным скриптом как раз и проверю.

      1. 2 декабря 2010 г. в 18:16 / ответ на коммент Dimox

        Ясно теперь. Извини, сразу не понял суть задачи.

    2. 2 декабря 2010 г. в 18:39 / ответ на коммент Тормоз

      А вот не станет ли этот скрипт грузить jQuery повторно

      В нормальном браузере не станет, вроде. Браузер проверяет сначала саму ссылку, если она в кэше, затем время изменения файла и прочее, если все идентично кэшу, то файл по ссылке не грузится. Думаю сейчас уже все браузеры так работают. А вот если вреймворк на сайте уже подключен, причем не с гугл-хранилища, без такой проверки библиотека будет грузиться повторно.

      С другой стороны, если этот код вызван до того, как подключается jquery локально, то в любом случае библиотека будет загружена 2 раза, или я что-то не так понял?

      А еще, Дим зачем нужно такое пугающее зацикливание на каждые 50 миллисекунд: setTimeout(‘initJQ()’, 50);? Оно ведь, ко всему прочему, вроде, еще и бесконечное – опасный код какой-то (так он чего доброго браузер повесит), я его не тестировал, но выглядит опасно :)

      Мне кажется, было бы логично, если это вообще возможно, проверять наличие библиотеки jquery сразу после того как загружена head часть документа (ведь, библиотека вызывается почти всегда именно там). Если jquery не обнаружено, то подключать её. Но опять же, кажется, могут возникнуть глюки в разных браузерах.

      1. anStream
        2 декабря 2010 г. в 19:17 / ответ на коммент Kama

        если этот код вызван до того, как подключается jquery локально, то в любом случае библиотека будет загружена 2 раза, или я что-то не так понял?

        Верно, если этот код будет вызван ранее чужого и чужой не шарит подобной проверки :)

        Дим зачем нужно такое пугающее зацикливание на каждые 50 миллисекунд: setTimeout(’initJQ()’, 50);? Оно ведь, ко всему прочему, вроде, еще и бесконечное…

        Бесконечным оно действительно может быть, но не всегда, а только до момента загрузки и выполнения кода jQuery, но всётаки может – если нет доступа к хосту с сорсом или с неверным урлом к сорсу. Тем не менее, не должно вызвать особой нагрузки на браузер – простой if раз в 50мс – это несложно.

        1. 2 декабря 2010 г. в 20:09 / ответ на коммент anStream

          Бесконечным оно действительно может быть, но не всегда, а только до момента загрузки и выполнения кода jQuery,

          Ааа, точно! Но все равно чет не понятно, зачем зацикливать нужно.

      2. 2 декабря 2010 г. в 19:17 / ответ на коммент Kama

        С другой стороны, если этот код вызван до того, как подключается jquery локально, то в любом случае библиотека будет загружена 2 раза, или я что-то не так понял?

        Да, скорее всего так и есть.

        А еще, Дим зачем нужно такое пугающее зацикливание на каждые 50 миллисекунд: setTimeout(’initJQ()’, 50);?

        Ты думаешь, я в этом разбираюсь? =) То, что нашел в Инете, то и вставил.

  5. 2 декабря 2010 г. в 18:15

    Я вот если честно так и не понял, что хорошего в этом…

  6. 2 декабря 2010 г. в 18:44

    Дима, а в твоем случае, просто вот так разве не будет работать:

    function initJQ(){
      if (typeof(jQuery) == 'undefined')
          document.write('<scr' + 'ipt type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></scr' + 'ipt>');
    }
    initJQ();
    // здесь пишем jQuery код, который будет работать!
    
    1. 2 декабря 2010 г. в 19:19 / ответ на коммент Kama

      Завтра протестирую.

    2. deleted
      3 декабря 2010 г. в 06:14 / ответ на коммент Kama

      Не используйте document.write – это может плохо кончится :)

    3. 3 декабря 2010 г. в 11:12 / ответ на коммент Kama

      Проверил – не работает.

  7. Гость
    3 декабря 2010 г. в 08:16

    Не используйте document.write – это может плохо кончится :)

    И чем же?

    1. deleted
      3 декабря 2010 г. в 19:49 / ответ на коммент Гость

      Хотя бы тем что если вы вызовете этот скрипт динамически после загрузки страницы, то браузер заменит содержание страницы на содержимое из document.write

      1. 3 декабря 2010 г. в 19:53 / ответ на коммент deleted

        Не заменит, я проверял. Хоть я и ожидал, что заменит, но все в порядке. Пробовал ставить скрипт и в head, и в body.

        1. deleted
          3 декабря 2010 г. в 20:12 / ответ на коммент Dimox

          Dimox, смотрите ниже – любой вызов document.write после загрузки document приведет к обновлению страницы.

      2. deleted
        3 декабря 2010 г. в 19:55 / ответ на коммент deleted

        Чтобы было понятнее на примере jQuery (чтобы кода меньше):
        $(document).ready(function() {
        document.write(‘Auch!!’);
        });

        $(window).load(function() {
        document.write(‘Auch!’);
        });

  8. 3 декабря 2010 г. в 22:30

    А если у меня уже подключён MooTools, который так же использует доллар $ для получения объектов из DOM и тут твой скрипт поверх подгрузит jQuery?

    1. 3 декабря 2010 г. в 22:46 / ответ на коммент Rulexec

      Да. Скрипт же проверяет только наличие jQuery.

    2. detroit
      4 декабря 2010 г. в 18:54 / ответ на коммент Rulexec

      var $j = jQuery.noConflict();

      $j.function();

      разграничивает ваш скрипт от действий иных фреймворков – Мутулз не Мутулз

  9. detroit
    4 декабря 2010 г. в 18:50

    Смело можно заносить ваш код – вы меня простите – на сайт govnokod.ru – кто нибудь догадался проверить как загрузка вашего кода играет на скорость сайта, задержка в 50 мс в добавок.
    Меня всегда удивляло как гадкий код берется с одного левого сайта – где умельцы в кавычках стряпают их мегатоннами и потом такие же умельцы распространяют их повсеместо, в добавок надо сказать этот код не будет работать если на сайте есть еще фреймворки – допустим prototype.js – весь джеквери отпадет – jQuery.noConflict() не учтен – еще надо сказать что оптимально использовать window.onload для асинхронной загрузки скрипта что в разы увеличит скорость – без таймаутов.

    1. 4 декабря 2010 г. в 19:06 / ответ на коммент detroit

      Покажите тогда правильную реализацию.

      1. detroit
        4 декабря 2010 г. в 19:12 / ответ на коммент Dimox

        вот так будет выглядеть оптимальная по всем параметрам загрузка джеквери:

        (function() {

        var jQuery;

        if (window.jQuery === undefined || window.jQuery.fn.jquery !== '1.4.4') {
        var script_tag = document.createElement('script');
        script_tag.setAttribute("type","text/javascript");
        script_tag.setAttribute("src","jquery.min.js");
        script_tag.onload = scriptLoadHandler;
        script_tag.onreadystatechange = function () { // IE
        if (this.readyState == 'complete' || this.readyState == 'loaded') {
        scriptLoadHandler();
        }
        };

        (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);
        } else {
        // Версия jQuery которую мы загружаем для сайта единственна
        $ = window.jQuery;
        main();
        }

        /******** Запустить мгновенно после загрузки jQuery ******/
        function scriptLoadHandler() {
        // Восстановим $ и window.jQuery к первоначальному виду
        $ = window.jQuery.noConflict(true);
        // Главная функция
        main();
        }

        function main() {
        // Здесь наши jQuery дела
        }

        })();

        1. 4 декабря 2010 г. в 19:24 / ответ на коммент detroit

          Спасибо. Завтра потестирую.

        2. 5 декабря 2010 г. в 10:52 / ответ на коммент detroit

          Проверил, все замечательно. Большое спасибо! Значит не зря я пост писал =)

          1. deleted
            7 декабря 2010 г. в 05:59 / ответ на коммент Dimox

            Может и не зря и для себя что-то откроете, но вот пару моментов по скрипту выше:
            1) если вызов этого скрипта будет перед кодом для библиотек использующих $ в качестве глобальной переменной, то код перестанет работать, так как $ будет перезаписан на объект jQuery.
            2) при таком условии (при такой проверке) вы рискуете загрузить версию старше или новее чем уже имеется на сайте – что приведет к потенциальным проблемам
            3) где будет задействованна переменная var jQuery из начала скрипта?

            Скрипт на коленке похоже писался, а вы его для сервиса собираете использовать…

            1. 7 декабря 2010 г. в 17:37 / ответ на коммент deleted

              Может быть тогда предложите свой вариант, лишенный этих недостатков?

              1. deleted
                7 декабря 2010 г. в 20:51 / ответ на коммент Dimox

                Вот немного модифицированный пример. Должен работать в 98% случаев. Но мне кажется что вы себе неправильную задачу поставили. Зачем вам jquery?

                1. 8 декабря 2010 г. в 13:18 / ответ на коммент deleted

                  Вот немного модифицированный пример.

                  Глядя на размер скрипта что-то пропадает желание его использовать =)

                  Зачем вам jquery?

                  Чтобы реализовать функции, которые я не смогу сделать через нативный JavaScript, т.к. не разбираюсь в нем.

                  1. deleted
                    8 декабря 2010 г. в 17:38 / ответ на коммент Dimox

                    Скрипт всегда можно ужать.

                    1. Alex
                      8 декабря 2010 г. в 19:45 / ответ на коммент deleted

                      К сожалению, в IE скрипт спотыкается на каждом шагу… Кроме того, как насчет случаев, когда jQuery подключается в одном файле, нужная нам функция находится во внешнем файле, а вызывается в третьем (в нужном месте страницы)? (вариантов перенести все в одно место не предлагать)

                      1. deleted
                        8 декабря 2010 г. в 21:23 / ответ на коммент Alex

                        Вы правы, нужна другая реализация для ИЕ. Сегодня выложу другой вариант. Насчет случаев с подключениями то проблем быть не должно. Если в вашем случае не так пожалуйста проясните.

                      2. deleted
                        10 декабря 2010 г. в 20:23 / ответ на коммент Alex

                        UPD: Решение (если оно есть) откладывается на пару дней.

                    2. 8 декабря 2010 г. в 20:45 / ответ на коммент deleted

                      Да я знаю про это. Просто я ожидал, что задача решается совсем небольшим скриптом, а оказывается, что все гораздо сложнее.

                      1. deleted
                        12 декабря 2010 г. в 21:06 / ответ на коммент Dimox

                        А почему бы вам не предоставлять услуги в iframe?

  10. detroit
    4 декабря 2010 г. в 19:17

    засовываете в отдельный js файл после него можно подключать иные фреймворки без страха что они не смогут все вместе работать и все.
    по вопросам как работает код пишите отвечу всем – там все просто

  11. 5 декабря 2010 г. в 17:36

    Спасибо за статью. Давно хотел знать как правильно работать с квери

  12. 13 декабря 2010 г. в 11:17

    Dimox, немного в оффтоп (т.к. гостевой книги тут не нашел, куда ещё писать такой оффтоп незнаю) : твой блог на каком движке крутиться ? MaxSite ?

    1. 13 декабря 2010 г. в 13:33 / ответ на коммент GTAlex

      гостевой книги тут не нашел, куда ещё писать такой оффтоп незнаю

      Через форму обратной связи, вверху ссылка “Контакты”.

      твой блог на каком движке крутиться ? MaxSite ?

      Если бы ты заглянул в код страницы, то понял бы, что WordPress =)

  13. 13 декабря 2010 г. в 13:39

    ммда, нехило я затупил … даже стыдно стало

  14. 10 января 2011 г. в 15:02
    <script>!window.jQuery && document.write('<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"><\/script>');</script>
  15. 20 марта 2011 г. в 11:29

    У вас такой удобных блог, и столько инфы. Почему я раньше его не встречал?

    1. 20 марта 2011 г. в 11:53 / ответ на коммент Romacho

      Наверное, ходили не теми дорогами Интернета =)

  16. merfo
    23 марта 2011 г. в 18:06

    а что это за плгин на этом блоге для Подсветка кода? а то я себе искал нашол yntaxHighlighter Plus. Так там галимо то что когда хочеш скопировать код выделяеються и числа строк вместе с кодом…

    1. 24 марта 2011 г. в 10:48 / ответ на коммент merfo

Ваш комментарий

Жирный текст

Ссылка

Цитата

Внутристрочный код

CSS-код

HTML-код

JavaScript-код

PHP-код