Подтвердить что ты не робот

Использовать javascript для ввода ссылок script по мере необходимости?

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

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

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

EDIT: Хорошо, я попробовал, и он работает в IE6 и FF, я еще не тестировал другие браузеры.

Вот мой код (Rev 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();

Любые предложения?

4b9b3361

Ответ 1

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

Ответ 2

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

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

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

Если вы используете 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);
  }
};

Ответ 3

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

Здесь ссылка на пример с использованием сценариев, отличных от YUI:

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

Ответ 4

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

Ответ 5

Я написал простой модуль, который автоматизирует работу по импорту/включая скрипты модулей в 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);
};

Ответ 6

Рассмотрите возможность использования require.js. Это может потребовать некоторой переделки вашей инфраструктуры frontend, но это того стоит. При необходимости вы можете просто сделать следующее в 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 trivial
});