Использовать JavaScript для вставки ссылок на скрипты по мере необходимости? - PullRequest
12 голосов
/ 15 октября 2008

У меня есть функция JS, которая может иногда использоваться на некоторых страницах. Он зависит от другого файла JS (swfObject.js), но я бы хотел избежать повсеместного включения этого файла, так как в большинстве случаев это бесполезный запрос.

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

Я вполне уверен, что это возможно (и я не собираюсь использовать document.write), но прежде чем я отправлюсь на неизведанную территорию, кто-нибудь делал это раньше, и если да, то какие-нибудь указатели?

РЕДАКТИРОВАТЬ: Хорошо, я попробовал, и он работает в IE6 и FF, я еще не тестировал другие браузеры.

Вот мой код (версия 2.0, теперь с дополнительными обратными вызовами):

function loadJSInclude(scriptPath, callback)
{
    var scriptNode = document.createElement('SCRIPT');
    scriptNode.type = 'text/javascript';
    scriptNode.src = scriptPath;

    var headNode = document.getElementsByTagName('HEAD');
    if (headNode[0] != null)
        headNode[0].appendChild(scriptNode);

    if (callback != null)    
    {
        scriptNode.onreadystagechange = callback;            
        scriptNode.onload = callback;
    }
}

и в методе с зависимостью:

var callbackMethod = function ()
{
    // Code to do after loading swfObject
}

// Include SWFObject if its needed
if (typeof(SWFObject) == 'undefined')    
    loadJSInclude('/js/swfObject.js', callbackMethod);
else
    calbackMethod();

Есть предложения?

Ответы [ 6 ]

4 голосов
/ 15 октября 2008

Если вы используете инфраструктуру более высокого уровня, такую ​​как JQuery, вы можете проверить функцию $.getScript(url, callback).

3 голосов
/ 15 октября 2008

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

if (iNeedSomeMore){
  Script.load("myBigCodeLibrary.js");  // includes code for myFancyMethod();
  myFancyMethod();                     // cool, no need for callbacks!
}

Существует умный способ вставлять зависимости скрипта без необходимости обратных вызовов . Вам просто нужно извлечь скрипт через синхронный AJAX-запрос и проверить скрипт на глобальном уровне.

Если вы используете Prototype, метод Script.load выглядит следующим образом:

var Script = {
  _loadedScripts: [],
  include: function(script){
    // include script only once
    if (this._loadedScripts.include(script)){
      return false;
    }
    // request file synchronous
    var code = new Ajax.Request(script, {
      asynchronous: false, method: "GET",
      evalJS: false, evalJSON: false
    }).transport.responseText;
    // eval code on global level
    if (Prototype.Browser.IE) {
      window.execScript(code);
    } else if (Prototype.Browser.WebKit){
      $$("head").first().insert(Object.extend(
        new Element("script", {type: "text/javascript"}), {text: code}
      ));
    } else {
      window.eval(code);
    }
    // remember included script
    this._loadedScripts.push(script);
  }
};
0 голосов
/ 16 сентября 2013

Рассмотрите возможность использования require.js . Это может потребовать доработки вашей среды интерфейса, но оно того стоит. С помощью require вы можете просто сделать следующее в fileUsedOccasionally.js:

define(['swfObject', 'someOtherDependency'], function (swfObject, someOtherDependency) {
  // you can now use swfObject as a JS object! you can call it whatever you want
  // you'll have to write a swfObject.js to wrap it with require
  // but that's trivial
});
0 голосов
/ 12 апреля 2013

Я написал простой модуль, который автоматизирует работу по импорту / включению скриптов модуля в JavaScript. Попробуйте и, пожалуйста, оставьте отзыв! :) Для подробного объяснения кода обратитесь к этому сообщению в блоге: http://stamat.wordpress.com/2013/04/12/javascript-require-import-include-modules/

// ----- USAGE -----

require('ivar.util.string');
require('ivar.net.*');
require('ivar/util/array.js');
require('http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js');

ready(function(){
    //do something when required scripts are loaded
});

    //--------------------

var _rmod = _rmod || {}; //require module namespace
_rmod.LOADED = false;
_rmod.on_ready_fn_stack = [];
_rmod.libpath = '';
_rmod.imported = {};
_rmod.loading = {
    scripts: {},
    length: 0
};

_rmod.findScriptPath = function(script_name) {
    var script_elems = document.getElementsByTagName('script');
    for (var i = 0; i < script_elems.length; i++) {
        if (script_elems[i].src.endsWith(script_name)) {
            var href = window.location.href;
            href = href.substring(0, href.lastIndexOf('/'));
            var url = script_elems[i].src.substring(0, script_elems[i].length - script_name.length);
            return url.substring(href.length+1, url.length);
        }
    }
    return '';
};

_rmod.libpath = _rmod.findScriptPath('script.js'); //Path of your main script used to mark the root directory of your library, any library


_rmod.injectScript = function(script_name, uri, callback, prepare) {

    if(!prepare)
        prepare(script_name, uri);

    var script_elem = document.createElement('script');
    script_elem.type = 'text/javascript';
    script_elem.title = script_name;
    script_elem.src = uri;
    script_elem.async = true;
    script_elem.defer = false;

    if(!callback)
        script_elem.onload = function() {
            callback(script_name, uri);
        };

    document.getElementsByTagName('head')[0].appendChild(script_elem);
};

_rmod.requirePrepare = function(script_name, uri) {
    _rmod.loading.scripts[script_name] = uri;
    _rmod.loading.length++;
};

_rmod.requireCallback = function(script_name, uri) {
    _rmod.loading.length--;
    delete _rmod.loading.scripts[script_name];
    _rmod.imported[script_name] = uri;

    if(_rmod.loading.length == 0)
        _rmod.onReady();
};

_rmod.onReady = function() {
    if (!_rmod.LOADED) {
        for (var i = 0; i < _rmod.on_ready_fn_stack.length; i++){
            _rmod.on_ready_fn_stack[i]();
        });
        _rmod.LOADED = true;
    }
};

_.rmod = namespaceToUri = function(script_name, url) {
    var np = script_name.split('.');
    if (np.getLast() === '*') {
        np.pop();
        np.push('_all');
    }

    if(!url)
        url = '';

    script_name = np.join('.');
    return  url + np.join('/')+'.js';
};

//you can rename based on your liking. I chose require, but it can be called include or anything else that is easy for you to remember or write, except import because it is reserved for future use.
var require = function(script_name) {
    var uri = '';
    if (script_name.indexOf('/') > -1) {
        uri = script_name;
        var lastSlash = uri.lastIndexOf('/');
        script_name = uri.substring(lastSlash+1, uri.length);
    } else {
        uri = _rmod.namespaceToUri(script_name, ivar._private.libpath);
    }

    if (!_rmod.loading.scripts.hasOwnProperty(script_name) 
     && !_rmod.imported.hasOwnProperty(script_name)) {
        _rmod.injectScript(script_name, uri, 
            _rmod.requireCallback, 
                _rmod.requirePrepare);
    }
};

var ready = function(fn) {
    _rmod.on_ready_fn_stack.push(fn);
};
0 голосов
/ 24 сентября 2009

Ни один из этих методов, включая document.writing скрипт-тег, не работает, если в самом скрипте есть document.write.

0 голосов
/ 15 октября 2008

Оформить заказ на утилиту YUI Loader. Это супер удобный, ненавязчивый javascript для загрузки скриптов по требованию.

Вот ссылка на пример с использованием не-YUI-скриптов:

http://developer.yahoo.com/yui/examples/yuiloader/yl-addmodule.html

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