Загрузите jQuery в js, затем выполните скрипт, который зависит от него - PullRequest
4 голосов
/ 28 июня 2010

У меня есть уникальная проблема -

Я разрабатываю веб-приложение, которое создает виджеты, которые пользователь может затем встроить на свою страницу (в основном, в сообщения в блоге). Я хочу, чтобы им просто пришлось встраивать одну строку, поэтому я просто использовал эту строку для включения оператора, чтобы вытащить Javascript с моего сервера.

Проблема в том, что я создаю код виджета с использованием jQuery, и мне нужно загрузить плагин jQuery, поскольку я, очевидно, не знаю, будет ли он доступен для моих пользователей. Я подумал: «Это должно быть довольно просто» ....

function includeJavaScript(jsFile) {
  var script = document.createElement('script');
  script.src = jsFile;
  script.type = 'text/javascript';
  document.getElementsByTagName('head')[0].appendChild(script);
}

includeJavaScript('http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js');
jQuery();

Итак, я добавляю файл jQuery в заголовок, а затем пытаюсь запустить функцию jQuery. Проблема в том, что это не работает! Каждый раз, когда я запускаю его, я получаю сообщение об ошибке, что переменная jQuery не определена. Я попробовал несколько вещей. Я попытался поместить функции jQuery в триггер onLoad, чтобы вся страница (включая, предположительно, файл jQuery) загружалась до вызова моего скрипта. Я попытался поместить функцию jQuery в отдельный файл и загрузить ее после загрузки файла jQuery lib. Но я понимаю, что упускаю что-то простое - я новичок в jQuery, поэтому, если мне не хватает чего-то очевидного, я прошу прощения ...

EDIT

Хорошо, я попробовал предложение, предложенное digitalFresh, следующим образом (используя Safari 5, если это поможет), но я все еще получаю ту же ошибку?

function test() {
    jQuery()
}

var script = document.createElement("script");
script.type = "text/javascript";
script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js';
script.onload = test(); //execute
document.body.appendChild(script);

EDIT

Ладно, я НАКОНЕЦ заставил его сработать, по неосторожному предложению Брендана, поместив СЕБЕ вызов в обработчик 'onload', вот так:

function addLoadEvent(func) { 
      var oldonload = window.onload; 
      if (typeof window.onload != 'function') { 
        window.onload = func; 
      } else { 
        window.onload = function() { 
          if (oldonload) { 
            oldonload(); 
          } 
          func(); 
        } 
    } 
} 
addLoadEvent( function() {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js';
    document.body.appendChild(script);
    jQuery();
});

На данный момент, как вы видите, мне даже не нужно помещать его в «onload» - он просто работает. Хотя я должен признать, я все еще не понимаю, ПОЧЕМУ это работает, что беспокоит меня ...

Ответы [ 5 ]

7 голосов
/ 28 июня 2010

Решение, которое вы в конечном итоге используете, работает, но медленно запускается , а не 100% отказоустойчиво . Если кто-то переписывает window.onload, ваш код не запустится. Также window.onload происходит, когда загружается весь контент на странице (включая изображения), что не совсем то, что вы хотите. Вы не хотите, чтобы ваш сценарий ждал так долго.

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

function include(file, callback) {
  var head      = document.getElementsByTagName('head')[0];
  var script    = document.createElement('script');
  script.type   = 'text/javascript';
  script.src    = file;
  script.onload = script.onreadystatechange = function() {
    // execute dependent code
    if (callback) callback();
    // prevent memory leak in IE
    head.removeChild(script);
    script.onload = null;
  };
  head.appendChild(script);
}

include('http://ajax.googleapis.com/.../jquery.min.js', myFunction);

В этом случае функция будет вызываться именно тогда, когда доступна jquery. Ваш код защищен от сбоев и запускается быстро.

2 голосов
/ 28 июня 2010

Скрипт не загружается или не выполняется при вызове функции jQuery.Вот почему вы получаете сообщение об ошибке, что jQuery не определен.

Я ответил на эту проблему на Динамическая загрузка скриптов .Скрипт прост для всех браузеров, кроме IE.Просто добавьте прослушиватель события onload

1 голос
/ 13 ноября 2013

Если вы используете jQuery, вы можете использовать getScript () . У Facebook есть хороший пример того, как использовать это . Это более управляемое решение по сравнению с оригинальным, которое я разместил ниже.

В качестве альтернативы:

Основываясь на ответе галамбалаза, вы можете обернуть его функцию include() в событие, подобное jQuery $(document).ready(), чтобы создавать отложенные сценарии со строкой зависимости, не полагаясь на дополнительный плагин JS. Я также добавил callbackOnError, что удобно, если вы извлекаете данные из Google CDN.

/* galambalazs's include() */
function include(file, callback, callbackOnError) {
    var head      = document.getElementsByTagName('head')[0];
    var script    = document.createElement('script');
    script.type   = 'text/javascript';
    script.src    = file;
    script.onload = script.onreadystatechange = function() {
      // execute dependent code
      if (callback) callback();
      // prevent memory leak in IE
      head.removeChild(script);
      script.onload = null;
      script.onerror = null;
    };
    script.onerror = function() {
      if(callbackOnError) callbackOnError();
      // prevent memory leak in IE
      head.removeChild(script);
      script.onload = null;
      script.onerror = null;
    };
    head.appendChild(script);
 }

/* If you need a deferred inline script, this will work */
function init() {
    // Insert Code
}

/* Example with callback */
$(document).ready(function() {
    include('something.js', init);
});

/* Maybe I want something on window.load() */
$(window).load(function() {
    // Without a callback
    include('whatever.js');
});

/* Or use an event to load and initialize script when it's needed */
$(".nearAButton").hover(include('button.js',function() {initButtonJS()}));

function initButtonJS() {
    $(".nearAButton").off("mouseenter mouseleave");
}

/* Attempt to load Google Code, on fail load local */
include(
    '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js',
    function () {
        // Inline Callback
    },
    function () {
        include('/local/jquery-ui-1.10.3.custom.min.js', function () {
            // Inline Callback
        });
    }
);
1 голос
/ 28 июня 2010

Сначала вы должны убедиться, что они не используют jquery, например что-то вроде:

if (jQuery) {  
    // jQuery is loaded  
} else {
    // jQuery is not loaded
}

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

Затем для встраивания объявите эту функцию:

function load_script (url)
 {
   var xmlhttp;
   try {
     // Mozilla / Safari / IE7
     xmlhttp = new XMLHttpRequest();
    } catch (e) {
      //Other IE
      xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
    }
    xmlhttp.open('GET', url, false); x.send('');
    eval(xmlhttp.responseText);
    var s = xmlhttp.responseText.split(/\n/);
    var r = /^function\s*([a-z_]+)/i; 

      for (var i = 0; i < s.length; i++)
      {
          var m = r.exec(s[i]);
          if (m != null)
              window[m[1]] = eval(m[1]);
      }
  } 

Тогда назовите это:

load_script('http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js');

Надеюсь, это поможет.

1 голос
/ 28 июня 2010

Используйте LABjs .Встраивание тегов <script> работает, потому что браузер загружает и выполняет любой скрипт в нем или ссылается на него при просмотре любого из них, но это также означает, что браузер будет блокироваться, пока он не завершит работу со скриптом.

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