Digital Office Automation System Backend
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

angular-route.js 32KB

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