<!DOCTYPE html>
<html>

  <head>
    <script src="lazyload.min.js"></script>
    <script data-require="jquery@2.1.3" data-semver="2.1.3" src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
    <script data-require="angular.js@1.4.0-beta.5" data-semver="1.4.0-beta.5" src="https://code.angularjs.org/1.4.0-beta.5/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-app="auto">
    <img src="https://docs.angularjs.org/img/guide/concepts-startup.png">
    <span style="font-size: 48px;margin: 0px 20px;vertical-align: bottom;">&rarr;</span>
    
    <!-- AUTO -->
    <div id="auto_container" class="demo yellow">
      <div ng-controller="CounterCtrl as counterAuto">
        <label>Auto</label>
        <button ng-click="increment()">Increment</button>
        <br />
        <br />
        <span>
          <ng-pluralize count="counter" when="{'0'    : '-',
                                               '1'    : '{} click',
                                               'other': '{} clicks'}"></ng-pluralize>
        </span>
      </div>
    </div>
        
    <br /><hr><br />
    
    <!-- Manual -->
    <div id="manual_container" class="demo blue">
    </div>
    
    <!-- Nested (manual within auto) -->
    <div id="nested_container" class="demo yellow">
      <div ng-app="nested" ng-controller="CounterCtrl as nestedCounterAuto">
        <label>Nested</label>

        <button ng-click="increment()">Increment</button>
        <br />
        <br />
        <span>
          <ng-pluralize count="counter" when="{'0'    : '-',
                                               '1'    : '{} click',
                                               'other': '{} clicks'}"></ng-pluralize>
        </span>
      </div>
    </div>
    
    <br/><br/>
    <ul style="font-size:12px;">
      <li><a href="https://github.com/angular/angular.js/issues/5653">https://github.com/angular/angular.js/issues/5653</a></li>
      <li><a href="https://blog.mariusschulz.com/2014/10/22/asynchronously-bootstrapping-angularjs-applications-with-server-side-data">https://blog.mariusschulz.com/2014/10/22/asynchronously-bootstrapping-angularjs-applications-with-server-side-data</a></li>
    </ul>
    
    <!-- Always enjoyable to be flttred! -->
    <div style="position:absolute;bottom:0px; margin: 0px 0px 40px 10px;">
      <script id='fbketsn'>(function(i){var f,s=document.getElementById(i);f=document.createElement('iframe');f.src='//api.flattr.com/button/view/?uid=ggarcia&button=compact&url='+encodeURIComponent(document.URL);f.title='Flattr';f.height=20;f.width=110;f.style.borderWidth=0;s.parentNode.insertBefore(f,s);})('fbketsn');</script>
    </div>
  </body>

  <script>
    manualBootstrap("manual");
  </script>

</html>
//-------------------------------------------------
//   AUTO
//-------------------------------------------------
var auto = angular.module('auto', []);

auto.controller('CounterCtrl', ['$scope', function($scope) {
  $scope.counter = 0;
  
  $scope.increment = function() {
    $scope.counter += 1;
  }
}]);

//-------------------------------------------------
//   NESTED
//-------------------------------------------------
var nested = angular.module('nested', []);

// nested.controller('NestedCounterCtrl', ['$scope', function($scope) {
//   $scope.counter = 0;
  
//   $scope.increment = function() {
//     $scope.counter += 1;
//   }
// }]);

//-------------------------------------------------
//   MANUAL BOOTSTRAPPING
//-------------------------------------------------
var container;
var htmlTemplate = "";

function manualBootstrap(name) {
  // Retrieve HTML template synchronously
  $.ajax({
			type: "GET",
			async: false,
			url: "htmlTemplate.html",
			dataType: 'html',
			success: function (msg) {
				htmlTemplate = msg;
				//console.log(htmlTemplate);
			},
			error: function (XMLHttpRequest, textStatus, errorThrown) {
			  //console.log(textStatus);
			}
	});
  
  // Retrieve JS controller using lazy loading
	var deferred = $.Deferred();		

	LazyLoad.js(["controllerTemplate.js"], function () {
		if (typeof window["manualCtrl"] === "undefined") 
			deferred.reject();
		else {
			deferred.resolve(window["manualCtrl"]);
		}
	});
		
  window.setTimeout(function() {
    $("#" + name + "_container").append('<div style="width:100%;height:100%"></div>');
    container = $("#" + name + "_container").children().first();
    container.attr("ng-app", name + '_app')
             .attr("ng-controller", name + "Ctrl as manualCtrl")
             //.attr("id", name)
             ;
             
    $.when(deferred).then(function(js) {
      container = $("#" + name + "_container").children().first();
      container.empty().html(htmlTemplate);
  
      angular.module(name + '_app', [])
             .controller(name + "Ctrl", js);
      angular.bootstrap(container, [name + '_app']);
    });
  });
}
/* Styles go here */

