1/** 2 * @license AngularJS v1.2.14 3 * (c) 2010-2014 Google, Inc. http://angularjs.org 4 * License: MIT 5 */ 6(function(window, angular, undefined) {'use strict'; 7 8 /** 9 * @ngdoc module 10 * @name ngRoute 11 * @description 12 * 13 * # ngRoute 14 * 15 * The `ngRoute` module provides routing and deeplinking services and directives for angular apps. 16 * 17 * ## Example 18 * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`. 19 * 20 * 21 * <div doc-module-components="ngRoute"></div> 22 */ 23 /* global -ngRouteModule */ 24 var ngRouteModule = angular.module('ngRoute', ['ng']). 25 provider('$route', $RouteProvider); 26 27 /** 28 * @ngdoc provider 29 * @name $routeProvider 30 * @function 31 * 32 * @description 33 * 34 * Used for configuring routes. 35 * 36 * ## Example 37 * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`. 38 * 39 * ## Dependencies 40 * Requires the {@link ngRoute `ngRoute`} module to be installed. 41 */ 42 function $RouteProvider(){ 43 function inherit(parent, extra) { 44 return angular.extend(new (angular.extend(function() {}, {prototype:parent}))(), extra); 45 } 46 47 var routes = {}; 48 49 /** 50 * @ngdoc method 51 * @name $routeProvider#when 52 * 53 * @param {string} path Route path (matched against `$location.path`). If `$location.path` 54 * contains redundant trailing slash or is missing one, the route will still match and the 55 * `$location.path` will be updated to add or drop the trailing slash to exactly match the 56 * route definition. 57 * 58 * * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up 59 * to the next slash are matched and stored in `$routeParams` under the given `name` 60 * when the route matches. 61 * * `path` can contain named groups starting with a colon and ending with a star: 62 * e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name` 63 * when the route matches. 64 * * `path` can contain optional named groups with a question mark: e.g.`:name?`. 65 * 66 * For example, routes like `/color/:color/largecode/:largecode*\/edit` will match 67 * `/color/brown/largecode/code/with/slashes/edit` and extract: 68 * 69 * * `color: brown` 70 * * `largecode: code/with/slashes`. 71 * 72 * 73 * @param {Object} route Mapping information to be assigned to `$route.current` on route 74 * match. 75 * 76 * Object properties: 77 * 78 * - `controller` ââ¬â `{(string|function()=}` ââ¬â Controller fn that should be associated with 79 * newly created scope or the name of a {@link angular.Module#controller registered 80 * controller} if passed as a string. 81 * - `controllerAs` ââ¬â `{string=}` ââ¬â A controller alias name. If present the controller will be 82 * published to scope under the `controllerAs` name. 83 * - `template` ââ¬â `{string=|function()=}` ââ¬â html template as a string or a function that 84 * returns an html template as a string which should be used by {@link 85 * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives. 86 * This property takes precedence over `templateUrl`. 87 * 88 * If `template` is a function, it will be called with the following parameters: 89 * 90 * - `{Array.<Object>}` - route parameters extracted from the current 91 * `$location.path()` by applying the current route 92 * 93 * - `templateUrl` ââ¬â `{string=|function()=}` ââ¬â path or function that returns a path to an html 94 * template that should be used by {@link ngRoute.directive:ngView ngView}. 95 * 96 * If `templateUrl` is a function, it will be called with the following parameters: 97 * 98 * - `{Array.<Object>}` - route parameters extracted from the current 99 * `$location.path()` by applying the current route 100 * 101 * - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should 102 * be injected into the controller. If any of these dependencies are promises, the router 103 * will wait for them all to be resolved or one to be rejected before the controller is 104 * instantiated. 105 * If all the promises are resolved successfully, the values of the resolved promises are 106 * injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is 107 * fired. If any of the promises are rejected the 108 * {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object 109 * is: 110 * 111 * - `key` ââ¬â `{string}`: a name of a dependency to be injected into the controller. 112 * - `factory` - `{string|function}`: If `string` then it is an alias for a service. 113 * Otherwise if function, then it is {@link auto.$injector#invoke injected} 114 * and the return value is treated as the dependency. If the result is a promise, it is 115 * resolved before its value is injected into the controller. Be aware that
116 * `ngRoute.$routeParams` will still refer to the previous route within these resolve 117 * functions. Use `$route.current.params` to access the new route parameters, instead. 118 * 119 * - `redirectTo` ââ¬â {(string|function())=} ââ¬â value to update 120 * {@link ng.$location $location} path with and trigger route redirection. 121 * 122 * If `redirectTo` is a function, it will be called with the following parameters: 123 * 124 * - `{Object.<string>}` - route parameters extracted from the current 125 * `$location.path()` by applying the current route templateUrl. 126 * - `{string}` - current `$location.path()` 127 * - `{Object}` - current `$location.search()` 128 * 129 * The custom `redirectTo` function is expected to return a string which will be used 130 * to update `$location.path()` and `$location.search()`. 131 * 132 * - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()` 133 * or `$location.hash()` changes. 134 * 135 * If the option is set to `false` and url in the browser changes, then 136 * `$routeUpdate` event is broadcasted on the root scope. 137 * 138 * - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive 139 * 140 * If the option is set to `true`, then the particular route can be matched without being 141 * case sensitive 142 * 143 * @returns {Object} self 144 * 145 * @description 146 * Adds a new route definition to the `$route` service. 147 */ 148 this.when = function(path, route) { 149 routes[path] = angular.extend( 150 {reloadOnSearch: true}, 151 route, 152 path && pathRegExp(path, route) 153 ); 154 155 // create redirection for trailing slashes 156 if (path) { 157 var redirectPath = (path[path.length-1] == '/') 158 ? path.substr(0, path.length-1) 159 : path +'/'; 160 161 routes[redirectPath] = angular.extend( 162 {redirectTo: path}, 163 pathRegExp(redirectPath, route) 164 ); 165 } 166 167 return this; 168 }; 169 170 /** 171 * @param path {string} path 172 * @param opts {Object} options 173 * @return {?Object} 174 * 175 * @description 176 * Normalizes the given path, returning a regular expression 177 * and the original path. 178 * 179 * Inspired by pathRexp in visionmedia/express/lib/utils.js. 180 */ 181 function pathRegExp(path, opts) { 182 var insensitive = opts.caseInsensitiveMatch, 183 ret = { 184 originalPath: path, 185 regexp: path 186 }, 187 keys = ret.keys = []; 188 189 path = path 190 .replace(/([().])/g, '\\$1') 191 .replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option){ 192 var optional = option === '?' ? option : null; 193 var star = option === '*' ? option : null; 194 keys.push({ name: key, optional: !!optional }); 195 slash = slash || ''; 196 return '' 197 + (optional ? '' : slash) 198 + '(?:' 199 + (optional ? slash : '') 200 + (star && '(.+?)' || '([^/]+)') 201 + (optional || '') 202 + ')' 203 + (optional || ''); 204 }) 205 .replace(/([\/$\*])/g, '\\$1'); 206 207 ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : ''); 208 return ret; 209 } 210 211 /** 212 * @ngdoc method 213 * @name $routeProvider#otherwise 214 * 215 * @description 216 * Sets route definition that will be used on route change when no other route definition 217 * is matched. 218 * 219 * @param {Object} params Mapping information to be assigned to `$route.current`. 220 * @returns {Object} self 221 */ 222 this.otherwise = function(params) { 223 this.when(null, params); 224 return this; 225 }; 226 227 228 this.$get = ['$rootScope', 229 '$location', 230 '$routeParams', 231 '$q', 232 '$injector', 233 '$http', 234 '$templateCache', 235 '$sce', 236 function($rootScope, $location, $routeParams, $q, $injector, $http, $templateCache, $sce) { 237 238 /** 239 * @ngdoc service 240 * @name $route 241 * @requires $location
242 * @requires $routeParams 243 * 244 * @property {Object} current Reference to the current route definition. 245 * The route definition contains: 246 * 247 * - `controller`: The controller constructor as define in route definition. 248 * - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for 249 * controller instantiation. The `locals` contain 250 * the resolved values of the `resolve` map. Additionally the `locals` also contain: 251 * 252 * - `$scope` - The current route scope. 253 * - `$template` - The current route template HTML. 254 * 255 * @property {Array.<Object>} routes Array of all configured routes. 256 * 257 * @description 258 * `$route` is used for deep-linking URLs to controllers and views (HTML partials). 259 * It watches `$location.url()` and tries to map the path to an existing route definition. 260 * 261 * Requires the {@link ngRoute `ngRoute`} module to be installed. 262 * 263 * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API. 264 * 265 * The `$route` service is typically used in conjunction with the 266 * {@link ngRoute.directive:ngView `ngView`} directive and the 267 * {@link ngRoute.$routeParams `$routeParams`} service. 268 * 269 * @example 270 This example shows how changing the URL hash causes the `$route` to match a route against the 271 URL, and the `ngView` pulls in the partial. 272 273 Note that this example is using {@link ng.directive:script inlined templates} 274 to get it working on jsfiddle as well. 275 276 <example name="$route-service" module="ngRouteExample" deps="angular-route.js" fixBase="true"> 277 <file name="index.html"> 278 <div ng-controller="MainCntl"> 279 Choose: 280 <a href="Book/Moby">Moby</a> | 281 <a href="Book/Moby/ch/1">Moby: Ch1</a> | 282 <a href="Book/Gatsby">Gatsby</a> | 283 <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> | 284 <a href="Book/Scarlet">Scarlet Letter</a><br/> 285 286 <div ng-view></div> 287 <hr /> 288 289 <pre>$location.path() = {{$location.path()}}</pre> 290 <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre> 291 <pre>$route.current.params = {{$route.current.params}}</pre> 292 <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre> 293 <pre>$routeParams = {{$routeParams}}</pre> 294 </div> 295 </file> 296 297 <file name="book.html"> 298 controller: {{name}}<br /> 299 Book Id: {{params.bookId}}<br /> 300 </file> 301 302 <file name="chapter.html"> 303 controller: {{name}}<br /> 304 Book Id: {{params.bookId}}<br /> 305 Chapter Id: {{params.chapterId}} 306 </file> 307 308 <file name="script.js"> 309 angular.module('ngRouteExample', ['ngRoute']) 310 311 .config(function($routeProvider, $locationProvider) { 312 $routeProvider.when('/Book/:bookId', { 313 templateUrl: 'book.html', 314 controller: BookCntl, 315 resolve: { 316 // I will cause a 1 second delay 317 delay: function($q, $timeout) { 318 var delay = $q.defer(); 319 $timeout(delay.resolve, 1000); 320 return delay.promise; 321 } 322 } 323 }); 324 $routeProvider.when('/Book/:bookId/ch/:chapterId', { 325 templateUrl: 'chapter.html', 326 controller: ChapterCntl 327 }); 328 329 // configure html5 to get links working on jsfiddle 330 $locationProvider.html5Mode(true); 331 }); 332 333 function MainCntl($scope, $route, $routeParams, $location) { 334 $scope.$route = $route; 335 $scope.$location = $location; 336 $scope.$routeParams = $routeParams; 337 } 338 339 function BookCntl($scope, $routeParams) { 340 $scope.name = "BookCntl"; 341 $scope.params = $routeParams; 342 } 343
344 function ChapterCntl($scope, $routeParams) { 345 $scope.name = "ChapterCntl"; 346 $scope.params = $routeParams; 347 } 348 </file> 349 350 <file name="protractor.js" type="protractor"> 351 it('should load and compile correct template', function() { 352 element(by.linkText('Moby: Ch1')).click(); 353 var content = element(by.css('[ng-view]')).getText(); 354 expect(content).toMatch(/controller\: ChapterCntl/); 355 expect(content).toMatch(/Book Id\: Moby/); 356 expect(content).toMatch(/Chapter Id\: 1/); 357 358 element(by.partialLinkText('Scarlet')).click(); 359 360 content = element(by.css('[ng-view]')).getText(); 361 expect(content).toMatch(/controller\: BookCntl/); 362 expect(content).toMatch(/Book Id\: Scarlet/); 363 }); 364 </file> 365 </example> 366 */ 367 368 /** 369 * @ngdoc event 370 * @name $route#$routeChangeStart 371 * @eventType broadcast on root scope 372 * @description 373 * Broadcasted before a route change. At this point the route services starts 374 * resolving all of the dependencies needed for the route change to occur. 375 * Typically this involves fetching the view template as well as any dependencies 376 * defined in `resolve` route property. Once all of the dependencies are resolved 377 * `$routeChangeSuccess` is fired. 378 * 379 * @param {Object} angularEvent Synthetic event object. 380 * @param {Route} next Future route information. 381 * @param {Route} current Current route information. 382 */ 383 384 /** 385 * @ngdoc event 386 * @name $route#$routeChangeSuccess 387 * @eventType broadcast on root scope 388 * @description 389 * Broadcasted after a route dependencies are resolved. 390 * {@link ngRoute.directive:ngView ngView} listens for the directive 391 * to instantiate the controller and render the view. 392 * 393 * @param {Object} angularEvent Synthetic event object. 394 * @param {Route} current Current route information. 395 * @param {Route|Undefined} previous Previous route information, or undefined if current is 396 * first route entered. 397 */ 398 399 /** 400 * @ngdoc event 401 * @name $route#$routeChangeError 402 * @eventType broadcast on root scope 403 * @description 404 * Broadcasted if any of the resolve promises are rejected. 405 * 406 * @param {Object} angularEvent Synthetic event object 407 * @param {Route} current Current route information. 408 * @param {Route} previous Previous route information. 409 * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise. 410 */ 411 412 /** 413 * @ngdoc event 414 * @name $route#$routeUpdate 415 * @eventType broadcast on root scope 416 * @description 417 * 418 * The `reloadOnSearch` property has been set to false, and we are reusing the same 419 * instance of the Controller. 420 */ 421 422 var forceReload = false, 423 $route = { 424 routes: routes, 425 426 /** 427 * @ngdoc method 428 * @name $route#reload 429 * 430 * @description 431 * Causes `$route` service to reload the current route even if 432 * {@link ng.$location $location} hasn't changed. 433 * 434 * As a result of that, {@link ngRoute.directive:ngView ngView} 435 * creates new scope, reinstantiates the controller. 436 */ 437 reload: function() { 438 forceReload = true; 439 $rootScope.$evalAsync(updateRoute); 440 } 441 }; 442 443 $rootScope.$on('$locationChangeSuccess', updateRoute); 444 445 return $route; 446
447 ///////////////////////////////////////////////////// 448 449 /** 450 * @param on {string} current url 451 * @param route {Object} route regexp to match the url against 452 * @return {?Object} 453 * 454 * @description 455 * Check if the route matches the current url. 456 * 457 * Inspired by match in 458 * visionmedia/express/lib/router/router.js. 459 */ 460 function switchRouteMatcher(on, route) { 461 var keys = route.keys, 462 params = {}; 463 464 if (!route.regexp) return null; 465 466 var m = route.regexp.exec(on); 467 if (!m) return null; 468 469 for (var i = 1, len = m.length; i < len; ++i) { 470 var key = keys[i - 1]; 471 472 var val = 'string' == typeof m[i] 473 ? decodeURIComponent(m[i]) 474 : m[i]; 475 476 if (key && val) { 477 params[key.name] = val; 478 } 479 } 480 return params; 481 } 482 483 function updateRoute() { 484 var next = parseRoute(), 485 last = $route.current; 486 487 if (next && last && next.$$route === last.$$route 488 && angular.equals(next.pathParams, last.pathParams) 489 && !next.reloadOnSearch && !forceReload) { 490 last.params = next.params; 491 angular.copy(last.params, $routeParams); 492 $rootScope.$broadcast('$routeUpdate', last); 493 } else if (next || last) { 494 forceReload = false; 495 $rootScope.$broadcast('$routeChangeStart', next, last); 496 $route.current = next; 497 if (next) { 498 if (next.redirectTo) { 499 if (angular.isString(next.redirectTo)) { 500 $location.path(interpolate(next.redirectTo, next.params)).search(next.params) 501 .replace(); 502 } else { 503 $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search())) 504 .replace(); 505 } 506 } 507 } 508 509 $q.when(next). 510 then(function() { 511 if (next) { 512 var locals = angular.extend({}, next.resolve), 513 template, templateUrl; 514 515 angular.forEach(locals, function(value, key) { 516 locals[key] = angular.isString(value) ? 517 $injector.get(value) : $injector.invoke(value); 518 }); 519 520 if (angular.isDefined(template = next.template)) { 521 if (angular.isFunction(template)) { 522 template = template(next.params); 523 } 524 } else if (angular.isDefined(templateUrl = next.templateUrl)) { 525 if (angular.isFunction(templateUrl)) { 526 templateUrl = templateUrl(next.params); 527 } 528 templateUrl = $sce.getTrustedResourceUrl(templateUrl); 529 if (angular.isDefined(templateUrl)) { 530 next.loadedTemplateUrl = templateUrl; 531 template = $http.get(templateUrl, {cache: $templateCache}). 532 then(function(response) { return response.data; }); 533 } 534 } 535 if (angular.isDefined(template)) { 536 locals['$template'] = template; 537 } 538 return $q.all(locals); 539 } 540 }). 541 // after route change 542 then(function(locals) { 543 if (next == $route.current) { 544 if (next) { 545 next.locals = locals; 546 angular.copy(next.params, $routeParams); 547 } 548 $rootScope.$broadcast('$routeChangeSuccess', next, last); 549 } 550 }, function(error) { 551 if (next == $route.current) { 552 $rootScope.$broadcast('$routeChangeError', next, last, error); 553 } 554 }); 555 } 556 } 557 558 559 /** 560 * @returns {Object} the current active route, by matching it against the URL 561 */ 562 function parseRoute() { 563 // Match a route 564 var params, match; 565 angular.forEach(routes, function(route, path) { 566 if (!match && (params = switchRouteMatcher($location.path(), route))) { 567 match = inherit(route, { 568 params: angular.extend({}, $location.search(), params), 569 pathParams: params}); 570 match.$$route = route; 571 } 572 }); 573 // No route matched; fallback to "otherwise" route 574 return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}}); 575 } 576 577 /** 578 * @returns {string} interpolation of the redirect path with the parameters 579 */ 580 function interpolate(string, params) { 581 var result = []; 582 angular.forEach((string||'').split(':'), function(segment, i) { 583 if (i === 0) { 584 result.push(segment); 585 } else { 586 var segmentMatch = segment.match(/(\w+)(.*)/); 587 var key = segmentMatch[1]; 588 result.push(params[key]); 589 result.push(segmentMatch[2] || ''); 590 delete params[key]; 591 } 592 }); 593 return result.join(''); 594 } 595 }]; 596 } 597
598 ngRouteModule.provider('$routeParams', $RouteParamsProvider); 599 600 601 /** 602 * @ngdoc service 603 * @name $routeParams 604 * @requires $route 605 * 606 * @description 607 * The `$routeParams` service allows you to retrieve the current set of route parameters. 608 * 609 * Requires the {@link ngRoute `ngRoute`} module to be installed. 610 * 611 * The route parameters are a combination of {@link ng.$location `$location`}'s 612 * {@link ng.$location#search `search()`} and {@link ng.$location#path `path()`}. 613 * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched. 614 * 615 * In case of parameter name collision, `path` params take precedence over `search` params. 616 * 617 * The service guarantees that the identity of the `$routeParams` object will remain unchanged 618 * (but its properties will likely change) even when a route change occurs. 619 * 620 * Note that the `$routeParams` are only updated *after* a route change completes successfully. 621 * This means that you cannot rely on `$routeParams` being correct in route resolve functions. 622 * Instead you can use `$route.current.params` to access the new route's parameters. 623 * 624 * @example 625 * ```js 626 * // Given: 627 * // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby 628 * // Route: /Chapter/:chapterId/Section/:sectionId 629 * // 630 * // Then 631 * $routeParams ==> {chapterId:1, sectionId:2, search:'moby'} 632 * ``` 633 */ 634 function $RouteParamsProvider() { 635 this.$get = function() { return {}; }; 636 } 637 638 ngRouteModule.directive('ngView', ngViewFactory); 639 ngRouteModule.directive('ngView', ngViewFillContentFactory); 640 641 642 /** 643 * @ngdoc directive 644 * @name ngView 645 * @restrict ECA 646 * 647 * @description 648 * # Overview 649 * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by 650 * including the rendered template of the current route into the main layout (`index.html`) file. 651 * Every time the current route changes, the included view changes with it according to the 652 * configuration of the `$route` service. 653 * 654 * Requires the {@link ngRoute `ngRoute`} module to be installed. 655 * 656 * @animations 657 * enter - animation is used to bring new content into the browser. 658 * leave - animation is used to animate existing content away. 659 * 660 * The enter and leave animation occur concurrently. 661 * 662 * @scope 663 * @priority 400 664 * @param {string=} onload Expression to evaluate whenever the view updates. 665 * 666 * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll 667 * $anchorScroll} to scroll the viewport after the view is updated. 668 * 669 * - If the attribute is not set, disable scrolling. 670 * - If the attribute is set without value, enable scrolling. 671 * - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated 672 * as an expression yields a truthy value. 673 * @example 674 <example name="ngView-directive" module="ngViewExample" 675 deps="angular-route.js;angular-animate.js" 676 animations="true" fixBase="true"> 677 <file name="index.html"> 678 <div ng-controller="MainCntl as main"> 679 Choose: 680 <a href="Book/Moby">Moby</a> | 681 <a href="Book/Moby/ch/1">Moby: Ch1</a> | 682 <a href="Book/Gatsby">Gatsby</a> | 683 <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> | 684 <a href="Book/Scarlet">Scarlet Letter</a><br/> 685 686 <div class="view-animate-container"> 687 <div ng-view class="view-animate"></div> 688 </div> 689 <hr /> 690 691 <pre>$location.path() = {{main.$location.path()}}</pre> 692 <pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre> 693 <pre>$route.current.params = {{main.$route.current.params}}</pre> 694 <pre>$route.current.scope.name = {{main.$route.current.scope.name}}</pre> 695 <pre>$routeParams = {{main.$routeParams}}</pre> 696 </div> 697 </file> 698 699 <file name="book.html"> 700 <div> 701 controller: {{book.name}}<br /> 702 Book Id: {{book.params.bookId}}<br /> 703 </div> 704 </file> 705 706 <file name="chapter.html"> 707 <div> 708 controller: {{chapter.name}}<br /> 709 Book Id: {{chapter.params.bookId}}<br /> 710 Chapter Id: {{chapter.params.chapterId}} 711 </div> 712 </file> 713 714 <file name="animations.css"> 715 .view-animate-container { 716 position:relative; 717 height:100px!important; 718 position:relative; 719 background:white; 720 border:1px solid black; 721 height:40px; 722 overflow:hidden; 723 } 724 725 .view-animate { 726 padding:10px; 727 } 728 729 .view-animate.ng-enter, .view-animate.ng-leave { 730 -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; 731 transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; 732 733 display:block; 734 width:100%; 735 border-left:1px solid black; 736 737 position:absolute; 738 top:0; 739 left:0; 740 right:0; 741 bottom:0; 742 padding:10px; 743 } 744 745 .view-animate.ng-enter { 746 left:100%; 747 } 748 .view-animate.ng-enter.ng-enter-active { 749 left:0; 750 } 751 .view-animate.ng-leave.ng-leave-active { 752 left:-100%; 753 } 754 </file> 755 756 <file name="script.js"> 757 angular.module('ngViewExample', ['ngRoute', 'ngAnimate'], 758 function($routeProvider, $locationProvider) { 759 $routeProvider.when('/Book/:bookId', { 760 templateUrl: 'book.html', 761 controller: BookCntl, 762 controllerAs: 'book' 763 }); 764 $routeProvider.when('/Book/:bookId/ch/:chapterId', { 765 templateUrl: 'chapter.html', 766 controller: ChapterCntl, 767 controllerAs: 'chapter' 768 }); 769 770 // configure html5 to get links working on jsfiddle 771 $locationProvider.html5Mode(true); 772 }); 773
774 function MainCntl($route, $routeParams, $location) { 775 this.$route = $route; 776 this.$location = $location; 777 this.$routeParams = $routeParams; 778 } 779 780 function BookCntl($routeParams) { 781 this.name = "BookCntl"; 782 this.params = $routeParams; 783 } 784 785 function ChapterCntl($routeParams) { 786 this.name = "ChapterCntl"; 787 this.params = $routeParams; 788 } 789 </file> 790 791 <file name="protractor.js" type="protractor"> 792 it('should load and compile correct template', function() { 793 element(by.linkText('Moby: Ch1')).click(); 794 var content = element(by.css('[ng-view]')).getText(); 795 expect(content).toMatch(/controller\: ChapterCntl/); 796 expect(content).toMatch(/Book Id\: Moby/); 797 expect(content).toMatch(/Chapter Id\: 1/); 798 799 element(by.partialLinkText('Scarlet')).click(); 800 801 content = element(by.css('[ng-view]')).getText(); 802 expect(content).toMatch(/controller\: BookCntl/); 803 expect(content).toMatch(/Book Id\: Scarlet/); 804 }); 805 </file> 806 </example> 807 */ 808 809 810 /** 811 * @ngdoc event 812 * @name ngView#$viewContentLoaded 813 * @eventType emit on the current ngView scope 814 * @description 815 * Emitted every time the ngView content is reloaded. 816 */ 817 ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate']; 818 function ngViewFactory( $route, $anchorScroll, $animate) { 819 return { 820 restrict: 'ECA', 821 terminal: true, 822 priority: 400, 823 transclude: 'element', 824 link: function(scope, $element, attr, ctrl, $transclude) { 825 var currentScope, 826 currentElement, 827 previousElement, 828 autoScrollExp = attr.autoscroll, 829 onloadExp = attr.onload || ''; 830 831 scope.$on('$routeChangeSuccess', update); 832 update(); 833 834 function cleanupLastView() { 835 if(previousElement) { 836 previousElement.remove(); 837 previousElement = null; 838 } 839 if(currentScope) { 840 currentScope.$destroy(); 841 currentScope = null; 842 } 843 if(currentElement) { 844 $animate.leave(currentElement, function() { 845 previousElement = null; 846 }); 847 previousElement = currentElement; 848 currentElement = null; 849 } 850 } 851 852 function update() { 853 var locals = $route.current && $route.current.locals, 854 template = locals && locals.$template; 855 856 if (angular.isDefined(template)) { 857 var newScope = scope.$new(); 858 var current = $route.current; 859 860 // Note: This will also link all children of ng-view that were contained in the original 861 // html. If that content contains controllers, ... they could pollute/change the scope. 862 // However, using ng-view on an element with additional content does not make sense... 863 // Note: We can't remove them in the cloneAttchFn of $transclude as that 864 // function is called before linking the content, which would apply child 865 // directives to non existing elements. 866 var clone = $transclude(newScope, function(clone) { 867 $animate.enter(clone, null, currentElement || $element, function onNgViewEnter () { 868 if (angular.isDefined(autoScrollExp) 869 && (!autoScrollExp || scope.$eval(autoScrollExp))) { 870 $anchorScroll(); 871 } 872 }); 873 cleanupLastView(); 874 }); 875 876 currentElement = clone; 877 currentScope = current.scope = newScope; 878 currentScope.$emit('$viewContentLoaded'); 879 currentScope.$eval(onloadExp); 880 } else { 881 cleanupLastView(); 882 } 883 } 884 } 885 }; 886 } 887 888// This directive is called during the $transclude call of the first `ngView` directive. 889// It will replace and compile the content of the element with the loaded template. 890// We need this directive so that the element content is already filled when 891// the link function of another directive on the same element as ngView 892// is called. 893 ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route']; 894 function ngViewFillContentFactory($compile, $controller, $route) { 895 return { 896 restrict: 'ECA', 897 priority: -400, 898 link: function(scope, $element) { 899 var current = $route.current, 900 locals = current.locals; 901 902 $element.html(locals.$template); 903 904 var link = $compile($element.contents()); 905 906 if (current.controller) { 907 locals.$scope = scope; 908 var controller = $controller(current.controller, locals); 909 if (current.controllerAs) { 910 scope[current.controllerAs] = controller; 911 } 912 $element.data('$ngControllerController', controller); 913 $element.children().data('$ngControllerController', controller); 914 } 915 916 link(scope); 917 } 918 }; 919 } 920 921 922})(window, window.angular);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.