Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/407.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 更改状态时角度组件脚本的延迟加载_Javascript_Angularjs_Angular Ui Router - Fatal编程技术网

Javascript 更改状态时角度组件脚本的延迟加载

Javascript 更改状态时角度组件脚本的延迟加载,javascript,angularjs,angular-ui-router,Javascript,Angularjs,Angular Ui Router,这个问题已经持续了大约一天了 我一直试图让我的AngularJS应用程序惰性地加载每个州组件的脚本文件。我正在Angular的一个大型项目中工作,index.html文件已经变形为100多个标记,包括各种控制器、服务和库的JS。它们大多数都很小,所以装载时间并不是一个大问题(虽然可能是),但在我看来从来都不干净 可能是因为我已经习惯了PHP的autoloader,或者只是被所有可以在编译时加载自己依赖项的语言所破坏。必须在应用程序的根文档中加载一些次要的边缘状态指令的脚本,或者如果指令被移动到另

这个问题已经持续了大约一天了

我一直试图让我的AngularJS应用程序惰性地加载每个州组件的脚本文件。我正在Angular的一个大型项目中工作,
index.html
文件已经变形为100多个
标记,包括各种控制器、服务和库的JS。它们大多数都很小,所以装载时间并不是一个大问题(虽然可能是),但在我看来从来都不干净

可能是因为我已经习惯了PHP的autoloader,或者只是被所有可以在编译时加载自己依赖项的语言所破坏。必须在应用程序的根文档中加载一些次要的边缘状态指令的脚本,或者如果指令被移动到另一个没有
列表的应用程序中,该指令实际上所属的模块不加载脚本本身,这不是模块化的

