最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

jquery - Load JavaScript on demand after lightbox is displayed - Stack Overflow

programmeradmin5浏览0评论

There is a button on every page of my site. When the button is clicked, a lightbox appears. The content of the lightbox is a form that relies on several JavaScript files including Angular. Those JavaScript files are used only for the form and nowhere else on the site.

In order to reduce page load time, my goal is to load the JavaScript files only after the user clicks the button.

Is there a best practice way of doing this? Some options I can think of are:

  1. The content of the lightbox is an iframe and the sourced html document contains script tags.
  2. Use the jquery.getscript method (or similar) to load the scripts

Is there a better way?

There is a button on every page of my site. When the button is clicked, a lightbox appears. The content of the lightbox is a form that relies on several JavaScript files including Angular. Those JavaScript files are used only for the form and nowhere else on the site.

In order to reduce page load time, my goal is to load the JavaScript files only after the user clicks the button.

Is there a best practice way of doing this? Some options I can think of are:

  1. The content of the lightbox is an iframe and the sourced html document contains script tags.
  2. Use the jquery.getscript method (or similar) to load the scripts

Is there a better way?

Share Improve this question edited Sep 28, 2016 at 14:58 4444 3,68010 gold badges34 silver badges46 bronze badges asked Sep 15, 2016 at 16:58 edtedt 22.4k33 gold badges85 silver badges119 bronze badges 4
  • have you tried those options? Are these scripts running in the iframe? If so not sure why they aren't just included in the page that loads in iframe. Problem really isn't clear – charlietfl Commented Sep 15, 2016 at 17:51
  • I tried option 2 with no success. Angular does not replace the tokens in the DOM. I'm trying to avoid option 1 if possible because using an iframe will add a lot setup work in order to create the sourced page for the iframe. – edt Commented Sep 21, 2016 at 16:46
  • there's a module for angular that load your JS, HTML or CSS according what you want. check here – Paulo Galdo Sandoval Commented Sep 21, 2016 at 16:49
  • Sounds great Paulo. When using that module, is there a good way to lazy load angular itself? – edt Commented Sep 21, 2016 at 16:55
Add a ment  | 

7 Answers 7

Reset to default 12 +200

By understanding your question, You want to lazy-load your js/css/html . You can achieve this using two plugins

Require.js

Pros :

  1. Explicit dependencies between modules, listed in code.
  2. Asynchronous module loading.
  3. Lazy (on-demand) module loading.
  4. Support for one of the standard module wrappers (AMD), a lot of munity modules implement it, so your modules can depend on them.

Cons :

  1. We can't inject the AngularJS modules on the fly. This loads files only when needed i.e. RequireJS only loads javascript files but it doesn't register the new angular modules and ponents in this new code

OcLazyLoad

Pros :

  1. OcLazyLoad is used to load the dependency files and also to inject the AngularJS modules on the fly.
  2. Loading Js and Css files are effortless.

Cons :

  1. We can't maintain the dependency files structure.

So you can use Require.js to load dependencies between modules listed in code and OcLazyLoad to inject Angular module on fly . And for your question regarding angular itself on fly, I don't think you can do that in this case.

Create script tag and attach script src and append it to head using javascript as below.

var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', 'test.js');
document.head.appendChild(script);

Another way is to load js file using jquery ajax call like below.

$.ajax({
    url: "test.js",
    dataType: "script",
    cache: true,
    success: function() {
        //Execute the function which you want...
    }
});

Depending on your project's architecture and whether you are using/want to use a library like require.js could help.

You can use it to require in the necessary modules for the lightbox.

The benefit of it in contrast to just dynamically loading a bunch of scripts, is that you will be able to manage dependencies between dynamically loading scripts and ensure they execute in a specific order if you need to (now or in the future).

Another idea could be to call an ajax function on the click of the button that would return an html partial, containing the lightbox scripts that you would then append to the document so the scripts would again load dynamically.

here is an example of how you achieve, I have implemented something similar on my websites and external JS are loaded only when required

<script type='text/javascript'>
$(elem).click(function() {
var d= document;
var id = 'ext-js';
if (d.getElementById(id)) return;
var t = d.createElement('script');
t.type = 'text/javascript';
t.src = '//path to external js';
t.id = id;
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(t);
});
</script>

The code also checks if the script is already loaded so it doesn't try to load with every click, you can easily scale to load multiple scripts, just give each script a different id and copy paste the below section for as many scripts you require.

var t = d.createElement('script');
t.type = 'text/javascript';
t.src = '//path to external js';
t.id = id;
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(t);

I hope this helps

Option 2 (dynamically loading scripts) is a good way to go - you probably just need to bootstrap angularjs correctly once it's been loaded. A quick demo:

(function() {
  "use strict";

  var angularLoaded = false;

  window.lazyLoadAngular = function() {
    if (angularLoaded) {
      return;
    }

    angularLoaded = true;

    var angularScript = document.createElement("script");
    angularScript.src = "//ajax.googleapis./ajax/libs/angularjs/1.5.8/angular.min.js";
    document.body.appendChild(angularScript);
    angularScript.onload = function() {
      var angular = window.angular,
      angularContent = document.querySelector('.angularContent');

      // reveal angular content
      angularContent.style.display = "block";

      // in practice, you're probably dynamically loading your angular app scripts as well... but here we'll just create it once angular is available
      createAngularApp();
      
      // bootstrap angular on the content
      angular.bootstrap(angularContent, ["myApp"]);
    };
  };


  function createAngularApp() {
    var angular = window.angular;
    angular.module("myApp", [])
    .controller("MyCtrl", ["$scope", MyCtrl]);
    
    function MyCtrl($scope) {
      $scope.isAngularWorking = "Yes it is!";
    }
  }

})();
.angularContent {
  display: none;
}
<button onclick="lazyLoadAngular()">Lazy load Angular</button>

<div class="angularContent">
  <div ng-controller="MyCtrl">
    Angular is working: {{isAngularWorking}}
  </div>
</div>

You can use SystemJs, Universal dynamic module loader - loads ES6 modules, AMD, CommonJS and global scripts in the browser and NodeJS, I think is very powerful engine.

For the dynamic script loading of the browser,you can use load-script package.

  • require('load-script') returns a function of the following interface: function(url[, opts][, cb]) {}
  • load-script appends a script node to the <head> element in the dom.

    Example

      var load = require('load-script')
    
      load('foo.js', function (err, script) {
      if (err) {
                // print useful message 
      }
      else {
            console.log(script.src);// Prints 'foo'.js' 
            // use script 
            // note that in IE8 and below loading error wouldn't be reported 
                }
           })
    

Alternatively you can bine the elements with the DOM

Example

 <script type="application/javascript">
   function loadJS(file) {
     // DOM: Create the script element
     var jsElement = document.createElement("script");
     // set the type attribute
     jsElement.type = "application/javascript";
     // make the script element load file
     jsElement.src = file;
     // finally insert the element to the body element in order to load the script
     document.body.appendChild(jsElement);
   }
 </script>

   <button onclick="loadJS('jsFile1.js');">Load jsFile1.js</button>
   <button onclick="loadJS('jsFile2.js');">Load jsFile2.js</button>
发布评论

评论列表(0)

  1. 暂无评论