Use javascript to inject script references as needed?

后端 未结 6 816
终归单人心
终归单人心 2020-12-08 03:20

I have a JS function that may occasionally get used on some pages. It is dependent on another JS file (swfObject.js), but I\'d like to avoid having to include this file all

相关标签:
6条回答
  • 2020-12-08 03:52

    If you're using a higher level framework such as JQuery, you could check out the $.getScript(url, callback) function.

    0 讨论(0)
  • 2020-12-08 03:53

    None of these methods, including document.writing a script tag, work if the script itself has a document.write in it.

    0 讨论(0)
  • 2020-12-08 03:59

    If you want your code on the very next line and like to write something like:

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

    There is a smart way to inject script dependencies without the need of callbacks. You simply have to pull the script via a synchronous AJAX request and eval the script on global level.

    If you use Prototype the Script.load method looks like this:

    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 讨论(0)
  • 2020-12-08 04:01

    Checkout the YUI Loader utility. It's super handy, unobtrusive javascript for loading scripts on-demand.

    Here's a link to an example using non-YUI scripts:

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

    0 讨论(0)
  • 2020-12-08 04:03

    I wrote a simple module that automatizes the job of importing/including module scripts in JavaScript. Give it a try and please spare some feedback! :) For detailed explanation of the code refer to this blog post: 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 讨论(0)
  • 2020-12-08 04:05

    Consider using require.js. This might need some rework of your frontend framework, but it's totally worth it. With require, you could just do the following in your 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 讨论(0)
提交回复
热议问题