不管怎样,我正在启动一个新项目,希望它更干净,但以这种方式将组件加载到Angular中会带来许多挑战。在文档或一些博客文章中,有很多问题曾经被提到过,所以我提出了一个问题,但我还没有看到一个端到端的解决方案能够与其他角度组件干净地集成

  • 如果呈现页面时Angular和模块已加载,则Angular仅引导
    ng app
    指令。即使使用延迟加载启动应用程序,也需要一种变通方法
  • 模块API的方法仅在应用程序启动之前有效。在应用程序启动后,但在定义新控制器、指令、过滤器或服务的脚本实际加载后(以及在实际需要时),注册新控制器、指令、过滤器或服务需要一种变通方法
  • 延迟加载脚本和调用基于AJAX的服务都需要调用回调,将服务调用的结果注入状态控制器需要在状态转换开始时调用实际存在的服务。实际上,调用一个延迟加载的服务并在状态改变之前解决它……需要一个变通方法
  • 所有这些都需要以一种不显得笨拙的方式组合在一起,并且可以轻松地在多个应用程序中重用,而无需每次都重新发明轮子
  • 我已经看到了1和2的答案。显然,可用于在加载整个页面后启动模块,而无需
    ng app
    指令。在引导后添加组件不太明显,但是。解决#3并以满足#4的方式完成这一切的难度更大

    上述解决#2的示例适用于控制器和指令。事实证明,添加服务要复杂一点,异步的,延迟加载的,并且意味着向延迟加载的控制器提供数据,尤其是这样。关于Isitor先生,他的代码当然适用于注册控制器作为概念证明,但代码的编写方式并不能轻松扩展到延迟加载脚本有意义的应用程序类型,即包含数十到数百个包含项、依赖项和异步服务的大得多的应用程序


    我将发布我提出的解决方案,但是如果有人有改进的建议,或者已经找到了一种截然不同的更好的方法,请随意添加。

    以下是角度模块的代码
    lazy
    ,具体取决于
    ui.router
    模块。当它包含在模块的依赖项中时,将启用状态脚本的延迟加载功能。我已经包括了主要应用程序模块的示例、一些惰性组件和我的
    index.html
    ,为了演示目的进行了清理。我正在使用库来实际处理脚本加载

    angular ui router lazy.js

    /**
     * Defines an AngularJS module 'lazy' which depends on and extends the ui-router
     * module to lazy-load scripts specified in the 'scripts' attribute of a state
     * definition object.  This is accomplished by registering a $stateChangeStart
     * event listener with the $rootScope, interrupting the associated state change
     * to invoke the included $scriptService which returns a promise that restarts the
     * previous state transition upon resolution.  The promise resolves when the
     * extended Script.js script loader finishes loading and inserting a new <script>
     * tag into the DOM.
     *
     * Modules using 'lazy' to lazy-load controllers and services should call lazy.makeLazy
     * on themselves to update the module API to inject references for the various $providers 
     * as the original methods are only useful before bootstrapping, during configuration,
     * when references to the $providers are in scope.  lazy.makeLazy will overwrite the
     * module.config functions to save these references so they are available at runtime,
     * after module bootstrapping.
     * See http://ify.io/lazy-loading-in-angularjs/ for additional details on this concept
     *
     * Calls to $stateProvider.state should include a 'scripts' property in the object
     * parameter containing an object with properties 'controllers', 'directives', 'services',
     * 'factories', and 'js', each containing an array of URLs to JS files defining these
     * component types, with other miscelleneous scripts described in the 'js' array.
     * These scripts will all be loaded in parallel and executed in an undefined order
     * when a state transition to the specified state is started.  All scripts will have
     * been loaded and executed before the 'resolve' property's promises are deferred,
     * meaning services described in 'scripts' can be injected into functions in 'resolve'.
     */
    
     (function() {
        // Instantiate the module, include the ui.router module for state functionality
        var lazy = angular.module('lazy',['ui.router']);
    
        /**
         * Hacking Angular to save references to $providers during module configuration.
         * 
         * The $providers are necessary to register components, but they use a private injector
         * only available during bootstrap when running config blocks.  The methods attached to the
         * Vanilla AngularJS modules rely on the same config queue, they don't actually run after the
         * module is bootstrapped or save any references to the providers in this injector.
         * In makeLazy, these methods are overwritten with methods referencing the dependencies
         * injected at configuration through their run context.  This allows them to access the
         * $providers and run the appropriate methods on demand even after the module has been
         * bootstrapped and the $providers injector and its references are no longer available.
         *
         * @param module      An AngularJS module resulting from an angular.module call.
         * @returns module    The same module with the provider convenience methods updated
         * to include the DI $provider references in their run context and to execute the $provider
         * call immediately rather than adding calls to a queue that will never again be invoked.
         */
        lazy.makeLazy = function(module) {
          // The providers can be injected into 'config' function blocks, so define a new one
          module.config(function($compileProvider,$filterProvider,$controllerProvider,$provide) {
            /**
             * Factory method for generating functions to call the appropriate $provider's
             * registration function, registering a provider under a given name.
             * 
             * @param registrationMethod    $provider registration method to call
             * @returns function            A function(name,constructor) calling
             * registationMethod(name,constructor) with those parameters and returning the module.
             */
            var register = function(registrationMethod) {
              /**
               * Function calls registrationMethod against its parameters and returns the module.
               * Analogous to the original module.config methods but with the DI references already saved.
               *
               * @param name          Name of the provider to register
               * @param constructor   Constructor for the provider
               * @returns module      The AngularJS module owning the providers
               */
              return function(name,constructor) {
                // Register the provider
                registrationMethod(name,constructor);
                // Return the module
                return module;
              };
            };
    
            // Overwrite the old methods with DI referencing methods from the factory
            // @TODO: Should probably derive a LazyModule from a module prototype and return
            // that for the sake of not overwriting native AngularJS code, but the old methods
            // don't work after `bootstrap` so they're not necessary anymore anyway.
            module.directive = register($compileProvider.directive);
            module.filter = register($filterProvider.register);
            module.controller = register($controllerProvider.register);
            module.provider = register($provide.provider);
            module.service = register($provide.service);
            module.factory = register($provide.factory);
            module.value = register($provide.value);
            module.constant = register($provide.constant);
          });
          // Return the module
          return module;
        };
    
        /**
         * Define the lazy module's star $scriptService with methods for invoking
         * the extended Script.js script loader to load scripts by URL and return
         * promises to do so.  Promises require the $q service to be injected, and
         * promise resolutions will take place in the Script.js rather than Angular
         * scope, so $rootScope must be injected to $apply the promise resolution
         * to Angular's $digest cycles.
         */
        lazy.service('$scriptService',function($q,$rootScope) {
          /**
           * Loads a batch of scripts and returns a promise which will be resolved
           * when Script.js has finished loading them.
           *
           * @param url   A string URL to a single script or an array of string URLs
           * @returns promise   A promise which will be resolved by Script.js
           */
          this.load = function(url) {
            // Instantiate the promise
            var deferred = $q.defer();
            // Resolve and bail immediately if url === null
            if (url === null) { deferred.resolve(); return deferred.promise; }
            // Load the scripts
            $script(url,function() {
              // Resolve the promise on callback
              $rootScope.$apply(function() { deferred.resolve(); });
            });
            // Promise that the URLs will be loaded
            return deferred.promise;
          };
    
          /**
           * Convenience method for loading the scripts specified by a 'lazy'
           * ui-router state's 'scripts' property object.  Promises that all
           * scripts will be loaded.
           *
           * @param scripts   Object containing properties 'controllers', 'directives',
           * 'services', 'factories', and 'js', each containing an array of URLs to JS
           * files defining those components, with miscelleneous scripts in the 'js' array.
           * any of these properties can be left off of the object safely, but scripts
           * specified in any other object property will not be loaded.
           * @returns promise   A promise that all scripts will be loaded
           */
          this.loadState = function(scripts) {
            // If no scripts are given, instantiate, resolve, and return an easy promise
            if (scripts === null) { var d = $q.defer; d.resolve(); return d; }
            // Promise that all these promises will resolve
            return $q.all([
              this.load(scripts['directives'] || null),
              this.load(scripts['controllers'] || null),
              this.load(scripts['services'] || null),
              this.load(scripts['factories'] || null),
    
              this.load(scripts['js'] || null)
            ]);
          };
        });
    
        // Declare a run block for the module accessing $rootScope, $scriptService, and $state
        lazy.run(function($rootScope,$scriptService,$state) {
          // Register a $stateChangeStart event listener on $rootScope, get a script loader
          // for the $rootScope, $scriptService, and $state service.
          $rootScope.$on('$stateChangeStart',scriptLoaderFactory($scriptService,$state));
        });
    
        /**
         * Returns a two-state function for handing $stateChangeStart events.
         * In the first state, the handler will interrupt the event, preventing
         * the state transition, and invoke $scriptService.loadState on the object
         * stored in the state definition's 'script' property.  Upon the resolution
         * of the loadState call, the handler restarts a $stateChangeStart event
         * by invoking the same transition.  When the handler is called to handle
         * this second event for the original state transition, the handler is in its
         * second state which allows the event to continue and the state transition
         * to happen using the ui-router module's default functionality.
         *
         * @param $scriptService    Injected $scriptService instance for lazy-loading.
         * @param $state            Injected $state service instance for state transitions.
         */
        var scriptLoaderFactory = function($scriptService,$state) {
          // Initialize handler state
          var pending = false;
          // Return the defined handler
          return function(event,toState,toParams,fromState,fromParams) {
            // Check handler state, and change state
            if (pending = !pending) {   // If pending === false state
              // Interrupt state transition
              event.preventDefault();
              // Invoke $scriptService to load state's scripts
              $scriptService.loadState(toState.scripts)
                // When scripts are loaded, restart the same state transition
                .then(function() { $state.go(toState,toParams); });
            } else {  // If pending === true state
              // NOOP, 'ui-router' default event handlers take over
            }
          };
        };
      })();
    
    /** End 'lazy' module */
    
    (function() {
      var lazyApp = angular && angular.module('lazyApp ',['lazy']);
      lazyApp = angular.module('lazy').makeLazy(lazyApp);
    
      lazyApp.config(function($stateProvider) {
    
        $stateProvider.state({
          name: 'root',
          url: '',
          views: {
            'mainView': { templateUrl: '/lazyapp/views/mainview.html', controller: 'lazyAppController' }
          },
          scripts: {
            'directives': [ 'lazyapp/directives/lazyheader/src/lazyheader.js' ],
            'controllers': [ 'lazyapp/controllers/lazyappcontroller.js' ],
            'services': [ 'lazyapp/services/sectionservice.js' ]
          },
          resolve: {
            sections: function(sectionService) {
              return sectionService.getSections();
            }
          }
        });
      });
    
      angular.bootstrap(document,['lazyApp']);
    })();
    
    (function() {
      var lazyApp = angular.module('lazyApp');
    
      lazyApp.service('sectionService',function($q) {
        this.getSections = function() {
          var deferred = $q.defer();
          deferred.resolve({
            'home': {},
            'news': {},
            'events': {},
            'involved': {},
            'contacts': {},
            'links': {}
          });
          return deferred.promise;
        };
      });
    })();
    
    (function() {
      var lazyApp = angular.module('lazyApp ');
    
      lazyApp.directive('lazyHeader',function() {
        return {
          templateUrl: 'lazyapp/directives/lazyheader/templates/lazyheader-main.html',
          restrict: 'E'
        };
      });
    })();
    
    (function() {
      var lazyApp = angular.module('lazyApp ');
    
      lazyApp.controller('lazyAppController',function(sections) {
        // @TODO: Control things.
        console.log(sections);
      });
    })();
    
    lazyapp.module.js

    /**
     * Defines an AngularJS module 'lazy' which depends on and extends the ui-router
     * module to lazy-load scripts specified in the 'scripts' attribute of a state
     * definition object.  This is accomplished by registering a $stateChangeStart
     * event listener with the $rootScope, interrupting the associated state change
     * to invoke the included $scriptService which returns a promise that restarts the
     * previous state transition upon resolution.  The promise resolves when the
     * extended Script.js script loader finishes loading and inserting a new <script>
     * tag into the DOM.
     *
     * Modules using 'lazy' to lazy-load controllers and services should call lazy.makeLazy
     * on themselves to update the module API to inject references for the various $providers 
     * as the original methods are only useful before bootstrapping, during configuration,
     * when references to the $providers are in scope.  lazy.makeLazy will overwrite the
     * module.config functions to save these references so they are available at runtime,
     * after module bootstrapping.
     * See http://ify.io/lazy-loading-in-angularjs/ for additional details on this concept
     *
     * Calls to $stateProvider.state should include a 'scripts' property in the object
     * parameter containing an object with properties 'controllers', 'directives', 'services',
     * 'factories', and 'js', each containing an array of URLs to JS files defining these
     * component types, with other miscelleneous scripts described in the 'js' array.
     * These scripts will all be loaded in parallel and executed in an undefined order
     * when a state transition to the specified state is started.  All scripts will have
     * been loaded and executed before the 'resolve' property's promises are deferred,
     * meaning services described in 'scripts' can be injected into functions in 'resolve'.
     */
    
     (function() {
        // Instantiate the module, include the ui.router module for state functionality
        var lazy = angular.module('lazy',['ui.router']);
    
        /**
         * Hacking Angular to save references to $providers during module configuration.
         * 
         * The $providers are necessary to register components, but they use a private injector
         * only available during bootstrap when running config blocks.  The methods attached to the
         * Vanilla AngularJS modules rely on the same config queue, they don't actually run after the
         * module is bootstrapped or save any references to the providers in this injector.
         * In makeLazy, these methods are overwritten with methods referencing the dependencies
         * injected at configuration through their run context.  This allows them to access the
         * $providers and run the appropriate methods on demand even after the module has been
         * bootstrapped and the $providers injector and its references are no longer available.
         *
         * @param module      An AngularJS module resulting from an angular.module call.
         * @returns module    The same module with the provider convenience methods updated
         * to include the DI $provider references in their run context and to execute the $provider
         * call immediately rather than adding calls to a queue that will never again be invoked.
         */
        lazy.makeLazy = function(module) {
          // The providers can be injected into 'config' function blocks, so define a new one
          module.config(function($compileProvider,$filterProvider,$controllerProvider,$provide) {
            /**
             * Factory method for generating functions to call the appropriate $provider's
             * registration function, registering a provider under a given name.
             * 
             * @param registrationMethod    $provider registration method to call
             * @returns function            A function(name,constructor) calling
             * registationMethod(name,constructor) with those parameters and returning the module.
             */
            var register = function(registrationMethod) {
              /**
               * Function calls registrationMethod against its parameters and returns the module.
               * Analogous to the original module.config methods but with the DI references already saved.
               *
               * @param name          Name of the provider to register
               * @param constructor   Constructor for the provider
               * @returns module      The AngularJS module owning the providers
               */
              return function(name,constructor) {
                // Register the provider
                registrationMethod(name,constructor);
                // Return the module
                return module;
              };
            };
    
            // Overwrite the old methods with DI referencing methods from the factory
            // @TODO: Should probably derive a LazyModule from a module prototype and return
            // that for the sake of not overwriting native AngularJS code, but the old methods
            // don't work after `bootstrap` so they're not necessary anymore anyway.
            module.directive = register($compileProvider.directive);
            module.filter = register($filterProvider.register);
            module.controller = register($controllerProvider.register);
            module.provider = register($provide.provider);
            module.service = register($provide.service);
            module.factory = register($provide.factory);
            module.value = register($provide.value);
            module.constant = register($provide.constant);
          });
          // Return the module
          return module;
        };
    
        /**
         * Define the lazy module's star $scriptService with methods for invoking
         * the extended Script.js script loader to load scripts by URL and return
         * promises to do so.  Promises require the $q service to be injected, and
         * promise resolutions will take place in the Script.js rather than Angular
         * scope, so $rootScope must be injected to $apply the promise resolution
         * to Angular's $digest cycles.
         */
        lazy.service('$scriptService',function($q,$rootScope) {
          /**
           * Loads a batch of scripts and returns a promise which will be resolved
           * when Script.js has finished loading them.
           *
           * @param url   A string URL to a single script or an array of string URLs
           * @returns promise   A promise which will be resolved by Script.js
           */
          this.load = function(url) {
            // Instantiate the promise
            var deferred = $q.defer();
            // Resolve and bail immediately if url === null
            if (url === null) { deferred.resolve(); return deferred.promise; }
            // Load the scripts
            $script(url,function() {
              // Resolve the promise on callback
              $rootScope.$apply(function() { deferred.resolve(); });
            });
            // Promise that the URLs will be loaded
            return deferred.promise;
          };
    
          /**
           * Convenience method for loading the scripts specified by a 'lazy'
           * ui-router state's 'scripts' property object.  Promises that all
           * scripts will be loaded.
           *
           * @param scripts   Object containing properties 'controllers', 'directives',
           * 'services', 'factories', and 'js', each containing an array of URLs to JS
           * files defining those components, with miscelleneous scripts in the 'js' array.
           * any of these properties can be left off of the object safely, but scripts
           * specified in any other object property will not be loaded.
           * @returns promise   A promise that all scripts will be loaded
           */
          this.loadState = function(scripts) {
            // If no scripts are given, instantiate, resolve, and return an easy promise
            if (scripts === null) { var d = $q.defer; d.resolve(); return d; }
            // Promise that all these promises will resolve
            return $q.all([
              this.load(scripts['directives'] || null),
              this.load(scripts['controllers'] || null),
              this.load(scripts['services'] || null),
              this.load(scripts['factories'] || null),
    
              this.load(scripts['js'] || null)
            ]);
          };
        });
    
        // Declare a run block for the module accessing $rootScope, $scriptService, and $state
        lazy.run(function($rootScope,$scriptService,$state) {
          // Register a $stateChangeStart event listener on $rootScope, get a script loader
          // for the $rootScope, $scriptService, and $state service.
          $rootScope.$on('$stateChangeStart',scriptLoaderFactory($scriptService,$state));
        });
    
        /**
         * Returns a two-state function for handing $stateChangeStart events.
         * In the first state, the handler will interrupt the event, preventing
         * the state transition, and invoke $scriptService.loadState on the object
         * stored in the state definition's 'script' property.  Upon the resolution
         * of the loadState call, the handler restarts a $stateChangeStart event
         * by invoking the same transition.  When the handler is called to handle
         * this second event for the original state transition, the handler is in its
         * second state which allows the event to continue and the state transition
         * to happen using the ui-router module's default functionality.
         *
         * @param $scriptService    Injected $scriptService instance for lazy-loading.
         * @param $state            Injected $state service instance for state transitions.
         */
        var scriptLoaderFactory = function($scriptService,$state) {
          // Initialize handler state
          var pending = false;
          // Return the defined handler
          return function(event,toState,toParams,fromState,fromParams) {
            // Check handler state, and change state
            if (pending = !pending) {   // If pending === false state
              // Interrupt state transition
              event.preventDefault();
              // Invoke $scriptService to load state's scripts
              $scriptService.loadState(toState.scripts)
                // When scripts are loaded, restart the same state transition
                .then(function() { $state.go(toState,toParams); });
            } else {  // If pending === true state
              // NOOP, 'ui-router' default event handlers take over
            }
          };
        };
      })();
    
    /** End 'lazy' module */
    
    (function() {
      var lazyApp = angular && angular.module('lazyApp ',['lazy']);
      lazyApp = angular.module('lazy').makeLazy(lazyApp);
    
      lazyApp.config(function($stateProvider) {
    
        $stateProvider.state({
          name: 'root',
          url: '',
          views: {
            'mainView': { templateUrl: '/lazyapp/views/mainview.html', controller: 'lazyAppController' }
          },
          scripts: {
            'directives': [ 'lazyapp/directives/lazyheader/src/lazyheader.js' ],
            'controllers': [ 'lazyapp/controllers/lazyappcontroller.js' ],
            'services': [ 'lazyapp/services/sectionservice.js' ]
          },
          resolve: {
            sections: function(sectionService) {
              return sectionService.getSections();
            }
          }
        });
      });
    
      angular.bootstrap(document,['lazyApp']);
    })();
    
    (function() {
      var lazyApp = angular.module('lazyApp');
    
      lazyApp.service('sectionService',function($q) {
        this.getSections = function() {
          var deferred = $q.defer();
          deferred.resolve({
            'home': {},
            'news': {},
            'events': {},
            'involved': {},
            'contacts': {},
            'links': {}
          });
          return deferred.promise;
        };
      });
    })();
    
    (function() {
      var lazyApp = angular.module('lazyApp ');
    
      lazyApp.directive('lazyHeader',function() {
        return {
          templateUrl: 'lazyapp/directives/lazyheader/templates/lazyheader-main.html',
          restrict: 'E'
        };
      });
    })();
    
    (function() {
      var lazyApp = angular.module('lazyApp ');
    
      lazyApp.controller('lazyAppController',function(sections) {
        // @TODO: Control things.
        console.log(sections);
      });
    })();
    
    sectionservice.js

    /**
     * Defines an AngularJS module 'lazy' which depends on and extends the ui-router
     * module to lazy-load scripts specified in the 'scripts' attribute of a state
     * definition object.  This is accomplished by registering a $stateChangeStart
     * event listener with the $rootScope, interrupting the associated state change
     * to invoke the included $scriptService which returns a promise that restarts the
     * previous state transition upon resolution.  The promise resolves when the
     * extended Script.js script loader finishes loading and inserting a new <script>
     * tag into the DOM.
     *
     * Modules using 'lazy' to lazy-load controllers and services should call lazy.makeLazy
     * on themselves to update the module API to inject references for the various $providers 
     * as the original methods are only useful before bootstrapping, during configuration,
     * when references to the $providers are in scope.  lazy.makeLazy will overwrite the
     * module.config functions to save these references so they are available at runtime,
     * after module bootstrapping.
     * See http://ify.io/lazy-loading-in-angularjs/ for additional details on this concept
     *
     * Calls to $stateProvider.state should include a 'scripts' property in the object
     * parameter containing an object with properties 'controllers', 'directives', 'services',
     * 'factories', and 'js', each containing an array of URLs to JS files defining these
     * component types, with other miscelleneous scripts described in the 'js' array.
     * These scripts will all be loaded in parallel and executed in an undefined order
     * when a state transition to the specified state is started.  All scripts will have
     * been loaded and executed before the 'resolve' property's promises are deferred,
     * meaning services described in 'scripts' can be injected into functions in 'resolve'.
     */
    
     (function() {
        // Instantiate the module, include the ui.router module for state functionality
        var lazy = angular.module('lazy',['ui.router']);
    
        /**
         * Hacking Angular to save references to $providers during module configuration.
         * 
         * The $providers are necessary to register components, but they use a private injector
         * only available during bootstrap when running config blocks.  The methods attached to the
         * Vanilla AngularJS modules rely on the same config queue, they don't actually run after the
         * module is bootstrapped or save any references to the providers in this injector.
         * In makeLazy, these methods are overwritten with methods referencing the dependencies
         * injected at configuration through their run context.  This allows them to access the
         * $providers and run the appropriate methods on demand even after the module has been
         * bootstrapped and the $providers injector and its references are no longer available.
         *
         * @param module      An AngularJS module resulting from an angular.module call.
         * @returns module    The same module with the provider convenience methods updated
         * to include the DI $provider references in their run context and to execute the $provider
         * call immediately rather than adding calls to a queue that will never again be invoked.
         */
        lazy.makeLazy = function(module) {
          // The providers can be injected into 'config' function blocks, so define a new one
          module.config(function($compileProvider,$filterProvider,$controllerProvider,$provide) {
            /**
             * Factory method for generating functions to call the appropriate $provider's
             * registration function, registering a provider under a given name.
             * 
             * @param registrationMethod    $provider registration method to call
             * @returns function            A function(name,constructor) calling
             * registationMethod(name,constructor) with those parameters and returning the module.
             */
            var register = function(registrationMethod) {
              /**
               * Function calls registrationMethod against its parameters and returns the module.
               * Analogous to the original module.config methods but with the DI references already saved.
               *
               * @param name          Name of the provider to register
               * @param constructor   Constructor for the provider
               * @returns module      The AngularJS module owning the providers
               */
              return function(name,constructor) {
                // Register the provider
                registrationMethod(name,constructor);
                // Return the module
                return module;
              };
            };
    
            // Overwrite the old methods with DI referencing methods from the factory
            // @TODO: Should probably derive a LazyModule from a module prototype and return
            // that for the sake of not overwriting native AngularJS code, but the old methods
            // don't work after `bootstrap` so they're not necessary anymore anyway.
            module.directive = register($compileProvider.directive);
            module.filter = register($filterProvider.register);
            module.controller = register($controllerProvider.register);
            module.provider = register($provide.provider);
            module.service = register($provide.service);
            module.factory = register($provide.factory);
            module.value = register($provide.value);
            module.constant = register($provide.constant);
          });
          // Return the module
          return module;
        };
    
        /**
         * Define the lazy module's star $scriptService with methods for invoking
         * the extended Script.js script loader to load scripts by URL and return
         * promises to do so.  Promises require the $q service to be injected, and
         * promise resolutions will take place in the Script.js rather than Angular
         * scope, so $rootScope must be injected to $apply the promise resolution
         * to Angular's $digest cycles.
         */
        lazy.service('$scriptService',function($q,$rootScope) {
          /**
           * Loads a batch of scripts and returns a promise which will be resolved
           * when Script.js has finished loading them.
           *
           * @param url   A string URL to a single script or an array of string URLs
           * @returns promise   A promise which will be resolved by Script.js
           */
          this.load = function(url) {
            // Instantiate the promise
            var deferred = $q.defer();
            // Resolve and bail immediately if url === null
            if (url === null) { deferred.resolve(); return deferred.promise; }
            // Load the scripts
            $script(url,function() {
              // Resolve the promise on callback
              $rootScope.$apply(function() { deferred.resolve(); });
            });
            // Promise that the URLs will be loaded
            return deferred.promise;
          };
    
          /**
           * Convenience method for loading the scripts specified by a 'lazy'
           * ui-router state's 'scripts' property object.  Promises that all
           * scripts will be loaded.
           *
           * @param scripts   Object containing properties 'controllers', 'directives',
           * 'services', 'factories', and 'js', each containing an array of URLs to JS
           * files defining those components, with miscelleneous scripts in the 'js' array.
           * any of these properties can be left off of the object safely, but scripts
           * specified in any other object property will not be loaded.
           * @returns promise   A promise that all scripts will be loaded
           */
          this.loadState = function(scripts) {
            // If no scripts are given, instantiate, resolve, and return an easy promise
            if (scripts === null) { var d = $q.defer; d.resolve(); return d; }
            // Promise that all these promises will resolve
            return $q.all([
              this.load(scripts['directives'] || null),
              this.load(scripts['controllers'] || null),
              this.load(scripts['services'] || null),
              this.load(scripts['factories'] || null),
    
              this.load(scripts['js'] || null)
            ]);
          };
        });
    
        // Declare a run block for the module accessing $rootScope, $scriptService, and $state
        lazy.run(function($rootScope,$scriptService,$state) {
          // Register a $stateChangeStart event listener on $rootScope, get a script loader
          // for the $rootScope, $scriptService, and $state service.
          $rootScope.$on('$stateChangeStart',scriptLoaderFactory($scriptService,$state));
        });
    
        /**
         * Returns a two-state function for handing $stateChangeStart events.
         * In the first state, the handler will interrupt the event, preventing
         * the state transition, and invoke $scriptService.loadState on the object
         * stored in the state definition's 'script' property.  Upon the resolution
         * of the loadState call, the handler restarts a $stateChangeStart event
         * by invoking the same transition.  When the handler is called to handle
         * this second event for the original state transition, the handler is in its
         * second state which allows the event to continue and the state transition
         * to happen using the ui-router module's default functionality.
         *
         * @param $scriptService    Injected $scriptService instance for lazy-loading.
         * @param $state            Injected $state service instance for state transitions.
         */
        var scriptLoaderFactory = function($scriptService,$state) {
          // Initialize handler state
          var pending = false;
          // Return the defined handler
          return function(event,toState,toParams,fromState,fromParams) {
            // Check handler state, and change state
            if (pending = !pending) {   // If pending === false state
              // Interrupt state transition
              event.preventDefault();
              // Invoke $scriptService to load state's scripts
              $scriptService.loadState(toState.scripts)
                // When scripts are loaded, restart the same state transition
                .then(function() { $state.go(toState,toParams); });
            } else {  // If pending === true state
              // NOOP, 'ui-router' default event handlers take over
            }
          };
        };
      })();
    
    /** End 'lazy' module */
    
    (function() {
      var lazyApp = angular && angular.module('lazyApp ',['lazy']);
      lazyApp = angular.module('lazy').makeLazy(lazyApp);
    
      lazyApp.config(function($stateProvider) {
    
        $stateProvider.state({
          name: 'root',
          url: '',
          views: {
            'mainView': { templateUrl: '/lazyapp/views/mainview.html', controller: 'lazyAppController' }
          },
          scripts: {
            'directives': [ 'lazyapp/directives/lazyheader/src/lazyheader.js' ],
            'controllers': [ 'lazyapp/controllers/lazyappcontroller.js' ],
            'services': [ 'lazyapp/services/sectionservice.js' ]
          },
          resolve: {
            sections: function(sectionService) {
              return sectionService.getSections();
            }
          }
        });
      });
    
      angular.bootstrap(document,['lazyApp']);
    })();
    
    (function() {
      var lazyApp = angular.module('lazyApp');
    
      lazyApp.service('sectionService',function($q) {
        this.getSections = function() {
          var deferred = $q.defer();
          deferred.resolve({
            'home': {},
            'news': {},
            'events': {},
            'involved': {},
            'contacts': {},
            'links': {}
          });
          return deferred.promise;
        };
      });
    })();
    
    (function() {
      var lazyApp = angular.module('lazyApp ');
    
      lazyApp.directive('lazyHeader',function() {
        return {
          templateUrl: 'lazyapp/directives/lazyheader/templates/lazyheader-main.html',
          restrict: 'E'
        };
      });
    })();
    
    (function() {
      var lazyApp = angular.module('lazyApp ');
    
      lazyApp.controller('lazyAppController',function(sections) {
        // @TODO: Control things.
        console.log(sections);
      });
    })();
    
    lazyheader.js

    /**
     * Defines an AngularJS module 'lazy' which depends on and extends the ui-router
     * module to lazy-load scripts specified in the 'scripts' attribute of a state
     * definition object.  This is accomplished by registering a $stateChangeStart
     * event listener with the $rootScope, interrupting the associated state change
     * to invoke the included $scriptService which returns a promise that restarts the
     * previous state transition upon resolution.  The promise resolves when the
     * extended Script.js script loader finishes loading and inserting a new <script>
     * tag into the DOM.
     *
     * Modules using 'lazy' to lazy-load controllers and services should call lazy.makeLazy
     * on themselves to update the module API to inject references for the various $providers 
     * as the original methods are only useful before bootstrapping, during configuration,
     * when references to the $providers are in scope.  lazy.makeLazy will overwrite the
     * module.config functions to save these references so they are available at runtime,
     * after module bootstrapping.
     * See http://ify.io/lazy-loading-in-angularjs/ for additional details on this concept
     *
     * Calls to $stateProvider.state should include a 'scripts' property in the object
     * parameter containing an object with properties 'controllers', 'directives', 'services',
     * 'factories', and 'js', each containing an array of URLs to JS files defining these
     * component types, with other miscelleneous scripts described in the 'js' array.
     * These scripts will all be loaded in parallel and executed in an undefined order
     * when a state transition to the specified state is started.  All scripts will have
     * been loaded and executed before the 'resolve' property's promises are deferred,
     * meaning services described in 'scripts' can be injected into functions in 'resolve'.
     */
    
     (function() {
        // Instantiate the module, include the ui.router module for state functionality
        var lazy = angular.module('lazy',['ui.router']);
    
        /**
         * Hacking Angular to save references to $providers during module configuration.
         * 
         * The $providers are necessary to register components, but they use a private injector
         * only available during bootstrap when running config blocks.  The methods attached to the
         * Vanilla AngularJS modules rely on the same config queue, they don't actually run after the
         * module is bootstrapped or save any references to the providers in this injector.
         * In makeLazy, these methods are overwritten with methods referencing the dependencies
         * injected at configuration through their run context.  This allows them to access the
         * $providers and run the appropriate methods on demand even after the module has been
         * bootstrapped and the $providers injector and its references are no longer available.
         *
         * @param module      An AngularJS module resulting from an angular.module call.
         * @returns module    The same module with the provider convenience methods updated
         * to include the DI $provider references in their run context and to execute the $provider
         * call immediately rather than adding calls to a queue that will never again be invoked.
         */
        lazy.makeLazy = function(module) {
          // The providers can be injected into 'config' function blocks, so define a new one
          module.config(function($compileProvider,$filterProvider,$controllerProvider,$provide) {
            /**
             * Factory method for generating functions to call the appropriate $provider's
             * registration function, registering a provider under a given name.
             * 
             * @param registrationMethod    $provider registration method to call
             * @returns function            A function(name,constructor) calling
             * registationMethod(name,constructor) with those parameters and returning the module.
             */
            var register = function(registrationMethod) {
              /**
               * Function calls registrationMethod against its parameters and returns the module.
               * Analogous to the original module.config methods but with the DI references already saved.
               *
               * @param name          Name of the provider to register
               * @param constructor   Constructor for the provider
               * @returns module      The AngularJS module owning the providers
               */
              return function(name,constructor) {
                // Register the provider
                registrationMethod(name,constructor);
                // Return the module
                return module;
              };
            };
    
            // Overwrite the old methods with DI referencing methods from the factory
            // @TODO: Should probably derive a LazyModule from a module prototype and return
            // that for the sake of not overwriting native AngularJS code, but the old methods
            // don't work after `bootstrap` so they're not necessary anymore anyway.
            module.directive = register($compileProvider.directive);
            module.filter = register($filterProvider.register);
            module.controller = register($controllerProvider.register);
            module.provider = register($provide.provider);
            module.service = register($provide.service);
            module.factory = register($provide.factory);
            module.value = register($provide.value);
            module.constant = register($provide.constant);
          });
          // Return the module
          return module;
        };
    
        /**
         * Define the lazy module's star $scriptService with methods for invoking
         * the extended Script.js script loader to load scripts by URL and return
         * promises to do so.  Promises require the $q service to be injected, and
         * promise resolutions will take place in the Script.js rather than Angular
         * scope, so $rootScope must be injected to $apply the promise resolution
         * to Angular's $digest cycles.
         */
        lazy.service('$scriptService',function($q,$rootScope) {
          /**
           * Loads a batch of scripts and returns a promise which will be resolved
           * when Script.js has finished loading them.
           *
           * @param url   A string URL to a single script or an array of string URLs
           * @returns promise   A promise which will be resolved by Script.js
           */
          this.load = function(url) {
            // Instantiate the promise
            var deferred = $q.defer();
            // Resolve and bail immediately if url === null
            if (url === null) { deferred.resolve(); return deferred.promise; }
            // Load the scripts
            $script(url,function() {
              // Resolve the promise on callback
              $rootScope.$apply(function() { deferred.resolve(); });
            });
            // Promise that the URLs will be loaded
            return deferred.promise;
          };
    
          /**
           * Convenience method for loading the scripts specified by a 'lazy'
           * ui-router state's 'scripts' property object.  Promises that all
           * scripts will be loaded.
           *
           * @param scripts   Object containing properties 'controllers', 'directives',
           * 'services', 'factories', and 'js', each containing an array of URLs to JS
           * files defining those components, with miscelleneous scripts in the 'js' array.
           * any of these properties can be left off of the object safely, but scripts
           * specified in any other object property will not be loaded.
           * @returns promise   A promise that all scripts will be loaded
           */
          this.loadState = function(scripts) {
            // If no scripts are given, instantiate, resolve, and return an easy promise
            if (scripts === null) { var d = $q.defer; d.resolve(); return d; }
            // Promise that all these promises will resolve
            return $q.all([
              this.load(scripts['directives'] || null),
              this.load(scripts['controllers'] || null),
              this.load(scripts['services'] || null),
              this.load(scripts['factories'] || null),
    
              this.load(scripts['js'] || null)
            ]);
          };
        });
    
        // Declare a run block for the module accessing $rootScope, $scriptService, and $state
        lazy.run(function($rootScope,$scriptService,$state) {
          // Register a $stateChangeStart event listener on $rootScope, get a script loader
          // for the $rootScope, $scriptService, and $state service.
          $rootScope.$on('$stateChangeStart',scriptLoaderFactory($scriptService,$state));
        });
    
        /**
         * Returns a two-state function for handing $stateChangeStart events.
         * In the first state, the handler will interrupt the event, preventing
         * the state transition, and invoke $scriptService.loadState on the object
         * stored in the state definition's 'script' property.  Upon the resolution
         * of the loadState call, the handler restarts a $stateChangeStart event
         * by invoking the same transition.  When the handler is called to handle
         * this second event for the original state transition, the handler is in its
         * second state which allows the event to continue and the state transition
         * to happen using the ui-router module's default functionality.
         *
         * @param $scriptService    Injected $scriptService instance for lazy-loading.
         * @param $state            Injected $state service instance for state transitions.
         */
        var scriptLoaderFactory = function($scriptService,$state) {
          // Initialize handler state
          var pending = false;
          // Return the defined handler
          return function(event,toState,toParams,fromState,fromParams) {
            // Check handler state, and change state
            if (pending = !pending) {   // If pending === false state
              // Interrupt state transition
              event.preventDefault();
              // Invoke $scriptService to load state's scripts
              $scriptService.loadState(toState.scripts)
                // When scripts are loaded, restart the same state transition
                .then(function() { $state.go(toState,toParams); });
            } else {  // If pending === true state
              // NOOP, 'ui-router' default event handlers take over
            }
          };
        };
      })();
    
    /** End 'lazy' module */
    
    (function() {
      var lazyApp = angular && angular.module('lazyApp ',['lazy']);
      lazyApp = angular.module('lazy').makeLazy(lazyApp);
    
      lazyApp.config(function($stateProvider) {
    
        $stateProvider.state({
          name: 'root',
          url: '',
          views: {
            'mainView': { templateUrl: '/lazyapp/views/mainview.html', controller: 'lazyAppController' }
          },
          scripts: {
            'directives': [ 'lazyapp/directives/lazyheader/src/lazyheader.js' ],
            'controllers': [ 'lazyapp/controllers/lazyappcontroller.js' ],
            'services': [ 'lazyapp/services/sectionservice.js' ]
          },
          resolve: {
            sections: function(sectionService) {
              return sectionService.getSections();
            }
          }
        });
      });
    
      angular.bootstrap(document,['lazyApp']);
    })();
    
    (function() {
      var lazyApp = angular.module('lazyApp');
    
      lazyApp.service('sectionService',function($q) {
        this.getSections = function() {
          var deferred = $q.defer();
          deferred.resolve({
            'home': {},
            'news': {},
            'events': {},
            'involved': {},
            'contacts': {},
            'links': {}
          });
          return deferred.promise;
        };
      });
    })();
    
    (function() {
      var lazyApp = angular.module('lazyApp ');
    
      lazyApp.directive('lazyHeader',function() {
        return {
          templateUrl: 'lazyapp/directives/lazyheader/templates/lazyheader-main.html',
          restrict: 'E'
        };
      });
    })();
    
    (function() {
      var lazyApp = angular.module('lazyApp ');
    
      lazyApp.controller('lazyAppController',function(sections) {
        // @TODO: Control things.
        console.log(sections);
      });
    })();
    
    lazyappcontroller.js

    /**
     * Defines an AngularJS module 'lazy' which depends on and extends the ui-router
     * module to lazy-load scripts specified in the 'scripts' attribute of a state
     * definition object.  This is accomplished by registering a $stateChangeStart
     * event listener with the $rootScope, interrupting the associated state change
     * to invoke the included $scriptService which returns a promise that restarts the
     * previous state transition upon resolution.  The promise resolves when the
     * extended Script.js script loader finishes loading and inserting a new <script>
     * tag into the DOM.
     *
     * Modules using 'lazy' to lazy-load controllers and services should call lazy.makeLazy
     * on themselves to update the module API to inject references for the various $providers 
     * as the original methods are only useful before bootstrapping, during configuration,
     * when references to the $providers are in scope.  lazy.makeLazy will overwrite the
     * module.config functions to save these references so they are available at runtime,
     * after module bootstrapping.
     * See http://ify.io/lazy-loading-in-angularjs/ for additional details on this concept
     *
     * Calls to $stateProvider.state should include a 'scripts' property in the object
     * parameter containing an object with properties 'controllers', 'directives', 'services',
     * 'factories', and 'js', each containing an array of URLs to JS files defining these
     * component types, with other miscelleneous scripts described in the 'js' array.
     * These scripts will all be loaded in parallel and executed in an undefined order
     * when a state transition to the specified state is started.  All scripts will have
     * been loaded and executed before the 'resolve' property's promises are deferred,
     * meaning services described in 'scripts' can be injected into functions in 'resolve'.
     */
    
     (function() {
        // Instantiate the module, include the ui.router module for state functionality
        var lazy = angular.module('lazy',['ui.router']);
    
        /**
         * Hacking Angular to save references to $providers during module configuration.
         * 
         * The $providers are necessary to register components, but they use a private injector
         * only available during bootstrap when running config blocks.  The methods attached to the
         * Vanilla AngularJS modules rely on the same config queue, they don't actually run after the
         * module is bootstrapped or save any references to the providers in this injector.
         * In makeLazy, these methods are overwritten with methods referencing the dependencies
         * injected at configuration through their run context.  This allows them to access the
         * $providers and run the appropriate methods on demand even after the module has been
         * bootstrapped and the $providers injector and its references are no longer available.
         *
         * @param module      An AngularJS module resulting from an angular.module call.
         * @returns module    The same module with the provider convenience methods updated
         * to include the DI $provider references in their run context and to execute the $provider
         * call immediately rather than adding calls to a queue that will never again be invoked.
         */
        lazy.makeLazy = function(module) {
          // The providers can be injected into 'config' function blocks, so define a new one
          module.config(function($compileProvider,$filterProvider,$controllerProvider,$provide) {
            /**
             * Factory method for generating functions to call the appropriate $provider's
             * registration function, registering a provider under a given name.
             * 
             * @param registrationMethod    $provider registration method to call
             * @returns function            A function(name,constructor) calling
             * registationMethod(name,constructor) with those parameters and returning the module.
             */
            var register = function(registrationMethod) {
              /**
               * Function calls registrationMethod against its parameters and returns the module.
               * Analogous to the original module.config methods but with the DI references already saved.
               *
               * @param name          Name of the provider to register
               * @param constructor   Constructor for the provider
               * @returns module      The AngularJS module owning the providers
               */
              return function(name,constructor) {
                // Register the provider
                registrationMethod(name,constructor);
                // Return the module
                return module;
              };
            };
    
            // Overwrite the old methods with DI referencing methods from the factory
            // @TODO: Should probably derive a LazyModule from a module prototype and return
            // that for the sake of not overwriting native AngularJS code, but the old methods
            // don't work after `bootstrap` so they're not necessary anymore anyway.
            module.directive = register($compileProvider.directive);
            module.filter = register($filterProvider.register);
            module.controller = register($controllerProvider.register);
            module.provider = register($provide.provider);
            module.service = register($provide.service);
            module.factory = register($provide.factory);
            module.value = register($provide.value);
            module.constant = register($provide.constant);
          });
          // Return the module
          return module;
        };
    
        /**
         * Define the lazy module's star $scriptService with methods for invoking
         * the extended Script.js script loader to load scripts by URL and return
         * promises to do so.  Promises require the $q service to be injected, and
         * promise resolutions will take place in the Script.js rather than Angular
         * scope, so $rootScope must be injected to $apply the promise resolution
         * to Angular's $digest cycles.
         */
        lazy.service('$scriptService',function($q,$rootScope) {
          /**
           * Loads a batch of scripts and returns a promise which will be resolved
           * when Script.js has finished loading them.
           *
           * @param url   A string URL to a single script or an array of string URLs
           * @returns promise   A promise which will be resolved by Script.js
           */
          this.load = function(url) {
            // Instantiate the promise
            var deferred = $q.defer();
            // Resolve and bail immediately if url === null
            if (url === null) { deferred.resolve(); return deferred.promise; }
            // Load the scripts
            $script(url,function() {
              // Resolve the promise on callback
              $rootScope.$apply(function() { deferred.resolve(); });
            });
            // Promise that the URLs will be loaded
            return deferred.promise;
          };
    
          /**
           * Convenience method for loading the scripts specified by a 'lazy'
           * ui-router state's 'scripts' property object.  Promises that all
           * scripts will be loaded.
           *
           * @param scripts   Object containing properties 'controllers', 'directives',
           * 'services', 'factories', and 'js', each containing an array of URLs to JS
           * files defining those components, with miscelleneous scripts in the 'js' array.
           * any of these properties can be left off of the object safely, but scripts
           * specified in any other object property will not be loaded.
           * @returns promise   A promise that all scripts will be loaded
           */
          this.loadState = function(scripts) {
            // If no scripts are given, instantiate, resolve, and return an easy promise
            if (scripts === null) { var d = $q.defer; d.resolve(); return d; }
            // Promise that all these promises will resolve
            return $q.all([
              this.load(scripts['directives'] || null),
              this.load(scripts['controllers'] || null),
              this.load(scripts['services'] || null),
              this.load(scripts['factories'] || null),
    
              this.load(scripts['js'] || null)
            ]);
          };
        });
    
        // Declare a run block for the module accessing $rootScope, $scriptService, and $state
        lazy.run(function($rootScope,$scriptService,$state) {
          // Register a $stateChangeStart event listener on $rootScope, get a script loader
          // for the $rootScope, $scriptService, and $state service.
          $rootScope.$on('$stateChangeStart',scriptLoaderFactory($scriptService,$state));
        });
    
        /**
         * Returns a two-state function for handing $stateChangeStart events.
         * In the first state, the handler will interrupt the event, preventing
         * the state transition, and invoke $scriptService.loadState on the object
         * stored in the state definition's 'script' property.  Upon the resolution
         * of the loadState call, the handler restarts a $stateChangeStart event
         * by invoking the same transition.  When the handler is called to handle
         * this second event for the original state transition, the handler is in its
         * second state which allows the event to continue and the state transition
         * to happen using the ui-router module's default functionality.
         *
         * @param $scriptService    Injected $scriptService instance for lazy-loading.
         * @param $state            Injected $state service instance for state transitions.
         */
        var scriptLoaderFactory = function($scriptService,$state) {
          // Initialize handler state
          var pending = false;
          // Return the defined handler
          return function(event,toState,toParams,fromState,fromParams) {
            // Check handler state, and change state
            if (pending = !pending) {   // If pending === false state
              // Interrupt state transition
              event.preventDefault();
              // Invoke $scriptService to load state's scripts
              $scriptService.loadState(toState.scripts)
                // When scripts are loaded, restart the same state transition
                .then(function() { $state.go(toState,toParams); });
            } else {  // If pending === true state
              // NOOP, 'ui-router' default event handlers take over
            }
          };
        };
      })();
    
    /** End 'lazy' module */
    
    (function() {
      var lazyApp = angular && angular.module('lazyApp ',['lazy']);
      lazyApp = angular.module('lazy').makeLazy(lazyApp);
    
      lazyApp.config(function($stateProvider) {
    
        $stateProvider.state({
          name: 'root',
          url: '',
          views: {
            'mainView': { templateUrl: '/lazyapp/views/mainview.html', controller: 'lazyAppController' }
          },
          scripts: {
            'directives': [ 'lazyapp/directives/lazyheader/src/lazyheader.js' ],
            'controllers': [ 'lazyapp/controllers/lazyappcontroller.js' ],
            'services': [ 'lazyapp/services/sectionservice.js' ]
          },
          resolve: {
            sections: function(sectionService) {
              return sectionService.getSections();
            }
          }
        });
      });
    
      angular.bootstrap(document,['lazyApp']);
    })();
    
    (function() {
      var lazyApp = angular.module('lazyApp');
    
      lazyApp.service('sectionService',function($q) {
        this.getSections = function() {
          var deferred = $q.defer();
          deferred.resolve({
            'home': {},
            'news': {},
            'events': {},
            'involved': {},
            'contacts': {},
            'links': {}
          });
          return deferred.promise;
        };
      });
    })();
    
    (function() {
      var lazyApp = angular.module('lazyApp ');
    
      lazyApp.directive('lazyHeader',function() {
        return {
          templateUrl: 'lazyapp/directives/lazyheader/templates/lazyheader-main.html',
          restrict: 'E'
        };
      });
    })();
    
    (function() {
      var lazyApp = angular.module('lazyApp ');
    
      lazyApp.controller('lazyAppController',function(sections) {
        // @TODO: Control things.
        console.log(sections);
      });
    })();
    

    我在这段代码中发现了一个bug。$scriptService无法正确处理子状态。它不会从父状态加载脚本。我已经在我的项目中修复了这个问题,当我有机会的时候,我会在这里更新代码。