| @@ -0,0 +1,9 @@ | ||
| { | ||
| "name": "angular-animate", | ||
| "version": "1.4.3", | ||
| "main": "./angular-animate.js", | ||
| "ignore": [], | ||
| "dependencies": { | ||
| "angular": "1.4.3" | ||
| } | ||
| } |
| @@ -0,0 +1,2 @@ | ||
| require('./angular-animate'); | ||
| module.exports = 'ngAnimate'; |
| @@ -0,0 +1,26 @@ | ||
| { | ||
| "name": "angular-animate", | ||
| "version": "1.4.3", | ||
| "description": "AngularJS module for animations", | ||
| "main": "index.js", | ||
| "scripts": { | ||
| "test": "echo \"Error: no test specified\" && exit 1" | ||
| }, | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/angular/angular.js.git" | ||
| }, | ||
| "keywords": [ | ||
| "angular", | ||
| "framework", | ||
| "browser", | ||
| "animation", | ||
| "client-side" | ||
| ], | ||
| "author": "Angular Core Team <angular-core+npm@google.com>", | ||
| "license": "MIT", | ||
| "bugs": { | ||
| "url": "https://github.com/angular/angular.js/issues" | ||
| }, | ||
| "homepage": "http://angularjs.org" | ||
| } |
| @@ -0,0 +1,35 @@ | ||
| { | ||
| "name": "angular-moment-service", | ||
| "version": "0.1.0", | ||
| "authors": [ | ||
| "Igor Rafael <igor.rafael@gmail.com>" | ||
| ], | ||
| "description": "AngularJS Service for dependency injection of moment.js\"", | ||
| "keywords": [ | ||
| "angular", | ||
| "momentjs" | ||
| ], | ||
| "license": "MIT", | ||
| "ignore": [ | ||
| "src", | ||
| "**/.*", | ||
| "node_modules", | ||
| "bower_components", | ||
| "test", | ||
| "tests" | ||
| ], | ||
| "dependencies": { | ||
| "momentjs": "~2.8.3" | ||
| }, | ||
| "homepage": "https://github.com/assisrafael/angular-momentjs", | ||
| "_release": "0.1.0", | ||
| "_resolution": { | ||
| "type": "version", | ||
| "tag": "0.1.0", | ||
| "commit": "fdedbb1f335108d443150e70494a6e7c36a3e051" | ||
| }, | ||
| "_source": "git://github.com/assisrafael/angular-momentjs.git", | ||
| "_target": "~0.1.0", | ||
| "_originalSource": "angular-momentjs-service", | ||
| "_direct": true | ||
| } |
| @@ -0,0 +1,22 @@ | ||
| The MIT License (MIT) | ||
|
|
||
| Copyright (c) 2014 Igor Rafael | ||
|
|
||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
|
|
||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
|
|
||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. | ||
|
|
| @@ -0,0 +1,49 @@ | ||
| angular-momentjs-service | ||
| ======================== | ||
|
|
||
| [AngularJS](https://angularjs.org) Wrapper for [Moment.js](http://momentjs.com) whithout registering it in the global scope. | ||
|
|
||
|
|
||
| How to use | ||
| ---------- | ||
|
|
||
| 1. Install angular-momentjs-service via bower: | ||
| ``` | ||
| bower install --save angular-momentjs-service | ||
| ``` | ||
|
|
||
| 2. Include angular-momentjs-service into your project. | ||
| ```HTML | ||
| <script src="angular-momentjs-service.min.js"></script> | ||
| ``` | ||
|
|
||
| 3. Add ```angular-momentjs``` module in the dependencies of a angular module: | ||
| ```JavaScript | ||
| angular.module('exampleApp', ['angular-momentjs']) | ||
| ``` | ||
|
|
||
| 4. Inject the MomentJS service into a controller, a directive, etc: | ||
| ```JavaScript | ||
| .controller('ExampleCtrl', ['$scope','MomentJS', function($scope, moment){ | ||
| $scope.now = moment(); | ||
| }]) | ||
| ``` | ||
|
|
||
| 5. Use the full MomentJS API as you wish. | ||
|
|
||
| How to test | ||
| ----------- | ||
|
|
||
| Soon... | ||
|
|
||
| How to contribute | ||
| ----------------- | ||
|
|
||
| I am very glad to see this project living with pull requests. | ||
|
|
||
| LICENSE | ||
| ------- | ||
|
|
||
| Copyright (c) 2014 Igor Rafael | ||
|
|
||
| Licensed under the MIT license. |
| @@ -0,0 +1,24 @@ | ||
| { | ||
| "name": "angular-moment-service", | ||
| "version": "0.1.0", | ||
| "authors": [ | ||
| "Igor Rafael <igor.rafael@gmail.com>" | ||
| ], | ||
| "description": "AngularJS Service for dependency injection of moment.js\"", | ||
| "keywords": [ | ||
| "angular", | ||
| "momentjs" | ||
| ], | ||
| "license": "MIT", | ||
| "ignore": [ | ||
| "src", | ||
| "**/.*", | ||
| "node_modules", | ||
| "bower_components", | ||
| "test", | ||
| "tests" | ||
| ], | ||
| "dependencies": { | ||
| "momentjs": "~2.8.3" | ||
| } | ||
| } |
| @@ -0,0 +1,20 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8"> | ||
| <title>AngularJS Service for MomentJS dependency injection</title> | ||
| <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script> | ||
| <script src="../release/angular-momentjs-service.js"></script> | ||
| <script> | ||
| angular.module('exampleApp', ['angular-momentjs']) | ||
| .controller('ExampleCtrl', ['$scope','MomentJS', function($scope, moment){ | ||
| $scope.now = moment(); | ||
| }]) | ||
| </script> | ||
| </head> | ||
| <body ng-app="exampleApp"> | ||
| <div ng-controller="ExampleCtrl"> | ||
| {{now}} | ||
| </div> | ||
| </body> | ||
| </html> |
| @@ -0,0 +1,38 @@ | ||
| var gulp = require('gulp'), | ||
| path = require('path'), | ||
| plugins = require('gulp-load-plugins')({ | ||
| config: path.join(__dirname, 'package.json') | ||
| }); | ||
|
|
||
| gulp.task('build', function() { | ||
| var pkg = require('./package.json'); | ||
|
|
||
| var header = ['/**', | ||
| ' * <%= pkg.name %>', | ||
| ' * <%= pkg.description %>', | ||
| ' * @version v<%= pkg.version %>', | ||
| ' * @link <%= pkg.homepage %>', | ||
| ' * @license <%= pkg.license %>', | ||
| ' */', | ||
| '(function (angular) {', | ||
| ' var global = {};', | ||
| '', | ||
| ''].join('\n'); | ||
|
|
||
| var footer = [ | ||
| '', | ||
| '})(angular);', | ||
| ''].join('\n'); | ||
|
|
||
| gulp.src([ | ||
| 'bower_components/momentjs/moment.js', | ||
| 'src/angular-momentjs-service.js' | ||
| ]) | ||
| .pipe(plugins.concat('angular-momentjs-service.js')) | ||
| .pipe(plugins.header(header, {pkg: pkg})) | ||
| .pipe(plugins.footer(footer)) | ||
| .pipe(gulp.dest('./release/')) | ||
| .pipe(plugins.uglify()) | ||
| .pipe(plugins.concat('angular-momentjs-service.min.js')) | ||
| .pipe(gulp.dest('./release/')); | ||
| }); |
| @@ -0,0 +1,19 @@ | ||
| { | ||
| "name": "angular-moment-service", | ||
| "version": "0.1.0", | ||
| "description": "AngularJS Service for dependency injection of moment.js", | ||
| "main": "index.js", | ||
| "scripts": { | ||
| "start": "gulp build" | ||
| }, | ||
| "author": "igor.rafael@gmail.com", | ||
| "license": "MIT", | ||
| "devDependencies": { | ||
| "gulp": "^3.8.8", | ||
| "gulp-concat": "^2.4.1", | ||
| "gulp-footer": "^1.0.5", | ||
| "gulp-header": "^1.1.1", | ||
| "gulp-load-plugins": "^0.6.0", | ||
| "gulp-uglify": "^1.0.1" | ||
| } | ||
| } |
| @@ -0,0 +1,19 @@ | ||
| { | ||
| "name": "angular-sanitize", | ||
| "version": "1.4.3", | ||
| "main": "./angular-sanitize.js", | ||
| "ignore": [], | ||
| "dependencies": { | ||
| "angular": "1.4.3" | ||
| }, | ||
| "homepage": "https://github.com/angular/bower-angular-sanitize", | ||
| "_release": "1.4.3", | ||
| "_resolution": { | ||
| "type": "version", | ||
| "tag": "v1.4.3", | ||
| "commit": "0367ee4c3f9cb8af5d1da9ec35b71a8b523d9fc0" | ||
| }, | ||
| "_source": "git://github.com/angular/bower-angular-sanitize.git", | ||
| "_target": "1.4.3", | ||
| "_originalSource": "angular-sanitize" | ||
| } |
| @@ -0,0 +1,68 @@ | ||
| # packaged angular-sanitize | ||
|
|
||
| This repo is for distribution on `npm` and `bower`. The source for this module is in the | ||
| [main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngSanitize). | ||
| Please file issues and pull requests against that repo. | ||
|
|
||
| ## Install | ||
|
|
||
| You can install this package either with `npm` or with `bower`. | ||
|
|
||
| ### npm | ||
|
|
||
| ```shell | ||
| npm install angular-sanitize | ||
| ``` | ||
|
|
||
| Then add `ngSanitize` as a dependency for your app: | ||
|
|
||
| ```javascript | ||
| angular.module('myApp', [require('angular-sanitize')]); | ||
| ``` | ||
|
|
||
| ### bower | ||
|
|
||
| ```shell | ||
| bower install angular-sanitize | ||
| ``` | ||
|
|
||
| Add a `<script>` to your `index.html`: | ||
|
|
||
| ```html | ||
| <script src="/bower_components/angular-sanitize/angular-sanitize.js"></script> | ||
| ``` | ||
|
|
||
| Then add `ngSanitize` as a dependency for your app: | ||
|
|
||
| ```javascript | ||
| angular.module('myApp', ['ngSanitize']); | ||
| ``` | ||
|
|
||
| ## Documentation | ||
|
|
||
| Documentation is available on the | ||
| [AngularJS docs site](http://docs.angularjs.org/api/ngSanitize). | ||
|
|
||
| ## License | ||
|
|
||
| The MIT License | ||
|
|
||
| Copyright (c) 2010-2015 Google, Inc. http://angularjs.org | ||
|
|
||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
|
|
||
| The above copyright notice and this permission notice shall be included in | ||
| all copies or substantial portions of the Software. | ||
|
|
||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| THE SOFTWARE. |
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "name": "angular-sanitize", | ||
| "version": "1.4.3", | ||
| "main": "./angular-sanitize.js", | ||
| "ignore": [], | ||
| "dependencies": { | ||
| "angular": "1.4.3" | ||
| } | ||
| } |
| @@ -0,0 +1,2 @@ | ||
| require('./angular-sanitize'); | ||
| module.exports = 'ngSanitize'; |
| @@ -0,0 +1,26 @@ | ||
| { | ||
| "name": "angular-sanitize", | ||
| "version": "1.4.3", | ||
| "description": "AngularJS module for sanitizing HTML", | ||
| "main": "index.js", | ||
| "scripts": { | ||
| "test": "echo \"Error: no test specified\" && exit 1" | ||
| }, | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/angular/angular.js.git" | ||
| }, | ||
| "keywords": [ | ||
| "angular", | ||
| "framework", | ||
| "browser", | ||
| "html", | ||
| "client-side" | ||
| ], | ||
| "author": "Angular Core Team <angular-core+npm@google.com>", | ||
| "license": "MIT", | ||
| "bugs": { | ||
| "url": "https://github.com/angular/angular.js/issues" | ||
| }, | ||
| "homepage": "http://angularjs.org" | ||
| } |
| @@ -0,0 +1,33 @@ | ||
| { | ||
| "name": "angular-ui-router", | ||
| "version": "0.2.13", | ||
| "main": "./release/angular-ui-router.js", | ||
| "dependencies": { | ||
| "angular": ">= 1.0.8" | ||
| }, | ||
| "ignore": [ | ||
| "**/.*", | ||
| "node_modules", | ||
| "bower_components", | ||
| "component.json", | ||
| "package.json", | ||
| "lib", | ||
| "config", | ||
| "sample", | ||
| "test", | ||
| "tests", | ||
| "ngdoc_assets", | ||
| "Gruntfile.js", | ||
| "files.js" | ||
| ], | ||
| "homepage": "https://github.com/angular-ui/ui-router", | ||
| "_release": "0.2.13", | ||
| "_resolution": { | ||
| "type": "version", | ||
| "tag": "0.2.13", | ||
| "commit": "c3d543aae43d4600512520a0d70723ac31f2cb62" | ||
| }, | ||
| "_source": "git://github.com/angular-ui/ui-router.git", | ||
| "_target": "0.2.13", | ||
| "_originalSource": "angular-ui-router" | ||
| } |
| @@ -0,0 +1,65 @@ | ||
|
|
||
| # Report an Issue | ||
|
|
||
| Help us make UI-Router better! If you think you might have found a bug, or some other weirdness, start by making sure | ||
| it hasn't already been reported. You can [search through existing issues](https://github.com/angular-ui/ui-router/search?q=wat%3F&type=Issues) | ||
| to see if someone's reported one similar to yours. | ||
|
|
||
| If not, then [create a plunkr](http://bit.ly/UIR-Plunk) that demonstrates the problem (try to use as little code | ||
| as possible: the more minimalist, the faster we can debug it). | ||
|
|
||
| Next, [create a new issue](https://github.com/angular-ui/ui-router/issues/new) that briefly explains the problem, | ||
| and provides a bit of background as to the circumstances that triggered it. Don't forget to include the link to | ||
| that plunkr you created! | ||
|
|
||
| **Note**: If you're unsure how a feature is used, or are encountering some unexpected behavior that you aren't sure | ||
| is a bug, it's best to talk it out on | ||
| [StackOverflow](http://stackoverflow.com/questions/ask?tags=angularjs,angular-ui-router) before reporting it. This | ||
| keeps development streamlined, and helps us focus on building great software. | ||
|
|
||
|
|
||
| Issues only! | | ||
| -------------| | ||
| Please keep in mind that the issue tracker is for *issues*. Please do *not* post an issue if you need help or support. Instead, see one of the above-mentioned forums or [IRC](irc://irc.freenode.net/#angularjs). | | ||
|
|
||
| ####Purple Labels | ||
| A purple label means that **you** need to take some further action. | ||
| - : Your issue is not specific enough, or there is no clear action that we can take. Please clarify and refine your issue. | ||
| - : Please [create a plunkr](http://bit.ly/UIR-Plunk) | ||
| - : We suspect your issue is really a help request, or could be answered by the community. Please ask your question on [StackOverflow](http://stackoverflow.com/questions/ask?tags=angularjs,angular-ui-router). If you determine that is an actual issue, please explain why. | ||
|
|
||
| If your issue gets labeled with purple label, no further action will be taken until you respond to the label appropriately. | ||
|
|
||
| # Contribute | ||
|
|
||
| **(1)** See the **[Developing](#developing)** section below, to get the development version of UI-Router up and running on your local machine. | ||
|
|
||
| **(2)** Check out the [roadmap](https://github.com/angular-ui/ui-router/milestones) to see where the project is headed, and if your feature idea fits with where we're headed. | ||
|
|
||
| **(3)** If you're not sure, [open an RFC](https://github.com/angular-ui/ui-router/issues/new?title=RFC:%20My%20idea) to get some feedback on your idea. | ||
|
|
||
| **(4)** Finally, commit some code and open a pull request. Code & commits should abide by the following rules: | ||
|
|
||
| - *Always* have test coverage for new features (or regression tests for bug fixes), and *never* break existing tests | ||
| - Commits should represent one logical change each; if a feature goes through multiple iterations, squash your commits down to one | ||
| - Make sure to follow the [Angular commit message format](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit-message-format) so your change will appear in the changelog of the next release. | ||
| - Changes should always respect the coding style of the project | ||
|
|
||
|
|
||
|
|
||
| # Developing | ||
|
|
||
| UI-Router uses <code>grunt >= 0.4.x</code>. Make sure to upgrade your environment and read the | ||
| [Migration Guide](http://gruntjs.com/upgrading-from-0.3-to-0.4). | ||
|
|
||
| Dependencies for building from source and running tests: | ||
|
|
||
| * [grunt-cli](https://github.com/gruntjs/grunt-cli) - run: `$ npm install -g grunt-cli` | ||
| * Then, install the development dependencies by running `$ npm install` from the project directory | ||
|
|
||
| There are a number of targets in the gruntfile that are used to generating different builds: | ||
|
|
||
| * `grunt`: Perform a normal build, runs jshint and karma tests | ||
| * `grunt build`: Perform a normal build | ||
| * `grunt dist`: Perform a clean build and generate documentation | ||
| * `grunt dev`: Run dev server (sample app) and watch for changes, builds and runs karma tests on changes. |
| @@ -0,0 +1,21 @@ | ||
| The MIT License | ||
|
|
||
| Copyright (c) 2014 The AngularUI Team, Karsten Sperling | ||
|
|
||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
|
|
||
| The above copyright notice and this permission notice shall be included in | ||
| all copies or substantial portions of the Software. | ||
|
|
||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| THE SOFTWARE. |
| @@ -0,0 +1,243 @@ | ||
| # AngularUI Router [](https://travis-ci.org/angular-ui/ui-router) | ||
|
|
||
| #### The de-facto solution to flexible routing with nested views | ||
| --- | ||
| **[Download 0.2.11](http://angular-ui.github.io/ui-router/release/angular-ui-router.js)** (or **[Minified](http://angular-ui.github.io/ui-router/release/angular-ui-router.min.js)**) **|** | ||
| **[Guide](https://github.com/angular-ui/ui-router/wiki) |** | ||
| **[API](http://angular-ui.github.io/ui-router/site) |** | ||
| **[Sample](http://angular-ui.github.com/ui-router/sample/) ([Src](https://github.com/angular-ui/ui-router/tree/gh-pages/sample)) |** | ||
| **[FAQ](https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions) |** | ||
| **[Resources](#resources) |** | ||
| **[Report an Issue](https://github.com/angular-ui/ui-router/blob/master/CONTRIBUTING.md#report-an-issue) |** | ||
| **[Contribute](https://github.com/angular-ui/ui-router/blob/master/CONTRIBUTING.md#contribute) |** | ||
| **[Help!](http://stackoverflow.com/questions/ask?tags=angularjs,angular-ui-router) |** | ||
| **[Discuss](https://groups.google.com/forum/#!categories/angular-ui/router)** | ||
|
|
||
| --- | ||
|
|
||
| AngularUI Router is a routing framework for [AngularJS](http://angularjs.org), which allows you to organize the | ||
| parts of your interface into a [*state machine*](https://en.wikipedia.org/wiki/Finite-state_machine). Unlike the | ||
| [`$route` service](http://docs.angularjs.org/api/ngRoute.$route) in the Angular ngRoute module, which is organized around URL | ||
| routes, UI-Router is organized around [*states*](https://github.com/angular-ui/ui-router/wiki), | ||
| which may optionally have routes, as well as other behavior, attached. | ||
|
|
||
| States are bound to *named*, *nested* and *parallel views*, allowing you to powerfully manage your application's interface. | ||
|
|
||
| Check out the sample app: http://angular-ui.github.io/ui-router/sample/ | ||
|
|
||
| - | ||
| **Note:** *UI-Router is under active development. As such, while this library is well-tested, the API may change. Consider using it in production applications only if you're comfortable following a changelog and updating your usage accordingly.* | ||
|
|
||
|
|
||
| ## Get Started | ||
|
|
||
| **(1)** Get UI-Router in one of the following ways: | ||
| - clone & [build](CONTRIBUTING.md#developing) this repository | ||
| - [download the release](http://angular-ui.github.io/ui-router/release/angular-ui-router.js) (or [minified](http://angular-ui.github.io/ui-router/release/angular-ui-router.min.js)) | ||
| - via **[Bower](http://bower.io/)**: by running `$ bower install angular-ui-router` from your console | ||
| - or via **[npm](https://www.npmjs.org/)**: by running `$ npm install angular-ui-router` from your console | ||
| - or via **[Component](https://github.com/component/component)**: by running `$ component install angular-ui/ui-router` from your console | ||
|
|
||
| **(2)** Include `angular-ui-router.js` (or `angular-ui-router.min.js`) in your `index.html`, after including Angular itself (For Component users: ignore this step) | ||
|
|
||
| **(3)** Add `'ui.router'` to your main module's list of dependencies (For Component users: replace `'ui.router'` with `require('angular-ui-router')`) | ||
|
|
||
| When you're done, your setup should look similar to the following: | ||
|
|
||
| > | ||
| ```html | ||
| <!doctype html> | ||
| <html ng-app="myApp"> | ||
| <head> | ||
| <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js"></script> | ||
| <script src="js/angular-ui-router.min.js"></script> | ||
| <script> | ||
| var myApp = angular.module('myApp', ['ui.router']); | ||
| // For Component users, it should look like this: | ||
| // var myApp = angular.module('myApp', [require('angular-ui-router')]); | ||
| </script> | ||
| ... | ||
| </head> | ||
| <body> | ||
| ... | ||
| </body> | ||
| </html> | ||
| ``` | ||
| ### [Nested States & Views](http://plnkr.co/edit/u18KQc?p=preview) | ||
|
|
||
| The majority of UI-Router's power is in its ability to nest states & views. | ||
|
|
||
| **(1)** First, follow the [setup](#get-started) instructions detailed above. | ||
|
|
||
| **(2)** Then, add a [`ui-view` directive](https://github.com/angular-ui/ui-router/wiki/Quick-Reference#ui-view) to the `<body />` of your app. | ||
|
|
||
| > | ||
| ```html | ||
| <!-- index.html --> | ||
| <body> | ||
| <div ui-view></div> | ||
| <!-- We'll also add some navigation: --> | ||
| <a ui-sref="state1">State 1</a> | ||
| <a ui-sref="state2">State 2</a> | ||
| </body> | ||
| ``` | ||
| **(3)** You'll notice we also added some links with [`ui-sref` directives](https://github.com/angular-ui/ui-router/wiki/Quick-Reference#ui-sref). In addition to managing state transitions, this directive auto-generates the `href` attribute of the `<a />` element it's attached to, if the corresponding state has a URL. Next we'll add some templates. These will plug into the `ui-view` within `index.html`. Notice that they have their own `ui-view` as well! That is the key to nesting states and views. | ||
|
|
||
| > | ||
| ```html | ||
| <!-- partials/state1.html --> | ||
| <h1>State 1</h1> | ||
| <hr/> | ||
| <a ui-sref="state1.list">Show List</a> | ||
| <div ui-view></div> | ||
| ``` | ||
| ```html | ||
| <!-- partials/state2.html --> | ||
| <h1>State 2</h1> | ||
| <hr/> | ||
| <a ui-sref="state2.list">Show List</a> | ||
| <div ui-view></div> | ||
| ``` | ||
| **(4)** Next, we'll add some child templates. *These* will get plugged into the `ui-view` of their parent state templates. | ||
|
|
||
| > | ||
| ```html | ||
| <!-- partials/state1.list.html --> | ||
| <h3>List of State 1 Items</h3> | ||
| <ul> | ||
| <li ng-repeat="item in items">{{ item }}</li> | ||
| </ul> | ||
| ``` | ||
| > | ||
| ```html | ||
| <!-- partials/state2.list.html --> | ||
| <h3>List of State 2 Things</h3> | ||
| <ul> | ||
| <li ng-repeat="thing in things">{{ thing }}</li> | ||
| </ul> | ||
| ``` | ||
| **(5)** Finally, we'll wire it all up with `$stateProvider`. Set up your states in the module config, as in the following: | ||
|
|
||
|
|
||
| > | ||
| ```javascript | ||
| myApp.config(function($stateProvider, $urlRouterProvider) { | ||
| // | ||
| // For any unmatched url, redirect to /state1 | ||
| $urlRouterProvider.otherwise("/state1"); | ||
| // | ||
| // Now set up the states | ||
| $stateProvider | ||
| .state('state1', { | ||
| url: "/state1", | ||
| templateUrl: "partials/state1.html" | ||
| }) | ||
| .state('state1.list', { | ||
| url: "/list", | ||
| templateUrl: "partials/state1.list.html", | ||
| controller: function($scope) { | ||
| $scope.items = ["A", "List", "Of", "Items"]; | ||
| } | ||
| }) | ||
| .state('state2', { | ||
| url: "/state2", | ||
| templateUrl: "partials/state2.html" | ||
| }) | ||
| .state('state2.list', { | ||
| url: "/list", | ||
| templateUrl: "partials/state2.list.html", | ||
| controller: function($scope) { | ||
| $scope.things = ["A", "Set", "Of", "Things"]; | ||
| } | ||
| }); | ||
| }); | ||
| ``` | ||
| **(6)** See this quick start example in action. | ||
| >**[Go to Quick Start Plunker for Nested States & Views](http://plnkr.co/edit/u18KQc?p=preview)** | ||
| **(7)** This only scratches the surface | ||
| >**[Dive Deeper!](https://github.com/angular-ui/ui-router/wiki)** | ||
|
|
||
| ### [Multiple & Named Views](http://plnkr.co/edit/SDOcGS?p=preview) | ||
|
|
||
| Another great feature is the ability to have multiple `ui-view`s view per template. | ||
|
|
||
| **Pro Tip:** *While multiple parallel views are a powerful feature, you'll often be able to manage your | ||
| interfaces more effectively by nesting your views, and pairing those views with nested states.* | ||
|
|
||
| **(1)** Follow the [setup](#get-started) instructions detailed above. | ||
|
|
||
| **(2)** Add one or more `ui-view` to your app, give them names. | ||
| > | ||
| ```html | ||
| <!-- index.html --> | ||
| <body> | ||
| <div ui-view="viewA"></div> | ||
| <div ui-view="viewB"></div> | ||
| <!-- Also a way to navigate --> | ||
| <a ui-sref="route1">Route 1</a> | ||
| <a ui-sref="route2">Route 2</a> | ||
| </body> | ||
| ``` | ||
| **(3)** Set up your states in the module config: | ||
| > | ||
| ```javascript | ||
| myApp.config(function($stateProvider) { | ||
| $stateProvider | ||
| .state('index', { | ||
| url: "", | ||
| views: { | ||
| "viewA": { template: "index.viewA" }, | ||
| "viewB": { template: "index.viewB" } | ||
| } | ||
| }) | ||
| .state('route1', { | ||
| url: "/route1", | ||
| views: { | ||
| "viewA": { template: "route1.viewA" }, | ||
| "viewB": { template: "route1.viewB" } | ||
| } | ||
| }) | ||
| .state('route2', { | ||
| url: "/route2", | ||
| views: { | ||
| "viewA": { template: "route2.viewA" }, | ||
| "viewB": { template: "route2.viewB" } | ||
| } | ||
| }) | ||
| }); | ||
| ``` | ||
| **(4)** See this quick start example in action. | ||
| >**[Go to Quick Start Plunker for Multiple & Named Views](http://plnkr.co/edit/SDOcGS?p=preview)** | ||
|
|
||
| ## Resources | ||
|
|
||
| * [In-Depth Guide](https://github.com/angular-ui/ui-router/wiki) | ||
| * [API Reference](http://angular-ui.github.io/ui-router/site) | ||
| * [Sample App](http://angular-ui.github.com/ui-router/sample/) ([Source](https://github.com/angular-ui/ui-router/tree/gh-pages/sample)) | ||
| * [FAQ](https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions) | ||
| * [Slides comparing ngRoute to ui-router](http://slid.es/timkindberg/ui-router#/) | ||
| * [UI-Router Extras / Addons](http://christopherthielen.github.io/ui-router-extras/#/home) (@christopherthielen) | ||
|
|
||
| ### Videos | ||
|
|
||
| * [Introduction Video](https://egghead.io/lessons/angularjs-introduction-ui-router) (egghead.io) | ||
| * [Tim Kindberg on Angular UI-Router](https://www.youtube.com/watch?v=lBqiZSemrqg) | ||
| * [Activating States](https://egghead.io/lessons/angularjs-ui-router-activating-states) (egghead.io) | ||
| * [Learn Angular.js using UI-Router](http://youtu.be/QETUuZ27N0w) (LearnCode.academy) | ||
|
|
||
|
|
||
|
|
||
| ## Reporting issues and Contributing | ||
|
|
||
| Please read our [Contributor guidelines](CONTRIBUTING.md) before reporting an issue or creating a pull request. |
| @@ -0,0 +1,126 @@ | ||
| // Type definitions for Angular JS 1.1.5+ (ui.router module) | ||
| // Project: https://github.com/angular-ui/ui-router | ||
| // Definitions by: Michel Salib <https://github.com/michelsalib> | ||
| // Definitions: https://github.com/borisyankov/DefinitelyTyped | ||
|
|
||
| declare module ng.ui { | ||
|
|
||
| interface IState { | ||
| name?: string; | ||
| template?: string; | ||
| templateUrl?: any; // string || () => string | ||
| templateProvider?: any; // () => string || IPromise<string> | ||
| controller?: any; | ||
| controllerAs?: string; | ||
| controllerProvider?: any; | ||
| resolve?: {}; | ||
| url?: string; | ||
| params?: any; | ||
| views?: {}; | ||
| abstract?: boolean; | ||
| onEnter?: (...args: any[]) => void; | ||
| onExit?: (...args: any[]) => void; | ||
| data?: any; | ||
| reloadOnSearch?: boolean; | ||
| } | ||
|
|
||
| interface ITypedState<T> extends IState { | ||
| data?: T; | ||
| } | ||
|
|
||
| interface IStateProvider extends IServiceProvider { | ||
| state(name: string, config: IState): IStateProvider; | ||
| state(config: IState): IStateProvider; | ||
| decorator(name?: string, decorator?: (state: IState, parent: Function) => any): any; | ||
| } | ||
|
|
||
| interface IUrlMatcher { | ||
| concat(pattern: string): IUrlMatcher; | ||
| exec(path: string, searchParams: {}): {}; | ||
| parameters(): string[]; | ||
| format(values: {}): string; | ||
| } | ||
|
|
||
| interface IUrlMatcherFactory { | ||
| compile(pattern: string): IUrlMatcher; | ||
| isMatcher(o: any): boolean; | ||
| } | ||
|
|
||
| interface IUrlRouterProvider extends IServiceProvider { | ||
| when(whenPath: RegExp, handler: Function): IUrlRouterProvider; | ||
| when(whenPath: RegExp, handler: any[]): IUrlRouterProvider; | ||
| when(whenPath: RegExp, toPath: string): IUrlRouterProvider; | ||
| when(whenPath: IUrlMatcher, hanlder: Function): IUrlRouterProvider; | ||
| when(whenPath: IUrlMatcher, handler: any[]): IUrlRouterProvider; | ||
| when(whenPath: IUrlMatcher, toPath: string): IUrlRouterProvider; | ||
| when(whenPath: string, handler: Function): IUrlRouterProvider; | ||
| when(whenPath: string, handler: any[]): IUrlRouterProvider; | ||
| when(whenPath: string, toPath: string): IUrlRouterProvider; | ||
| otherwise(handler: Function): IUrlRouterProvider; | ||
| otherwise(handler: any[]): IUrlRouterProvider; | ||
| otherwise(path: string): IUrlRouterProvider; | ||
| rule(handler: Function): IUrlRouterProvider; | ||
| rule(handler: any[]): IUrlRouterProvider; | ||
| } | ||
|
|
||
| interface IStateOptions { | ||
| location?: any; | ||
| inherit?: boolean; | ||
| relative?: IState; | ||
| notify?: boolean; | ||
| reload?: boolean; | ||
| } | ||
|
|
||
| interface IHrefOptions { | ||
| lossy?: boolean; | ||
| inherit?: boolean; | ||
| relative?: IState; | ||
| absolute?: boolean; | ||
| } | ||
|
|
||
| interface IStateService { | ||
| go(to: string, params?: {}, options?: IStateOptions): IPromise<any>; | ||
| transitionTo(state: string, params?: {}, updateLocation?: boolean): void; | ||
| transitionTo(state: string, params?: {}, options?: IStateOptions): void; | ||
| includes(state: string, params?: {}): boolean; | ||
| is(state:string, params?: {}): boolean; | ||
| is(state: IState, params?: {}): boolean; | ||
| href(state: IState, params?: {}, options?: IHrefOptions): string; | ||
| href(state: string, params?: {}, options?: IHrefOptions): string; | ||
| get(state: string): IState; | ||
| get(): IState[]; | ||
| current: IState; | ||
| params: any; | ||
| reload(): void; | ||
| } | ||
|
|
||
| interface IStateParamsService { | ||
| [key: string]: any; | ||
| } | ||
|
|
||
| interface IStateParams { | ||
| [key: string]: any; | ||
| } | ||
|
|
||
| interface IUrlRouterService { | ||
| /* | ||
| * Triggers an update; the same update that happens when the address bar | ||
| * url changes, aka $locationChangeSuccess. | ||
| * | ||
| * This method is useful when you need to use preventDefault() on the | ||
| * $locationChangeSuccess event, perform some custom logic (route protection, | ||
| * auth, config, redirection, etc) and then finally proceed with the transition | ||
| * by calling $urlRouter.sync(). | ||
| * | ||
| */ | ||
| sync(): void; | ||
| } | ||
|
|
||
| interface IUiViewScrollProvider { | ||
| /* | ||
| * Reverts back to using the core $anchorScroll service for scrolling | ||
| * based on the url anchor. | ||
| */ | ||
| useAnchorScroll(): void; | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "name": "angular-ui-router", | ||
| "version": "0.2.13", | ||
| "main": "./release/angular-ui-router.js", | ||
| "dependencies": { | ||
| "angular": ">= 1.0.8" | ||
| }, | ||
| "ignore": [ | ||
| "**/.*", | ||
| "node_modules", | ||
| "bower_components", | ||
| "component.json", | ||
| "package.json", | ||
| "lib", | ||
| "config", | ||
| "sample", | ||
| "test", | ||
| "tests", | ||
| "ngdoc_assets", | ||
| "Gruntfile.js", | ||
| "files.js" | ||
| ] | ||
| } |
| @@ -0,0 +1,292 @@ | ||
| /*jshint globalstrict:true*/ | ||
| /*global angular:false*/ | ||
| 'use strict'; | ||
|
|
||
| var isDefined = angular.isDefined, | ||
| isFunction = angular.isFunction, | ||
| isString = angular.isString, | ||
| isObject = angular.isObject, | ||
| isArray = angular.isArray, | ||
| forEach = angular.forEach, | ||
| extend = angular.extend, | ||
| copy = angular.copy; | ||
|
|
||
| function inherit(parent, extra) { | ||
| return extend(new (extend(function() {}, { prototype: parent }))(), extra); | ||
| } | ||
|
|
||
| function merge(dst) { | ||
| forEach(arguments, function(obj) { | ||
| if (obj !== dst) { | ||
| forEach(obj, function(value, key) { | ||
| if (!dst.hasOwnProperty(key)) dst[key] = value; | ||
| }); | ||
| } | ||
| }); | ||
| return dst; | ||
| } | ||
|
|
||
| /** | ||
| * Finds the common ancestor path between two states. | ||
| * | ||
| * @param {Object} first The first state. | ||
| * @param {Object} second The second state. | ||
| * @return {Array} Returns an array of state names in descending order, not including the root. | ||
| */ | ||
| function ancestors(first, second) { | ||
| var path = []; | ||
|
|
||
| for (var n in first.path) { | ||
| if (first.path[n] !== second.path[n]) break; | ||
| path.push(first.path[n]); | ||
| } | ||
| return path; | ||
| } | ||
|
|
||
| /** | ||
| * IE8-safe wrapper for `Object.keys()`. | ||
| * | ||
| * @param {Object} object A JavaScript object. | ||
| * @return {Array} Returns the keys of the object as an array. | ||
| */ | ||
| function objectKeys(object) { | ||
| if (Object.keys) { | ||
| return Object.keys(object); | ||
| } | ||
| var result = []; | ||
|
|
||
| angular.forEach(object, function(val, key) { | ||
| result.push(key); | ||
| }); | ||
| return result; | ||
| } | ||
|
|
||
| /** | ||
| * IE8-safe wrapper for `Array.prototype.indexOf()`. | ||
| * | ||
| * @param {Array} array A JavaScript array. | ||
| * @param {*} value A value to search the array for. | ||
| * @return {Number} Returns the array index value of `value`, or `-1` if not present. | ||
| */ | ||
| function indexOf(array, value) { | ||
| if (Array.prototype.indexOf) { | ||
| return array.indexOf(value, Number(arguments[2]) || 0); | ||
| } | ||
| var len = array.length >>> 0, from = Number(arguments[2]) || 0; | ||
| from = (from < 0) ? Math.ceil(from) : Math.floor(from); | ||
|
|
||
| if (from < 0) from += len; | ||
|
|
||
| for (; from < len; from++) { | ||
| if (from in array && array[from] === value) return from; | ||
| } | ||
| return -1; | ||
| } | ||
|
|
||
| /** | ||
| * Merges a set of parameters with all parameters inherited between the common parents of the | ||
| * current state and a given destination state. | ||
| * | ||
| * @param {Object} currentParams The value of the current state parameters ($stateParams). | ||
| * @param {Object} newParams The set of parameters which will be composited with inherited params. | ||
| * @param {Object} $current Internal definition of object representing the current state. | ||
| * @param {Object} $to Internal definition of object representing state to transition to. | ||
| */ | ||
| function inheritParams(currentParams, newParams, $current, $to) { | ||
| var parents = ancestors($current, $to), parentParams, inherited = {}, inheritList = []; | ||
|
|
||
| for (var i in parents) { | ||
| if (!parents[i].params) continue; | ||
| parentParams = objectKeys(parents[i].params); | ||
| if (!parentParams.length) continue; | ||
|
|
||
| for (var j in parentParams) { | ||
| if (indexOf(inheritList, parentParams[j]) >= 0) continue; | ||
| inheritList.push(parentParams[j]); | ||
| inherited[parentParams[j]] = currentParams[parentParams[j]]; | ||
| } | ||
| } | ||
| return extend({}, inherited, newParams); | ||
| } | ||
|
|
||
| /** | ||
| * Performs a non-strict comparison of the subset of two objects, defined by a list of keys. | ||
| * | ||
| * @param {Object} a The first object. | ||
| * @param {Object} b The second object. | ||
| * @param {Array} keys The list of keys within each object to compare. If the list is empty or not specified, | ||
| * it defaults to the list of keys in `a`. | ||
| * @return {Boolean} Returns `true` if the keys match, otherwise `false`. | ||
| */ | ||
| function equalForKeys(a, b, keys) { | ||
| if (!keys) { | ||
| keys = []; | ||
| for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility | ||
| } | ||
|
|
||
| for (var i=0; i<keys.length; i++) { | ||
| var k = keys[i]; | ||
| if (a[k] != b[k]) return false; // Not '===', values aren't necessarily normalized | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| /** | ||
| * Returns the subset of an object, based on a list of keys. | ||
| * | ||
| * @param {Array} keys | ||
| * @param {Object} values | ||
| * @return {Boolean} Returns a subset of `values`. | ||
| */ | ||
| function filterByKeys(keys, values) { | ||
| var filtered = {}; | ||
|
|
||
| forEach(keys, function (name) { | ||
| filtered[name] = values[name]; | ||
| }); | ||
| return filtered; | ||
| } | ||
|
|
||
| // like _.indexBy | ||
| // when you know that your index values will be unique, or you want last-one-in to win | ||
| function indexBy(array, propName) { | ||
| var result = {}; | ||
| forEach(array, function(item) { | ||
| result[item[propName]] = item; | ||
| }); | ||
| return result; | ||
| } | ||
|
|
||
| // extracted from underscore.js | ||
| // Return a copy of the object only containing the whitelisted properties. | ||
| function pick(obj) { | ||
| var copy = {}; | ||
| var keys = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1)); | ||
| forEach(keys, function(key) { | ||
| if (key in obj) copy[key] = obj[key]; | ||
| }); | ||
| return copy; | ||
| } | ||
|
|
||
| // extracted from underscore.js | ||
| // Return a copy of the object omitting the blacklisted properties. | ||
| function omit(obj) { | ||
| var copy = {}; | ||
| var keys = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1)); | ||
| for (var key in obj) { | ||
| if (indexOf(keys, key) == -1) copy[key] = obj[key]; | ||
| } | ||
| return copy; | ||
| } | ||
|
|
||
| function pluck(collection, key) { | ||
| var result = isArray(collection) ? [] : {}; | ||
|
|
||
| forEach(collection, function(val, i) { | ||
| result[i] = isFunction(key) ? key(val) : val[key]; | ||
| }); | ||
| return result; | ||
| } | ||
|
|
||
| function filter(collection, callback) { | ||
| var array = isArray(collection); | ||
| var result = array ? [] : {}; | ||
| forEach(collection, function(val, i) { | ||
| if (callback(val, i)) { | ||
| result[array ? result.length : i] = val; | ||
| } | ||
| }); | ||
| return result; | ||
| } | ||
|
|
||
| function map(collection, callback) { | ||
| var result = isArray(collection) ? [] : {}; | ||
|
|
||
| forEach(collection, function(val, i) { | ||
| result[i] = callback(val, i); | ||
| }); | ||
| return result; | ||
| } | ||
|
|
||
| /** | ||
| * @ngdoc overview | ||
| * @name ui.router.util | ||
| * | ||
| * @description | ||
| * # ui.router.util sub-module | ||
| * | ||
| * This module is a dependency of other sub-modules. Do not include this module as a dependency | ||
| * in your angular app (use {@link ui.router} module instead). | ||
| * | ||
| */ | ||
| angular.module('ui.router.util', ['ng']); | ||
|
|
||
| /** | ||
| * @ngdoc overview | ||
| * @name ui.router.router | ||
| * | ||
| * @requires ui.router.util | ||
| * | ||
| * @description | ||
| * # ui.router.router sub-module | ||
| * | ||
| * This module is a dependency of other sub-modules. Do not include this module as a dependency | ||
| * in your angular app (use {@link ui.router} module instead). | ||
| */ | ||
| angular.module('ui.router.router', ['ui.router.util']); | ||
|
|
||
| /** | ||
| * @ngdoc overview | ||
| * @name ui.router.state | ||
| * | ||
| * @requires ui.router.router | ||
| * @requires ui.router.util | ||
| * | ||
| * @description | ||
| * # ui.router.state sub-module | ||
| * | ||
| * This module is a dependency of the main ui.router module. Do not include this module as a dependency | ||
| * in your angular app (use {@link ui.router} module instead). | ||
| * | ||
| */ | ||
| angular.module('ui.router.state', ['ui.router.router', 'ui.router.util']); | ||
|
|
||
| /** | ||
| * @ngdoc overview | ||
| * @name ui.router | ||
| * | ||
| * @requires ui.router.state | ||
| * | ||
| * @description | ||
| * # ui.router | ||
| * | ||
| * ## The main module for ui.router | ||
| * There are several sub-modules included with the ui.router module, however only this module is needed | ||
| * as a dependency within your angular app. The other modules are for organization purposes. | ||
| * | ||
| * The modules are: | ||
| * * ui.router - the main "umbrella" module | ||
| * * ui.router.router - | ||
| * | ||
| * *You'll need to include **only** this module as the dependency within your angular app.* | ||
| * | ||
| * <pre> | ||
| * <!doctype html> | ||
| * <html ng-app="myApp"> | ||
| * <head> | ||
| * <script src="js/angular.js"></script> | ||
| * <!-- Include the ui-router script --> | ||
| * <script src="js/angular-ui-router.min.js"></script> | ||
| * <script> | ||
| * // ...and add 'ui.router' as a dependency | ||
| * var myApp = angular.module('myApp', ['ui.router']); | ||
| * </script> | ||
| * </head> | ||
| * <body> | ||
| * </body> | ||
| * </html> | ||
| * </pre> | ||
| */ | ||
| angular.module('ui.router', ['ui.router.state']); | ||
|
|
||
| angular.module('ui.router.compat', ['ui.router']); |
| @@ -0,0 +1,252 @@ | ||
| /** | ||
| * @ngdoc object | ||
| * @name ui.router.util.$resolve | ||
| * | ||
| * @requires $q | ||
| * @requires $injector | ||
| * | ||
| * @description | ||
| * Manages resolution of (acyclic) graphs of promises. | ||
| */ | ||
| $Resolve.$inject = ['$q', '$injector']; | ||
| function $Resolve( $q, $injector) { | ||
|
|
||
| var VISIT_IN_PROGRESS = 1, | ||
| VISIT_DONE = 2, | ||
| NOTHING = {}, | ||
| NO_DEPENDENCIES = [], | ||
| NO_LOCALS = NOTHING, | ||
| NO_PARENT = extend($q.when(NOTHING), { $$promises: NOTHING, $$values: NOTHING }); | ||
|
|
||
|
|
||
| /** | ||
| * @ngdoc function | ||
| * @name ui.router.util.$resolve#study | ||
| * @methodOf ui.router.util.$resolve | ||
| * | ||
| * @description | ||
| * Studies a set of invocables that are likely to be used multiple times. | ||
| * <pre> | ||
| * $resolve.study(invocables)(locals, parent, self) | ||
| * </pre> | ||
| * is equivalent to | ||
| * <pre> | ||
| * $resolve.resolve(invocables, locals, parent, self) | ||
| * </pre> | ||
| * but the former is more efficient (in fact `resolve` just calls `study` | ||
| * internally). | ||
| * | ||
| * @param {object} invocables Invocable objects | ||
| * @return {function} a function to pass in locals, parent and self | ||
| */ | ||
| this.study = function (invocables) { | ||
| if (!isObject(invocables)) throw new Error("'invocables' must be an object"); | ||
| var invocableKeys = objectKeys(invocables || {}); | ||
|
|
||
| // Perform a topological sort of invocables to build an ordered plan | ||
| var plan = [], cycle = [], visited = {}; | ||
| function visit(value, key) { | ||
| if (visited[key] === VISIT_DONE) return; | ||
|
|
||
| cycle.push(key); | ||
| if (visited[key] === VISIT_IN_PROGRESS) { | ||
| cycle.splice(0, indexOf(cycle, key)); | ||
| throw new Error("Cyclic dependency: " + cycle.join(" -> ")); | ||
| } | ||
| visited[key] = VISIT_IN_PROGRESS; | ||
|
|
||
| if (isString(value)) { | ||
| plan.push(key, [ function() { return $injector.get(value); }], NO_DEPENDENCIES); | ||
| } else { | ||
| var params = $injector.annotate(value); | ||
| forEach(params, function (param) { | ||
| if (param !== key && invocables.hasOwnProperty(param)) visit(invocables[param], param); | ||
| }); | ||
| plan.push(key, value, params); | ||
| } | ||
|
|
||
| cycle.pop(); | ||
| visited[key] = VISIT_DONE; | ||
| } | ||
| forEach(invocables, visit); | ||
| invocables = cycle = visited = null; // plan is all that's required | ||
|
|
||
| function isResolve(value) { | ||
| return isObject(value) && value.then && value.$$promises; | ||
| } | ||
|
|
||
| return function (locals, parent, self) { | ||
| if (isResolve(locals) && self === undefined) { | ||
| self = parent; parent = locals; locals = null; | ||
| } | ||
| if (!locals) locals = NO_LOCALS; | ||
| else if (!isObject(locals)) { | ||
| throw new Error("'locals' must be an object"); | ||
| } | ||
| if (!parent) parent = NO_PARENT; | ||
| else if (!isResolve(parent)) { | ||
| throw new Error("'parent' must be a promise returned by $resolve.resolve()"); | ||
| } | ||
|
|
||
| // To complete the overall resolution, we have to wait for the parent | ||
| // promise and for the promise for each invokable in our plan. | ||
| var resolution = $q.defer(), | ||
| result = resolution.promise, | ||
| promises = result.$$promises = {}, | ||
| values = extend({}, locals), | ||
| wait = 1 + plan.length/3, | ||
| merged = false; | ||
|
|
||
| function done() { | ||
| // Merge parent values we haven't got yet and publish our own $$values | ||
| if (!--wait) { | ||
| if (!merged) merge(values, parent.$$values); | ||
| result.$$values = values; | ||
| result.$$promises = result.$$promises || true; // keep for isResolve() | ||
| delete result.$$inheritedValues; | ||
| resolution.resolve(values); | ||
| } | ||
| } | ||
|
|
||
| function fail(reason) { | ||
| result.$$failure = reason; | ||
| resolution.reject(reason); | ||
| } | ||
|
|
||
| // Short-circuit if parent has already failed | ||
| if (isDefined(parent.$$failure)) { | ||
| fail(parent.$$failure); | ||
| return result; | ||
| } | ||
|
|
||
| if (parent.$$inheritedValues) { | ||
| merge(values, omit(parent.$$inheritedValues, invocableKeys)); | ||
| } | ||
|
|
||
| // Merge parent values if the parent has already resolved, or merge | ||
| // parent promises and wait if the parent resolve is still in progress. | ||
| extend(promises, parent.$$promises); | ||
| if (parent.$$values) { | ||
| merged = merge(values, omit(parent.$$values, invocableKeys)); | ||
| result.$$inheritedValues = omit(parent.$$values, invocableKeys); | ||
| done(); | ||
| } else { | ||
| if (parent.$$inheritedValues) { | ||
| result.$$inheritedValues = omit(parent.$$inheritedValues, invocableKeys); | ||
| } | ||
| parent.then(done, fail); | ||
| } | ||
|
|
||
| // Process each invocable in the plan, but ignore any where a local of the same name exists. | ||
| for (var i=0, ii=plan.length; i<ii; i+=3) { | ||
| if (locals.hasOwnProperty(plan[i])) done(); | ||
| else invoke(plan[i], plan[i+1], plan[i+2]); | ||
| } | ||
|
|
||
| function invoke(key, invocable, params) { | ||
| // Create a deferred for this invocation. Failures will propagate to the resolution as well. | ||
| var invocation = $q.defer(), waitParams = 0; | ||
| function onfailure(reason) { | ||
| invocation.reject(reason); | ||
| fail(reason); | ||
| } | ||
| // Wait for any parameter that we have a promise for (either from parent or from this | ||
| // resolve; in that case study() will have made sure it's ordered before us in the plan). | ||
| forEach(params, function (dep) { | ||
| if (promises.hasOwnProperty(dep) && !locals.hasOwnProperty(dep)) { | ||
| waitParams++; | ||
| promises[dep].then(function (result) { | ||
| values[dep] = result; | ||
| if (!(--waitParams)) proceed(); | ||
| }, onfailure); | ||
| } | ||
| }); | ||
| if (!waitParams) proceed(); | ||
| function proceed() { | ||
| if (isDefined(result.$$failure)) return; | ||
| try { | ||
| invocation.resolve($injector.invoke(invocable, self, values)); | ||
| invocation.promise.then(function (result) { | ||
| values[key] = result; | ||
| done(); | ||
| }, onfailure); | ||
| } catch (e) { | ||
| onfailure(e); | ||
| } | ||
| } | ||
| // Publish promise synchronously; invocations further down in the plan may depend on it. | ||
| promises[key] = invocation.promise; | ||
| } | ||
|
|
||
| return result; | ||
| }; | ||
| }; | ||
|
|
||
| /** | ||
| * @ngdoc function | ||
| * @name ui.router.util.$resolve#resolve | ||
| * @methodOf ui.router.util.$resolve | ||
| * | ||
| * @description | ||
| * Resolves a set of invocables. An invocable is a function to be invoked via | ||
| * `$injector.invoke()`, and can have an arbitrary number of dependencies. | ||
| * An invocable can either return a value directly, | ||
| * or a `$q` promise. If a promise is returned it will be resolved and the | ||
| * resulting value will be used instead. Dependencies of invocables are resolved | ||
| * (in this order of precedence) | ||
| * | ||
| * - from the specified `locals` | ||
| * - from another invocable that is part of this `$resolve` call | ||
| * - from an invocable that is inherited from a `parent` call to `$resolve` | ||
| * (or recursively | ||
| * - from any ancestor `$resolve` of that parent). | ||
| * | ||
| * The return value of `$resolve` is a promise for an object that contains | ||
| * (in this order of precedence) | ||
| * | ||
| * - any `locals` (if specified) | ||
| * - the resolved return values of all injectables | ||
| * - any values inherited from a `parent` call to `$resolve` (if specified) | ||
| * | ||
| * The promise will resolve after the `parent` promise (if any) and all promises | ||
| * returned by injectables have been resolved. If any invocable | ||
| * (or `$injector.invoke`) throws an exception, or if a promise returned by an | ||
| * invocable is rejected, the `$resolve` promise is immediately rejected with the | ||
| * same error. A rejection of a `parent` promise (if specified) will likewise be | ||
| * propagated immediately. Once the `$resolve` promise has been rejected, no | ||
| * further invocables will be called. | ||
| * | ||
| * Cyclic dependencies between invocables are not permitted and will caues `$resolve` | ||
| * to throw an error. As a special case, an injectable can depend on a parameter | ||
| * with the same name as the injectable, which will be fulfilled from the `parent` | ||
| * injectable of the same name. This allows inherited values to be decorated. | ||
| * Note that in this case any other injectable in the same `$resolve` with the same | ||
| * dependency would see the decorated value, not the inherited value. | ||
| * | ||
| * Note that missing dependencies -- unlike cyclic dependencies -- will cause an | ||
| * (asynchronous) rejection of the `$resolve` promise rather than a (synchronous) | ||
| * exception. | ||
| * | ||
| * Invocables are invoked eagerly as soon as all dependencies are available. | ||
| * This is true even for dependencies inherited from a `parent` call to `$resolve`. | ||
| * | ||
| * As a special case, an invocable can be a string, in which case it is taken to | ||
| * be a service name to be passed to `$injector.get()`. This is supported primarily | ||
| * for backwards-compatibility with the `resolve` property of `$routeProvider` | ||
| * routes. | ||
| * | ||
| * @param {object} invocables functions to invoke or | ||
| * `$injector` services to fetch. | ||
| * @param {object} locals values to make available to the injectables | ||
| * @param {object} parent a promise returned by another call to `$resolve`. | ||
| * @param {object} self the `this` for the invoked methods | ||
| * @return {object} Promise for an object that contains the resolved return value | ||
| * of all invocables, as well as any inherited and local values. | ||
| */ | ||
| this.resolve = function (invocables, locals, parent, self) { | ||
| return this.study(invocables)(locals, parent, self); | ||
| }; | ||
| } | ||
|
|
||
| angular.module('ui.router.util').service('$resolve', $Resolve); | ||
|
|
| @@ -0,0 +1,268 @@ | ||
| function parseStateRef(ref, current) { | ||
| var preparsed = ref.match(/^\s*({[^}]*})\s*$/), parsed; | ||
| if (preparsed) ref = current + '(' + preparsed[1] + ')'; | ||
| parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/); | ||
| if (!parsed || parsed.length !== 4) throw new Error("Invalid state ref '" + ref + "'"); | ||
| return { state: parsed[1], paramExpr: parsed[3] || null }; | ||
| } | ||
|
|
||
| function stateContext(el) { | ||
| var stateData = el.parent().inheritedData('$uiView'); | ||
|
|
||
| if (stateData && stateData.state && stateData.state.name) { | ||
| return stateData.state; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @ngdoc directive | ||
| * @name ui.router.state.directive:ui-sref | ||
| * | ||
| * @requires ui.router.state.$state | ||
| * @requires $timeout | ||
| * | ||
| * @restrict A | ||
| * | ||
| * @description | ||
| * A directive that binds a link (`<a>` tag) to a state. If the state has an associated | ||
| * URL, the directive will automatically generate & update the `href` attribute via | ||
| * the {@link ui.router.state.$state#methods_href $state.href()} method. Clicking | ||
| * the link will trigger a state transition with optional parameters. | ||
| * | ||
| * Also middle-clicking, right-clicking, and ctrl-clicking on the link will be | ||
| * handled natively by the browser. | ||
| * | ||
| * You can also use relative state paths within ui-sref, just like the relative | ||
| * paths passed to `$state.go()`. You just need to be aware that the path is relative | ||
| * to the state that the link lives in, in other words the state that loaded the | ||
| * template containing the link. | ||
| * | ||
| * You can specify options to pass to {@link ui.router.state.$state#go $state.go()} | ||
| * using the `ui-sref-opts` attribute. Options are restricted to `location`, `inherit`, | ||
| * and `reload`. | ||
| * | ||
| * @example | ||
| * Here's an example of how you'd use ui-sref and how it would compile. If you have the | ||
| * following template: | ||
| * <pre> | ||
| * <a ui-sref="home">Home</a> | <a ui-sref="about">About</a> | <a ui-sref="{page: 2}">Next page</a> | ||
| * | ||
| * <ul> | ||
| * <li ng-repeat="contact in contacts"> | ||
| * <a ui-sref="contacts.detail({ id: contact.id })">{{ contact.name }}</a> | ||
| * </li> | ||
| * </ul> | ||
| * </pre> | ||
| * | ||
| * Then the compiled html would be (assuming Html5Mode is off and current state is contacts): | ||
| * <pre> | ||
| * <a href="#/home" ui-sref="home">Home</a> | <a href="#/about" ui-sref="about">About</a> | <a href="#/contacts?page=2" ui-sref="{page: 2}">Next page</a> | ||
| * | ||
| * <ul> | ||
| * <li ng-repeat="contact in contacts"> | ||
| * <a href="#/contacts/1" ui-sref="contacts.detail({ id: contact.id })">Joe</a> | ||
| * </li> | ||
| * <li ng-repeat="contact in contacts"> | ||
| * <a href="#/contacts/2" ui-sref="contacts.detail({ id: contact.id })">Alice</a> | ||
| * </li> | ||
| * <li ng-repeat="contact in contacts"> | ||
| * <a href="#/contacts/3" ui-sref="contacts.detail({ id: contact.id })">Bob</a> | ||
| * </li> | ||
| * </ul> | ||
| * | ||
| * <a ui-sref="home" ui-sref-opts="{reload: true}">Home</a> | ||
| * </pre> | ||
| * | ||
| * @param {string} ui-sref 'stateName' can be any valid absolute or relative state | ||
| * @param {Object} ui-sref-opts options to pass to {@link ui.router.state.$state#go $state.go()} | ||
| */ | ||
| $StateRefDirective.$inject = ['$state', '$timeout']; | ||
| function $StateRefDirective($state, $timeout) { | ||
| var allowedOptions = ['location', 'inherit', 'reload']; | ||
|
|
||
| return { | ||
| restrict: 'A', | ||
| require: ['?^uiSrefActive', '?^uiSrefActiveEq'], | ||
| link: function(scope, element, attrs, uiSrefActive) { | ||
| var ref = parseStateRef(attrs.uiSref, $state.current.name); | ||
| var params = null, url = null, base = stateContext(element) || $state.$current; | ||
| var newHref = null, isAnchor = element.prop("tagName") === "A"; | ||
| var isForm = element[0].nodeName === "FORM"; | ||
| var attr = isForm ? "action" : "href", nav = true; | ||
|
|
||
| var options = { relative: base, inherit: true }; | ||
| var optionsOverride = scope.$eval(attrs.uiSrefOpts) || {}; | ||
|
|
||
| angular.forEach(allowedOptions, function(option) { | ||
| if (option in optionsOverride) { | ||
| options[option] = optionsOverride[option]; | ||
| } | ||
| }); | ||
|
|
||
| var update = function(newVal) { | ||
| if (newVal) params = angular.copy(newVal); | ||
| if (!nav) return; | ||
|
|
||
| newHref = $state.href(ref.state, params, options); | ||
|
|
||
| var activeDirective = uiSrefActive[1] || uiSrefActive[0]; | ||
| if (activeDirective) { | ||
| activeDirective.$$setStateInfo(ref.state, params); | ||
| } | ||
| if (newHref === null) { | ||
| nav = false; | ||
| return false; | ||
| } | ||
| attrs.$set(attr, newHref); | ||
| }; | ||
|
|
||
| if (ref.paramExpr) { | ||
| scope.$watch(ref.paramExpr, function(newVal, oldVal) { | ||
| if (newVal !== params) update(newVal); | ||
| }, true); | ||
| params = angular.copy(scope.$eval(ref.paramExpr)); | ||
| } | ||
| update(); | ||
|
|
||
| if (isForm) return; | ||
|
|
||
| element.bind("click", function(e) { | ||
| var button = e.which || e.button; | ||
| if ( !(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || element.attr('target')) ) { | ||
| // HACK: This is to allow ng-clicks to be processed before the transition is initiated: | ||
| var transition = $timeout(function() { | ||
| $state.go(ref.state, params, options); | ||
| }); | ||
| e.preventDefault(); | ||
|
|
||
| // if the state has no URL, ignore one preventDefault from the <a> directive. | ||
| var ignorePreventDefaultCount = isAnchor && !newHref ? 1: 0; | ||
| e.preventDefault = function() { | ||
| if (ignorePreventDefaultCount-- <= 0) | ||
| $timeout.cancel(transition); | ||
| }; | ||
| } | ||
| }); | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| /** | ||
| * @ngdoc directive | ||
| * @name ui.router.state.directive:ui-sref-active | ||
| * | ||
| * @requires ui.router.state.$state | ||
| * @requires ui.router.state.$stateParams | ||
| * @requires $interpolate | ||
| * | ||
| * @restrict A | ||
| * | ||
| * @description | ||
| * A directive working alongside ui-sref to add classes to an element when the | ||
| * related ui-sref directive's state is active, and removing them when it is inactive. | ||
| * The primary use-case is to simplify the special appearance of navigation menus | ||
| * relying on `ui-sref`, by having the "active" state's menu button appear different, | ||
| * distinguishing it from the inactive menu items. | ||
| * | ||
| * ui-sref-active can live on the same element as ui-sref or on a parent element. The first | ||
| * ui-sref-active found at the same level or above the ui-sref will be used. | ||
| * | ||
| * Will activate when the ui-sref's target state or any child state is active. If you | ||
| * need to activate only when the ui-sref target state is active and *not* any of | ||
| * it's children, then you will use | ||
| * {@link ui.router.state.directive:ui-sref-active-eq ui-sref-active-eq} | ||
| * | ||
| * @example | ||
| * Given the following template: | ||
| * <pre> | ||
| * <ul> | ||
| * <li ui-sref-active="active" class="item"> | ||
| * <a href ui-sref="app.user({user: 'bilbobaggins'})">@bilbobaggins</a> | ||
| * </li> | ||
| * </ul> | ||
| * </pre> | ||
| * | ||
| * | ||
| * When the app state is "app.user" (or any children states), and contains the state parameter "user" with value "bilbobaggins", | ||
| * the resulting HTML will appear as (note the 'active' class): | ||
| * <pre> | ||
| * <ul> | ||
| * <li ui-sref-active="active" class="item active"> | ||
| * <a ui-sref="app.user({user: 'bilbobaggins'})" href="/users/bilbobaggins">@bilbobaggins</a> | ||
| * </li> | ||
| * </ul> | ||
| * </pre> | ||
| * | ||
| * The class name is interpolated **once** during the directives link time (any further changes to the | ||
| * interpolated value are ignored). | ||
| * | ||
| * Multiple classes may be specified in a space-separated format: | ||
| * <pre> | ||
| * <ul> | ||
| * <li ui-sref-active='class1 class2 class3'> | ||
| * <a ui-sref="app.user">link</a> | ||
| * </li> | ||
| * </ul> | ||
| * </pre> | ||
| */ | ||
|
|
||
| /** | ||
| * @ngdoc directive | ||
| * @name ui.router.state.directive:ui-sref-active-eq | ||
| * | ||
| * @requires ui.router.state.$state | ||
| * @requires ui.router.state.$stateParams | ||
| * @requires $interpolate | ||
| * | ||
| * @restrict A | ||
| * | ||
| * @description | ||
| * The same as {@link ui.router.state.directive:ui-sref-active ui-sref-active} but will only activate | ||
| * when the exact target state used in the `ui-sref` is active; no child states. | ||
| * | ||
| */ | ||
| $StateRefActiveDirective.$inject = ['$state', '$stateParams', '$interpolate']; | ||
| function $StateRefActiveDirective($state, $stateParams, $interpolate) { | ||
| return { | ||
| restrict: "A", | ||
| controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) { | ||
| var state, params, activeClass; | ||
|
|
||
| // There probably isn't much point in $observing this | ||
| // uiSrefActive and uiSrefActiveEq share the same directive object with some | ||
| // slight difference in logic routing | ||
| activeClass = $interpolate($attrs.uiSrefActiveEq || $attrs.uiSrefActive || '', false)($scope); | ||
|
|
||
| // Allow uiSref to communicate with uiSrefActive[Equals] | ||
| this.$$setStateInfo = function (newState, newParams) { | ||
| state = $state.get(newState, stateContext($element)); | ||
| params = newParams; | ||
| update(); | ||
| }; | ||
|
|
||
| $scope.$on('$stateChangeSuccess', update); | ||
|
|
||
| // Update route state | ||
| function update() { | ||
| if (isMatch()) { | ||
| $element.addClass(activeClass); | ||
| } else { | ||
| $element.removeClass(activeClass); | ||
| } | ||
| } | ||
|
|
||
| function isMatch() { | ||
| if (typeof $attrs.uiSrefActiveEq !== 'undefined') { | ||
| return state && $state.is(state.name, params); | ||
| } else { | ||
| return state && $state.includes(state.name, params); | ||
| } | ||
| } | ||
| }] | ||
| }; | ||
| } | ||
|
|
||
| angular.module('ui.router.state') | ||
| .directive('uiSref', $StateRefDirective) | ||
| .directive('uiSrefActive', $StateRefActiveDirective) | ||
| .directive('uiSrefActiveEq', $StateRefActiveDirective); |
| @@ -0,0 +1,39 @@ | ||
| /** | ||
| * @ngdoc filter | ||
| * @name ui.router.state.filter:isState | ||
| * | ||
| * @requires ui.router.state.$state | ||
| * | ||
| * @description | ||
| * Translates to {@link ui.router.state.$state#methods_is $state.is("stateName")}. | ||
| */ | ||
| $IsStateFilter.$inject = ['$state']; | ||
| function $IsStateFilter($state) { | ||
| var isFilter = function (state) { | ||
| return $state.is(state); | ||
| }; | ||
| isFilter.$stateful = true; | ||
| return isFilter; | ||
| } | ||
|
|
||
| /** | ||
| * @ngdoc filter | ||
| * @name ui.router.state.filter:includedByState | ||
| * | ||
| * @requires ui.router.state.$state | ||
| * | ||
| * @description | ||
| * Translates to {@link ui.router.state.$state#methods_includes $state.includes('fullOrPartialStateName')}. | ||
| */ | ||
| $IncludedByStateFilter.$inject = ['$state']; | ||
| function $IncludedByStateFilter($state) { | ||
| var includesFilter = function (state) { | ||
| return $state.includes(state); | ||
| }; | ||
| includesFilter.$stateful = true; | ||
| return includesFilter; | ||
| } | ||
|
|
||
| angular.module('ui.router.state') | ||
| .filter('isState', $IsStateFilter) | ||
| .filter('includedByState', $IncludedByStateFilter); |
| @@ -0,0 +1,110 @@ | ||
| /** | ||
| * @ngdoc object | ||
| * @name ui.router.util.$templateFactory | ||
| * | ||
| * @requires $http | ||
| * @requires $templateCache | ||
| * @requires $injector | ||
| * | ||
| * @description | ||
| * Service. Manages loading of templates. | ||
| */ | ||
| $TemplateFactory.$inject = ['$http', '$templateCache', '$injector']; | ||
| function $TemplateFactory( $http, $templateCache, $injector) { | ||
|
|
||
| /** | ||
| * @ngdoc function | ||
| * @name ui.router.util.$templateFactory#fromConfig | ||
| * @methodOf ui.router.util.$templateFactory | ||
| * | ||
| * @description | ||
| * Creates a template from a configuration object. | ||
| * | ||
| * @param {object} config Configuration object for which to load a template. | ||
| * The following properties are search in the specified order, and the first one | ||
| * that is defined is used to create the template: | ||
| * | ||
| * @param {string|object} config.template html string template or function to | ||
| * load via {@link ui.router.util.$templateFactory#fromString fromString}. | ||
| * @param {string|object} config.templateUrl url to load or a function returning | ||
| * the url to load via {@link ui.router.util.$templateFactory#fromUrl fromUrl}. | ||
| * @param {Function} config.templateProvider function to invoke via | ||
| * {@link ui.router.util.$templateFactory#fromProvider fromProvider}. | ||
| * @param {object} params Parameters to pass to the template function. | ||
| * @param {object} locals Locals to pass to `invoke` if the template is loaded | ||
| * via a `templateProvider`. Defaults to `{ params: params }`. | ||
| * | ||
| * @return {string|object} The template html as a string, or a promise for | ||
| * that string,or `null` if no template is configured. | ||
| */ | ||
| this.fromConfig = function (config, params, locals) { | ||
| return ( | ||
| isDefined(config.template) ? this.fromString(config.template, params) : | ||
| isDefined(config.templateUrl) ? this.fromUrl(config.templateUrl, params) : | ||
| isDefined(config.templateProvider) ? this.fromProvider(config.templateProvider, params, locals) : | ||
| null | ||
| ); | ||
| }; | ||
|
|
||
| /** | ||
| * @ngdoc function | ||
| * @name ui.router.util.$templateFactory#fromString | ||
| * @methodOf ui.router.util.$templateFactory | ||
| * | ||
| * @description | ||
| * Creates a template from a string or a function returning a string. | ||
| * | ||
| * @param {string|object} template html template as a string or function that | ||
| * returns an html template as a string. | ||
| * @param {object} params Parameters to pass to the template function. | ||
| * | ||
| * @return {string|object} The template html as a string, or a promise for that | ||
| * string. | ||
| */ | ||
| this.fromString = function (template, params) { | ||
| return isFunction(template) ? template(params) : template; | ||
| }; | ||
|
|
||
| /** | ||
| * @ngdoc function | ||
| * @name ui.router.util.$templateFactory#fromUrl | ||
| * @methodOf ui.router.util.$templateFactory | ||
| * | ||
| * @description | ||
| * Loads a template from the a URL via `$http` and `$templateCache`. | ||
| * | ||
| * @param {string|Function} url url of the template to load, or a function | ||
| * that returns a url. | ||
| * @param {Object} params Parameters to pass to the url function. | ||
| * @return {string|Promise.<string>} The template html as a string, or a promise | ||
| * for that string. | ||
| */ | ||
| this.fromUrl = function (url, params) { | ||
| if (isFunction(url)) url = url(params); | ||
| if (url == null) return null; | ||
| else return $http | ||
| .get(url, { cache: $templateCache, headers: { Accept: 'text/html' }}) | ||
| .then(function(response) { return response.data; }); | ||
| }; | ||
|
|
||
| /** | ||
| * @ngdoc function | ||
| * @name ui.router.util.$templateFactory#fromProvider | ||
| * @methodOf ui.router.util.$templateFactory | ||
| * | ||
| * @description | ||
| * Creates a template by invoking an injectable provider function. | ||
| * | ||
| * @param {Function} provider Function to invoke via `$injector.invoke` | ||
| * @param {Object} params Parameters for the template. | ||
| * @param {Object} locals Locals to pass to `invoke`. Defaults to | ||
| * `{ params: params }`. | ||
| * @return {string|Promise.<string>} The template html as a string, or a promise | ||
| * for that string. | ||
| */ | ||
| this.fromProvider = function (provider, params, locals) { | ||
| return $injector.invoke(provider, null, locals || { params: params }); | ||
| }; | ||
| } | ||
|
|
||
| angular.module('ui.router.util').service('$templateFactory', $TemplateFactory); |
| @@ -0,0 +1,71 @@ | ||
|
|
||
| $ViewProvider.$inject = []; | ||
| function $ViewProvider() { | ||
|
|
||
| this.$get = $get; | ||
| /** | ||
| * @ngdoc object | ||
| * @name ui.router.state.$view | ||
| * | ||
| * @requires ui.router.util.$templateFactory | ||
| * @requires $rootScope | ||
| * | ||
| * @description | ||
| * | ||
| */ | ||
| $get.$inject = ['$rootScope', '$templateFactory']; | ||
| function $get( $rootScope, $templateFactory) { | ||
| return { | ||
| // $view.load('full.viewName', { template: ..., controller: ..., resolve: ..., async: false, params: ... }) | ||
| /** | ||
| * @ngdoc function | ||
| * @name ui.router.state.$view#load | ||
| * @methodOf ui.router.state.$view | ||
| * | ||
| * @description | ||
| * | ||
| * @param {string} name name | ||
| * @param {object} options option object. | ||
| */ | ||
| load: function load(name, options) { | ||
| var result, defaults = { | ||
| template: null, controller: null, view: null, locals: null, notify: true, async: true, params: {} | ||
| }; | ||
| options = extend(defaults, options); | ||
|
|
||
| if (options.view) { | ||
| result = $templateFactory.fromConfig(options.view, options.params, options.locals); | ||
| } | ||
| if (result && options.notify) { | ||
| /** | ||
| * @ngdoc event | ||
| * @name ui.router.state.$state#$viewContentLoading | ||
| * @eventOf ui.router.state.$view | ||
| * @eventType broadcast on root scope | ||
| * @description | ||
| * | ||
| * Fired once the view **begins loading**, *before* the DOM is rendered. | ||
| * | ||
| * @param {Object} event Event object. | ||
| * @param {Object} viewConfig The view config properties (template, controller, etc). | ||
| * | ||
| * @example | ||
| * | ||
| * <pre> | ||
| * $scope.$on('$viewContentLoading', | ||
| * function(event, viewConfig){ | ||
| * // Access to all the view config properties. | ||
| * // and one special property 'targetView' | ||
| * // viewConfig.targetView | ||
| * }); | ||
| * </pre> | ||
| */ | ||
| $rootScope.$broadcast('$viewContentLoading', options); | ||
| } | ||
| return result; | ||
| } | ||
| }; | ||
| } | ||
| } | ||
|
|
||
| angular.module('ui.router.state').provider('$view', $ViewProvider); |
| @@ -0,0 +1,302 @@ | ||
| /** | ||
| * @ngdoc directive | ||
| * @name ui.router.state.directive:ui-view | ||
| * | ||
| * @requires ui.router.state.$state | ||
| * @requires $compile | ||
| * @requires $controller | ||
| * @requires $injector | ||
| * @requires ui.router.state.$uiViewScroll | ||
| * @requires $document | ||
| * | ||
| * @restrict ECA | ||
| * | ||
| * @description | ||
| * The ui-view directive tells $state where to place your templates. | ||
| * | ||
| * @param {string=} name A view name. The name should be unique amongst the other views in the | ||
| * same state. You can have views of the same name that live in different states. | ||
| * | ||
| * @param {string=} autoscroll It allows you to set the scroll behavior of the browser window | ||
| * when a view is populated. By default, $anchorScroll is overridden by ui-router's custom scroll | ||
| * service, {@link ui.router.state.$uiViewScroll}. This custom service let's you | ||
| * scroll ui-view elements into view when they are populated during a state activation. | ||
| * | ||
| * *Note: To revert back to old [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) | ||
| * functionality, call `$uiViewScrollProvider.useAnchorScroll()`.* | ||
| * | ||
| * @param {string=} onload Expression to evaluate whenever the view updates. | ||
| * | ||
| * @example | ||
| * A view can be unnamed or named. | ||
| * <pre> | ||
| * <!-- Unnamed --> | ||
| * <div ui-view></div> | ||
| * | ||
| * <!-- Named --> | ||
| * <div ui-view="viewName"></div> | ||
| * </pre> | ||
| * | ||
| * You can only have one unnamed view within any template (or root html). If you are only using a | ||
| * single view and it is unnamed then you can populate it like so: | ||
| * <pre> | ||
| * <div ui-view></div> | ||
| * $stateProvider.state("home", { | ||
| * template: "<h1>HELLO!</h1>" | ||
| * }) | ||
| * </pre> | ||
| * | ||
| * The above is a convenient shortcut equivalent to specifying your view explicitly with the {@link ui.router.state.$stateProvider#views `views`} | ||
| * config property, by name, in this case an empty name: | ||
| * <pre> | ||
| * $stateProvider.state("home", { | ||
| * views: { | ||
| * "": { | ||
| * template: "<h1>HELLO!</h1>" | ||
| * } | ||
| * } | ||
| * }) | ||
| * </pre> | ||
| * | ||
| * But typically you'll only use the views property if you name your view or have more than one view | ||
| * in the same template. There's not really a compelling reason to name a view if its the only one, | ||
| * but you could if you wanted, like so: | ||
| * <pre> | ||
| * <div ui-view="main"></div> | ||
| * </pre> | ||
| * <pre> | ||
| * $stateProvider.state("home", { | ||
| * views: { | ||
| * "main": { | ||
| * template: "<h1>HELLO!</h1>" | ||
| * } | ||
| * } | ||
| * }) | ||
| * </pre> | ||
| * | ||
| * Really though, you'll use views to set up multiple views: | ||
| * <pre> | ||
| * <div ui-view></div> | ||
| * <div ui-view="chart"></div> | ||
| * <div ui-view="data"></div> | ||
| * </pre> | ||
| * | ||
| * <pre> | ||
| * $stateProvider.state("home", { | ||
| * views: { | ||
| * "": { | ||
| * template: "<h1>HELLO!</h1>" | ||
| * }, | ||
| * "chart": { | ||
| * template: "<chart_thing/>" | ||
| * }, | ||
| * "data": { | ||
| * template: "<data_thing/>" | ||
| * } | ||
| * } | ||
| * }) | ||
| * </pre> | ||
| * | ||
| * Examples for `autoscroll`: | ||
| * | ||
| * <pre> | ||
| * <!-- If autoscroll present with no expression, | ||
| * then scroll ui-view into view --> | ||
| * <ui-view autoscroll/> | ||
| * | ||
| * <!-- If autoscroll present with valid expression, | ||
| * then scroll ui-view into view if expression evaluates to true --> | ||
| * <ui-view autoscroll='true'/> | ||
| * <ui-view autoscroll='false'/> | ||
| * <ui-view autoscroll='scopeVariable'/> | ||
| * </pre> | ||
| */ | ||
| $ViewDirective.$inject = ['$state', '$injector', '$uiViewScroll', '$interpolate']; | ||
| function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate) { | ||
|
|
||
| function getService() { | ||
| return ($injector.has) ? function(service) { | ||
| return $injector.has(service) ? $injector.get(service) : null; | ||
| } : function(service) { | ||
| try { | ||
| return $injector.get(service); | ||
| } catch (e) { | ||
| return null; | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| var service = getService(), | ||
| $animator = service('$animator'), | ||
| $animate = service('$animate'); | ||
|
|
||
| // Returns a set of DOM manipulation functions based on which Angular version | ||
| // it should use | ||
| function getRenderer(attrs, scope) { | ||
| var statics = function() { | ||
| return { | ||
| enter: function (element, target, cb) { target.after(element); cb(); }, | ||
| leave: function (element, cb) { element.remove(); cb(); } | ||
| }; | ||
| }; | ||
|
|
||
| if ($animate) { | ||
| return { | ||
| enter: function(element, target, cb) { | ||
| var promise = $animate.enter(element, null, target, cb); | ||
| if (promise && promise.then) promise.then(cb); | ||
| }, | ||
| leave: function(element, cb) { | ||
| var promise = $animate.leave(element, cb); | ||
| if (promise && promise.then) promise.then(cb); | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| if ($animator) { | ||
| var animate = $animator && $animator(scope, attrs); | ||
|
|
||
| return { | ||
| enter: function(element, target, cb) {animate.enter(element, null, target); cb(); }, | ||
| leave: function(element, cb) { animate.leave(element); cb(); } | ||
| }; | ||
| } | ||
|
|
||
| return statics(); | ||
| } | ||
|
|
||
| var directive = { | ||
| restrict: 'ECA', | ||
| terminal: true, | ||
| priority: 400, | ||
| transclude: 'element', | ||
| compile: function (tElement, tAttrs, $transclude) { | ||
| return function (scope, $element, attrs) { | ||
| var previousEl, currentEl, currentScope, latestLocals, | ||
| onloadExp = attrs.onload || '', | ||
| autoScrollExp = attrs.autoscroll, | ||
| renderer = getRenderer(attrs, scope); | ||
|
|
||
| scope.$on('$stateChangeSuccess', function() { | ||
| updateView(false); | ||
| }); | ||
| scope.$on('$viewContentLoading', function() { | ||
| updateView(false); | ||
| }); | ||
|
|
||
| updateView(true); | ||
|
|
||
| function cleanupLastView() { | ||
| if (previousEl) { | ||
| previousEl.remove(); | ||
| previousEl = null; | ||
| } | ||
|
|
||
| if (currentScope) { | ||
| currentScope.$destroy(); | ||
| currentScope = null; | ||
| } | ||
|
|
||
| if (currentEl) { | ||
| renderer.leave(currentEl, function() { | ||
| previousEl = null; | ||
| }); | ||
|
|
||
| previousEl = currentEl; | ||
| currentEl = null; | ||
| } | ||
| } | ||
|
|
||
| function updateView(firstTime) { | ||
| var newScope, | ||
| name = getUiViewName(scope, attrs, $element, $interpolate), | ||
| previousLocals = name && $state.$current && $state.$current.locals[name]; | ||
|
|
||
| if (!firstTime && previousLocals === latestLocals) return; // nothing to do | ||
| newScope = scope.$new(); | ||
| latestLocals = $state.$current.locals[name]; | ||
|
|
||
| var clone = $transclude(newScope, function(clone) { | ||
| renderer.enter(clone, $element, function onUiViewEnter() { | ||
| if(currentScope) { | ||
| currentScope.$emit('$viewContentAnimationEnded'); | ||
| } | ||
|
|
||
| if (angular.isDefined(autoScrollExp) && !autoScrollExp || scope.$eval(autoScrollExp)) { | ||
| $uiViewScroll(clone); | ||
| } | ||
| }); | ||
| cleanupLastView(); | ||
| }); | ||
|
|
||
| currentEl = clone; | ||
| currentScope = newScope; | ||
| /** | ||
| * @ngdoc event | ||
| * @name ui.router.state.directive:ui-view#$viewContentLoaded | ||
| * @eventOf ui.router.state.directive:ui-view | ||
| * @eventType emits on ui-view directive scope | ||
| * @description * | ||
| * Fired once the view is **loaded**, *after* the DOM is rendered. | ||
| * | ||
| * @param {Object} event Event object. | ||
| */ | ||
| currentScope.$emit('$viewContentLoaded'); | ||
| currentScope.$eval(onloadExp); | ||
| } | ||
| }; | ||
| } | ||
| }; | ||
|
|
||
| return directive; | ||
| } | ||
|
|
||
| $ViewDirectiveFill.$inject = ['$compile', '$controller', '$state', '$interpolate']; | ||
| function $ViewDirectiveFill ( $compile, $controller, $state, $interpolate) { | ||
| return { | ||
| restrict: 'ECA', | ||
| priority: -400, | ||
| compile: function (tElement) { | ||
| var initial = tElement.html(); | ||
| return function (scope, $element, attrs) { | ||
| var current = $state.$current, | ||
| name = getUiViewName(scope, attrs, $element, $interpolate), | ||
| locals = current && current.locals[name]; | ||
|
|
||
| if (! locals) { | ||
| return; | ||
| } | ||
|
|
||
| $element.data('$uiView', { name: name, state: locals.$$state }); | ||
| $element.html(locals.$template ? locals.$template : initial); | ||
|
|
||
| var link = $compile($element.contents()); | ||
|
|
||
| if (locals.$$controller) { | ||
| locals.$scope = scope; | ||
| var controller = $controller(locals.$$controller, locals); | ||
| if (locals.$$controllerAs) { | ||
| scope[locals.$$controllerAs] = controller; | ||
| } | ||
| $element.data('$ngControllerController', controller); | ||
| $element.children().data('$ngControllerController', controller); | ||
| } | ||
|
|
||
| link(scope); | ||
| }; | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| /** | ||
| * Shared ui-view code for both directives: | ||
| * Given scope, element, and its attributes, return the view's name | ||
| */ | ||
| function getUiViewName(scope, attrs, element, $interpolate) { | ||
| var name = $interpolate(attrs.uiView || attrs.name || '')(scope); | ||
| var inherited = element.inheritedData('$uiView'); | ||
| return name.indexOf('@') >= 0 ? name : (name + '@' + (inherited ? inherited.state.name : '')); | ||
| } | ||
|
|
||
| angular.module('ui.router.state').directive('uiView', $ViewDirective); | ||
| angular.module('ui.router.state').directive('uiView', $ViewDirectiveFill); |
| @@ -0,0 +1,52 @@ | ||
| /** | ||
| * @ngdoc object | ||
| * @name ui.router.state.$uiViewScrollProvider | ||
| * | ||
| * @description | ||
| * Provider that returns the {@link ui.router.state.$uiViewScroll} service function. | ||
| */ | ||
| function $ViewScrollProvider() { | ||
|
|
||
| var useAnchorScroll = false; | ||
|
|
||
| /** | ||
| * @ngdoc function | ||
| * @name ui.router.state.$uiViewScrollProvider#useAnchorScroll | ||
| * @methodOf ui.router.state.$uiViewScrollProvider | ||
| * | ||
| * @description | ||
| * Reverts back to using the core [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) service for | ||
| * scrolling based on the url anchor. | ||
| */ | ||
| this.useAnchorScroll = function () { | ||
| useAnchorScroll = true; | ||
| }; | ||
|
|
||
| /** | ||
| * @ngdoc object | ||
| * @name ui.router.state.$uiViewScroll | ||
| * | ||
| * @requires $anchorScroll | ||
| * @requires $timeout | ||
| * | ||
| * @description | ||
| * When called with a jqLite element, it scrolls the element into view (after a | ||
| * `$timeout` so the DOM has time to refresh). | ||
| * | ||
| * If you prefer to rely on `$anchorScroll` to scroll the view to the anchor, | ||
| * this can be enabled by calling {@link ui.router.state.$uiViewScrollProvider#methods_useAnchorScroll `$uiViewScrollProvider.useAnchorScroll()`}. | ||
| */ | ||
| this.$get = ['$anchorScroll', '$timeout', function ($anchorScroll, $timeout) { | ||
| if (useAnchorScroll) { | ||
| return $anchorScroll; | ||
| } | ||
|
|
||
| return function ($element) { | ||
| $timeout(function () { | ||
| $element[0].scrollIntoView(); | ||
| }, 0, false); | ||
| }; | ||
| }]; | ||
| } | ||
|
|
||
| angular.module('ui.router.state').provider('$uiViewScroll', $ViewScrollProvider); |
| @@ -0,0 +1,17 @@ | ||
| { | ||
| "name": "angular", | ||
| "version": "1.4.3", | ||
| "main": "./angular.js", | ||
| "ignore": [], | ||
| "dependencies": {}, | ||
| "homepage": "https://github.com/angular/bower-angular", | ||
| "_release": "1.4.3", | ||
| "_resolution": { | ||
| "type": "version", | ||
| "tag": "v1.4.3", | ||
| "commit": "dbd689e8103a6366e53e1f6786727f7c65ccfd75" | ||
| }, | ||
| "_source": "git://github.com/angular/bower-angular.git", | ||
| "_target": "1.4.3", | ||
| "_originalSource": "angular" | ||
| } |
| @@ -0,0 +1,64 @@ | ||
| # packaged angular | ||
|
|
||
| This repo is for distribution on `npm` and `bower`. The source for this module is in the | ||
| [main AngularJS repo](https://github.com/angular/angular.js). | ||
| Please file issues and pull requests against that repo. | ||
|
|
||
| ## Install | ||
|
|
||
| You can install this package either with `npm` or with `bower`. | ||
|
|
||
| ### npm | ||
|
|
||
| ```shell | ||
| npm install angular | ||
| ``` | ||
|
|
||
| Then add a `<script>` to your `index.html`: | ||
|
|
||
| ```html | ||
| <script src="/node_modules/angular/angular.js"></script> | ||
| ``` | ||
|
|
||
| Or `require('angular')` from your code. | ||
|
|
||
| ### bower | ||
|
|
||
| ```shell | ||
| bower install angular | ||
| ``` | ||
|
|
||
| Then add a `<script>` to your `index.html`: | ||
|
|
||
| ```html | ||
| <script src="/bower_components/angular/angular.js"></script> | ||
| ``` | ||
|
|
||
| ## Documentation | ||
|
|
||
| Documentation is available on the | ||
| [AngularJS docs site](http://docs.angularjs.org/). | ||
|
|
||
| ## License | ||
|
|
||
| The MIT License | ||
|
|
||
| Copyright (c) 2010-2015 Google, Inc. http://angularjs.org | ||
|
|
||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
|
|
||
| The above copyright notice and this permission notice shall be included in | ||
| all copies or substantial portions of the Software. | ||
|
|
||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| THE SOFTWARE. |
| @@ -0,0 +1,21 @@ | ||
| /* Include this file in your html if you are using the CSP mode. */ | ||
|
|
||
| @charset "UTF-8"; | ||
|
|
||
| [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], | ||
| .ng-cloak, .x-ng-cloak, | ||
| .ng-hide:not(.ng-hide-animate) { | ||
| display: none !important; | ||
| } | ||
|
|
||
| ng\:form { | ||
| display: block; | ||
| } | ||
|
|
||
| .ng-animate-shim { | ||
| visibility:hidden; | ||
| } | ||
|
|
||
| .ng-anchor { | ||
| position:absolute; | ||
| } |