web-dev-qa-db-fra.com

Charger dynamiquement JS dans JS

J'ai une page Web dynamique dans laquelle j'ai besoin d'importer un fichier JS externe (sous une condition IF) dans un autre fichier javascript.

J'ai essayé de rechercher une solution réalisable, mais cela n'a pas fonctionné.

J'ai essayé de charger un fichier JS dans le DOM en utilisant document.createElement() mais cela ne fonctionnait pas non plus. Apparemment, le Js était chargé dans le DOM mais n'était pas accessible dans le fichier JS actuel.

La solution dans jQuery sera également satisfaisante

257
Riju Mahna

la $.getScript() de jQuery est parfois boguée, alors j'utilise ma propre implémentation comme:

jQuery.loadScript = function (url, callback) {
    jQuery.ajax({
        url: url,
        dataType: 'script',
        success: callback,
        async: true
    });
}

et l'utiliser comme:

if (typeof someObject == 'undefined') $.loadScript('url_to_someScript.js', function(){
    //Stuff to do after someScript has loaded
});
121
kayen

Mon hypothèse est que dans votre solution DOM uniquement, vous avez fait quelque chose comme:

var script = document.createElement('script');
script.src = something;
//do stuff with the script

Tout d’abord, cela ne fonctionnera pas car le script n’est pas ajouté à l’arborescence du document, il ne sera donc pas chargé. En outre, même lorsque vous le faites, l’exécution de javascript se poursuit pendant le chargement de l’autre script. Par conséquent, son contenu ne sera disponible que lorsque ce script sera entièrement chargé.

Vous pouvez écouter l'événement load du script et utiliser les résultats comme vous le feriez. Alors:

var script = document.createElement('script');
script.onload = function () {
    //do stuff with the script
};
script.src = something;

document.head.appendChild(script); //or something of the likes
459
Zirak

Je dois le faire fréquemment, donc je l'utilise:

var loadJS = function(url, implementationCode, location){
    //url is URL of external file, implementationCode is the code
    //to be called from the file, location is the location to 
    //insert the <script> element

    var scriptTag = document.createElement('script');
    scriptTag.src = url;

    scriptTag.onload = implementationCode;
    scriptTag.onreadystatechange = implementationCode;

    location.appendChild(scriptTag);
};
var yourCodeToBeCalled = function(){
//your code goes here
}
loadJS('yourcode.js', yourCodeToBeCalled, document.body);

Pour plus d'informations, voir ce site Comment puis-je inclure un fichier JavaScript dans un autre fichier JavaScript? , qui est la source de mon idée de fonction.

67
Anonymous JS Fan

Vous pouvez charger dynamiquement le js dans la page et non un autre fichier js

vous devez utiliser le getScript pour charger le fichier js

$.getScript("ajax/test.js", function(data, textStatus, jqxhr) {
console.log(data); //data returned
console.log(textStatus); //success
console.log(jqxhr.status); //200
console.log('Load was performed.');
});
21
muthu

Nécromanisme.

J'utilise cela pour charger des scripts dépendants;
cela fonctionne avec IE8 + sans ajouter de dépendance à une autre bibliothèque comme jQuery!

