diff --git a/js/angular/service/templateCache.js b/js/angular/service/templateCache.js new file mode 100644 index 0000000000..18d094dfca --- /dev/null +++ b/js/angular/service/templateCache.js @@ -0,0 +1,142 @@ +// closure to keep things neat +(function() { + var templatesToCache = []; + +/** + * @ngdoc service + * @name $ionicTemplateCache + * @module ionic + * @description An angular service that preemptively caches template files to reduce flicker and boost performance. + * @usage + * State templates are cached automatically, but you can optionally cache other templates. + * ```js + * $ionicTemplateCahce('myNgIncludeTemplate.html'); + * ``` + * + * Optionally disable all preemptive caching with the `$ionicConfigProvider` or individual states by setting `prefetchTemplate` + * in the $state definition + * ```js + * $ionicTemplateCahce('myNgIncludeTemplate.html'); + * ```js + * angular.module('myApp', ['ionic']) + * .config(function($stateProvider, $ionicConfigProvider) { + * + * // disable preemptive template caching globally + * $ionicConfigProvider.prefetchTemplates(false); + * + * // disable individual states + * $stateProvider + * .state('tabs', { + * url: "/tab", + * abstract: true, + * prefetchTemplate: false, + * templateUrl: "tabs-templates/tabs.html" + * }) + * .state('tabs.home', { + * url: "/home", + * views: { + * 'home-tab': { + * prefetchTemplate: false, + * templateUrl: "tabs-templates/home.html", + * controller: 'HomeTabCtrl' + * } + * } + * }); + * }); + * ``` + */ +IonicModule +.factory('$ionicTemplateCache', [ +'$http', +'$templateCache', +'$timeout', +'$ionicConfig', +function($http, $templateCache, $timeout, $ionicConfig) { + var toCache = templatesToCache, + hasRun = false; + /** + * @ngdoc method + * @name $ionicTemplateCache + * @description Add template(s) to be cached. + * @param {string | array} string or array of strings of templates to cache. + */ + function $ionicTemplateCache(templates){ + if(toCache.length > 500) return false; + if(typeof templates === 'undefined')return run(); + if(isString(templates))templates = [templates]; + forEach(templates, function(template){ + toCache.push(template); + }); + // is this is being called after the initial IonicModule.run() + if(hasRun) run(); + } + + // run through methods - internal method + var run = function(){ + if($ionicConfig.prefetchTemplates === false)return + //console.log('prefetching', toCache); + //for testing + $ionicTemplateCache._runCount++; + + hasRun = true; + // ignore if race condition already zeroed out array + if(toCache.length === 0)return; + //console.log(toCache); + var i = 0; + while ( i < 5 && (template = toCache.pop()) ) { + // note that inline templates are ignored by this request + if (isString(template)) $http.get(template, { cache: $templateCache }); + i++; + } + // only preload 5 templates a second + if(toCache.length)$timeout(function(){run()}, 1000); + }; + + // exposing for testing + $ionicTemplateCache._runCount = 0; + // default method + return $ionicTemplateCache; +}]) + +/** + * @ngdoc config + * @name $ionicTemplateCache + * @module ionic + * @private + * + * Intercepts the $stateprovider.state() command to look for templateUrls that can be cached + */ +.config([ +'$stateProvider', +'$ionicConfigProvider', +function($stateProvider, $ionicConfigProvider) { + var stateProviderState = $stateProvider.state; + $stateProvider.state = function(stateName, definition) { + // don't even bother if it's disabled. note, another config may run after this, so it's not a catch-all + if($ionicConfigProvider.prefetchTemplates() !== false){ + var enabled = definition.prefetchTemplate != false; + if(enabled && isString(definition.templateUrl))templatesToCache.push(definition.templateUrl); + if(angular.isObject(definition.views)){ + for (var key in definition.views){ + enabled = definition.views[key].prefetchTemplate != false; + if(enabled && isString(definition.views[key].templateUrl)) templatesToCache.push(definition.views[key].templateUrl); + } + } + } + return stateProviderState.call($stateProvider, stateName, definition); + }; +}]) + +/** + * @ngdoc run + * @name $ionicTemplateCache + * @module ionic + * @private + * + * process the templateUrls collected by the $stateProvider, adding them to the cache + */ +.run(function($ionicTemplateCache) { + $ionicTemplateCache(); +}); + +})(); diff --git a/test/html/tabs-cache.html b/test/html/tabs-cache.html new file mode 100644 index 0000000000..5dd66ff0f0 --- /dev/null +++ b/test/html/tabs-cache.html @@ -0,0 +1,112 @@ + +
+ + + +Free and open source, Ionic offers a library of mobile-optimized HTML, CSS and JS components for building highly interactive apps.
+Built with Sass and optimized for AngularJS.
++ Tabs Nav Stack +
+Banging your head against a wall uses 150 calories an hour.
+Dogs have four toes on their hind feet, and five on their front feet.
+The ant can lift 50 times its own weight, can pull 30 times its own weight and always falls over on its right side when intoxicated.
+A cockroach will live nine days without it's head, before it starves to death.
+Polar bears are left handed.
++ Home + More Facts +
+111,111,111 x 111,111,111 = 12,345,678,987,654,321
+1 in every 4 Americans has appeared on T.V.
+11% of the world is left-handed.
+1 in 8 Americans has worked at a McDonalds restaurant.
+$283,200 is the absolute highest amount of money you can win on Jeopardy.
+101 Dalmatians, Peter Pan, Lady and the Tramp, and Mulan are the only Disney cartoons where both parents are present and don't die throughout the movie.
++ Home + Scientific Facts +
+Example of Ionic tabs. Navigate to each tab, and + navigate to child views of each tab and notice how + each tab has its own navigation history.
++ Scientific Facts +
+