.demo {
  border: 1px dotted darkgrey;
  height: 200px;
  width: 150px;
  text-align: center;
  padding: 20px;
  display: inline-block;
  vertical-align: bottom
}
.yellow {
  background-color: rgba(255,255,0,0.05);
}
.blue {
  background-color: rgba(0,0,255,0.05);
}

button {
  width: 100%;
  height: 30px;
  margin: 10px 0px;
}
<label>Manual</label>
<button ng-click="increment()">Increment</button>
<br />
<br />
<span>
  <ng-pluralize count="counter" when="{'0'    : '-',
                                       '1'    : '{} click',
                                       'other': '{} clicks'}"></ng-pluralize>
</span>
"use strict";

var manualCtrl = ['$scope', function($scope) {
  $scope.counter = 0;
  
  $scope.increment = function() {
    $scope.counter += 1;
  }

	//End of controller
}];
LazyLoad=function(e){function u(t,n){var r=e.createElement(t),i;for(i in n){if(n.hasOwnProperty(i)){r.setAttribute(i,n[i])}}return r}function a(e){var t=r[e],n,o;if(t){n=t.callback;o=t.urls;o.shift();i=0;if(!o.length){n&&n.call(t.context,t.obj);r[e]=null;s[e].length&&l(e)}}}function f(){var n=navigator.userAgent;t={async:e.createElement("script").async===true};(t.webkit=/AppleWebKit\//.test(n))||(t.ie=/MSIE|Trident/.test(n))||(t.opera=/Opera/.test(n))||(t.gecko=/Gecko\//.test(n))||(t.unknown=true)}function l(i,o,l,p,d){var v=function(){a(i)},m=i==="css",g=[],y,b,w,E,S,x;t||f();if(o){o=typeof o==="string"?[o]:o.concat();if(m||t.async||t.gecko||t.opera){s[i].push({urls:o,callback:l,obj:p,context:d})}else{for(y=0,b=o.length;y<b;++y){s[i].push({urls:[o[y]],callback:y===b-1?l:null,obj:p,context:d})}}}if(r[i]||!(E=r[i]=s[i].shift())){return}n||(n=e.head||e.getElementsByTagName("head")[0]);S=E.urls.concat();for(y=0,b=S.length;y<b;++y){x=S[y];if(m){w=u("link",{href:x,rel:"stylesheet"})}else{w=u("script",{src:x});w.async=false}w.className="lazyload";w.setAttribute("charset","utf-8");if(t.ie&&!m&&"onreadystatechange"in w&&!("draggable"in w)){w.onreadystatechange=function(){if(/loaded|complete/.test(w.readyState)){w.onreadystatechange=null;v()}}}else if(m&&(t.gecko||t.webkit)){if(t.webkit){E.urls[y]=w.href;h()}else{w.innerHTML='@import "'+x+'";';c(w)}}else{w.onload=w.onerror=v}g.push(w)}for(y=0,b=g.length;y<b;++y){n.appendChild(g[y])}}function c(e){var t;try{t=!!e.sheet.cssRules}catch(n){i+=1;if(i<200){setTimeout(function(){c(e)},50)}else{t&&a("css")}return}a("css")}function h(){var e=r.css,t;if(e){t=o.length;while(--t>=0){if(o[t].href===e.urls[0]){a("css");break}}i+=1;if(e){if(i<200){setTimeout(h,50)}else{a("css")}}}}var t,n,r={},i=0,s={css:[],js:[]},o=e.styleSheets;return{css:function(e,t,n,r){l("css",e,t,n,r)},js:function(e,t,n,r){l("js",e,t,n,r)}}}(this.document)