var cScriptLoader = (function ()
{
    function cScriptLoader(files)
    {
        var _this = this;
        this.log = function (t)
        {
            console.log("ScriptLoader: " + t);
        };
        this.withNoCache = function (filename)
        {
            if (filename.indexOf("?") === -1)
                filename += "?no_cache=" + new Date().getTime();
            else
                filename += "&no_cache=" + new Date().getTime();
            return filename;
        };
        this.loadStyle = function (filename)
        {
            // HTMLLinkElement
            var link = document.createElement("link");
            link.rel = "stylesheet";
            link.type = "text/css";
            link.href = _this.withNoCache(filename);
            _this.log('Loading style ' + filename);
            link.onload = function ()
            {
                _this.log('Loaded style "' + filename + '".');
            };
            link.onerror = function ()
            {
                _this.log('Error loading style "' + filename + '".');
            };
            _this.m_head.appendChild(link);
        };
        this.loadScript = function (i)
        {
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = _this.withNoCache(_this.m_js_files[i]);
            var loadNextScript = function ()
            {
                if (i + 1 < _this.m_js_files.length)
                {
                    _this.loadScript(i + 1);
                }
            };
            script.onload = function ()
            {
                _this.log('Loaded script "' + _this.m_js_files[i] + '".');
                loadNextScript();
            };
            script.onerror = function ()
            {
                _this.log('Error loading script "' + _this.m_js_files[i] + '".');
                loadNextScript();
            };
            _this.log('Loading script "' + _this.m_js_files[i] + '".');
            _this.m_head.appendChild(script);
        };
        this.loadFiles = function ()
        {
            // this.log(this.m_css_files);
            // this.log(this.m_js_files);
            for (var i = 0; i < _this.m_css_files.length; ++i)
                _this.loadStyle(_this.m_css_files[i]);
            _this.loadScript(0);
        };
        this.m_js_files = [];
        this.m_css_files = [];
        this.m_head = document.getElementsByTagName("head")[0];
        // this.m_head = document.head; // IE9+ only
        function endsWith(str, suffix)
        {
            if (str === null || suffix === null)
                return false;
            return str.indexOf(suffix, str.length - suffix.length) !== -1;
        }
        for (var i = 0; i < files.length; ++i)
        {
            if (endsWith(files[i], ".css"))
            {
                this.m_css_files.Push(files[i]);
            }
            else if (endsWith(files[i], ".js"))
            {
                this.m_js_files.Push(files[i]);
            }
            else
                this.log('Error unknown filetype "' + files[i] + '".');
        }
    }
    return cScriptLoader;
})();
var ScriptLoader = new cScriptLoader(["foo.css", "Scripts/Script4.js", "foobar.css", "Scripts/Script1.js", "Scripts/Script2.js", "Scripts/Script3.js"]);
ScriptLoader.loadFiles();

Si vous êtes intéressé par la version TypeScript - utilisée pour créer ceci:

class cScriptLoader {
    private m_js_files: string[];
    private m_css_files: string[];
    private m_head:HTMLHeadElement;

    private log = (t:any) =>
    {
        console.log("ScriptLoader: " + t);
    }


    constructor(files: string[]) {
        this.m_js_files = [];
        this.m_css_files = [];
        this.m_head = document.getElementsByTagName("head")[0];
        // this.m_head = document.head; // IE9+ only


        function endsWith(str:string, suffix:string):boolean 
        {
            if(str === null || suffix === null)
                return false;

            return str.indexOf(suffix, str.length - suffix.length) !== -1;
        }


        for(var i:number = 0; i < files.length; ++i) 
        {
            if(endsWith(files[i], ".css"))
            {
                this.m_css_files.Push(files[i]);
            }
            else if(endsWith(files[i], ".js"))
            {
                this.m_js_files.Push(files[i]);
            }
            else
                this.log('Error unknown filetype "' + files[i] +'".');
        }

    }


    public withNoCache = (filename:string):string =>
    {
        if(filename.indexOf("?") === -1)
            filename += "?no_cache=" + new Date().getTime();
        else
            filename += "&no_cache=" + new Date().getTime();

        return filename;    
    }


    public loadStyle = (filename:string) =>
    {
        // HTMLLinkElement
        var link = document.createElement("link");
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = this.withNoCache(filename);

        this.log('Loading style ' + filename);
        link.onload = () =>
        {
            this.log('Loaded style "' + filename + '".');

        };

        link.onerror = () =>
        {
            this.log('Error loading style "' + filename + '".');
        };

        this.m_head.appendChild(link);
    }


    public loadScript = (i:number) => 
    {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = this.withNoCache(this.m_js_files[i]);

        var loadNextScript = () => 
        {
            if (i + 1 < this.m_js_files.length)
            {
                this.loadScript(i + 1);
            }
        }

        script.onload = () =>
        {
            this.log('Loaded script "' + this.m_js_files[i] + '".');
            loadNextScript();
        };


        script.onerror = () =>
        {
            this.log('Error loading script "' + this.m_js_files[i] + '".');
            loadNextScript();
        };


        this.log('Loading script "' + this.m_js_files[i] + '".');
        this.m_head.appendChild(script);
    }

    public loadFiles = () => 
    {
        // this.log(this.m_css_files);
        // this.log(this.m_js_files);

        for(var i:number = 0; i < this.m_css_files.length; ++i)
            this.loadStyle(this.m_css_files[i])

        this.loadScript(0);
    }

}


var ScriptLoader = new cScriptLoader(["foo.css", "Scripts/Script4.js", "foobar.css", "Scripts/Script1.js", "Scripts/Script2.js", "Scripts/Script3.js"]);
ScriptLoader.loadFiles();

S'il s'agit de charger une liste dynamique de scripts, écrivez-les dans un attribut, tel que data-main, par exemple. <script src="scriptloader.js" data-main="file1.js,file2.js,file3.js,etc." ></script>
et faire une element.getAttribute("data-main").split(',')

tel que

var target = document.currentScript || (function() {
  var scripts = document.getElementsByTagName('script');
  // Note: this is for IE as IE doesn't support currentScript
  // this does not work if you have deferred loading with async
  // e.g. <script src="..." async="async" ></script>
  // https://web.archive.org/web/20180618155601/https://www.w3schools.com/TAgs/att_script_async.asp
  return scripts[scripts.length - 1];
})();

target.getAttribute("data-main").split(',')

pour obtenir la liste.

11
Stefan Steiger

La méthode jQuery.getScript() est un raccourci de la fonction Ajax (avec l'attribut dataType: $.ajax({ url: url,dataType: "script"}))

Si vous voulez que les scripts puissent être mis en cache, utilisez --- [RequireJS ) ou suivez l'exemple de jQuery pour étendre la méthode jQuery.getScript de la même manière.

jQuery.cachedScript = function( url, options ) {

  // Allow user to set any option except for dataType, cache, and url
  options = $.extend( options || {}, {
    dataType: "script",
    cache: true,
    url: url
  });

  // Use $.ajax() since it is more flexible than $.getScript
  // Return the jqXHR object so we can chain callbacks
  return jQuery.ajax( options );
};

// Usage
$.cachedScript( "ajax/test.js" ).done(function( script, textStatus ) {
  console.log( textStatus );
});

Référence: jQuery.getScript () | Documentation de l'API jQuery

7
Trent

Vous pouvez le faire en utilisant JQuery:

$.getScript("ajax/test.js", function(data, textStatus, jqxhr) {
  console.log(data); //data returned
  console.log(textStatus); //success
  console.log(jqxhr.status); //200
  console.log('Load was performed.');
});

ce lien devrait aider: http://api.jquery.com/jQuery.getScript/

4
Hazem Hagrass

Je recommande d'utiliser requirejs avec les fichiers de classe javascript d'AMD

bon exemple de comment l'utiliser ici

http://www.sitepoint.com/understanding-requirejs-for-effective-javascript-module-loading/

4
aqm

jQuery a $.getScript() :

Description : Chargez un fichier JavaScript à partir du serveur à l'aide d'une requête HTTP GET, puis exécutez-le.

3
Blender

Pour créer mon plugin, je devais charger des scripts et des styles externes dans un fichier JS, qui étaient tous prédéfinis. Pour ce faire, j'ai procédé comme suit:

    this.loadRequiredFiles = function (callback) {
        var scripts = ['xx.js', 'yy.js'];
        var styles = ['zz.css'];
        var filesloaded = 0;
        var filestoload = scripts.length + styles.length;
        for (var i = 0; i < scripts.length; i++) {
            log('Loading script ' + scripts[i]);
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = scripts[i];
            script.onload = function () {
                log('Loaded script');
                log(this);
                filesloaded++;  // (This means increment, i.e. add one)
                finishLoad();
            };
            document.head.appendChild(script);
        }
        for (var i = 0; i < styles.length; i++) {
            log('Loading style ' + styles[i]);
            var style = document.createElement('link');
            style.rel = 'stylesheet';
            style.href = styles[i];
            style.type = 'text/css';
            style.onload = function () {
                log('Loaded style');
                log(this);
                filesloaded++;
                finishLoad();
            };
            document.head.appendChild(style);
        }
        function finishLoad() {
            if (filesloaded === filestoload) {
                callback();
            }
        }
    };

Plus de script en contexte:

function myPlugin() {

    var opts = {
        verbose: false
    };                          ///< The options required to run this function
    var self = this;            ///< An alias to 'this' in case we're in jQuery                         ///< Constants required for this function to work

    this.getOptions = function() {
        return opts;
    };

    this.setOptions = function(options) {
        for (var x in options) {
            opts[x] = options[x];
        }
    };

    /**
     * @brief Load the required files for this plugin
     * @param {Function} callback A callback function to run when all files have been loaded
     */
    this.loadRequiredFiles = function (callback) {
        var scripts = ['xx.js', 'yy.js'];
        var styles = ['zz.css'];
        var filesloaded = 0;
        var filestoload = scripts.length + styles.length;
        for (var i = 0; i < scripts.length; i++) {
            log('Loading script ' + scripts[i]);
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = scripts[i];
            script.onload = function () {
                log('Loaded script');
                log(this);
                filesloaded++;
                finishLoad();
            };
            document.head.appendChild(script);
        }
        for (var i = 0; i < styles.length; i++) {
            log('Loading style ' + styles[i]);
            var style = document.createElement('link');
            style.rel = 'stylesheet';
            style.href = styles[i];
            style.type = 'text/css';
            style.onload = function () {
                log('Loaded style');
                log(this);
                filesloaded++;
                finishLoad();
            };
            document.head.appendChild(style);
        }
        function finishLoad() {
            if (filesloaded === filestoload) {
                callback();
            }
        }
    };

    /**
     * @brief Enable user-controlled logging within this function
     * @param {String} msg The message to log
     * @param {Boolean} force True to log message even if user has set logging to false
     */
    function log(msg, force) {
        if (opts.verbose || force) {
            console.log(msg);
        }
    }

    /**
     * @brief Initialise this function
     */
    this.init = function() {
        self.loadRequiredFiles(self.afterLoadRequiredFiles);
    };

    this.afterLoadRequiredFiles = function () {
        // Do stuff
    };

}
3
Luke Madhanga

Voici une petite librairie pour charger dynamiquement des fichiers javascript et CSS:

https://github.com/todotresde/javascript-loader

Je suppose qu’il est utile de charger les fichiers css et js dans l’ordre et de manière dynamique.

Prise en charge de l'extension pour charger n'importe quelle bibliothèque de votre choix, et pas seulement le fichier principal, vous pouvez l'utiliser pour charger des fichiers personnalisés.

C'EST À DIRE.:

<html>
<head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="scripts/javascript-loader.js" type="text/javascript" charset="utf-8" ></script>    
    <script type="text/javascript">
        $(function() {

            registerLib("threejs", test);

            function test(){
                console.log(THREE);
            }

            registerLib("tinymce", draw);

            function draw(){
                tinymce.init({selector:'textarea'});
            }

        }); 
    </script>
</head>
<body>
    <textarea>Your content here.</textarea>
</body>
0
todotresde

Si vous avez de nombreux fichiers avec des dépendances , utilisez AMD/RequireJS. http://requirejs.org/

0
aleksandr_hramcov

Vous pouvez utiliser la méthode $.getScript() de jQuery pour le faire, mais si vous voulez une fonctionnalité plus complète, yepnope.js est votre choix. Il prend en charge le chargement conditionnel des scripts et des feuilles de style et est facile à utiliser.

0
Licson