New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

angular-visor

Package Overview
Dependencies
Maintainers
2
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

angular-visor - npm Package Compare versions

Comparing version 0.1.1 to 0.1.2

12

bower.json
{
"name": "visor",
"description": "Angular authentication and authorization library",
"version": "0.1.1",
"version": "0.1.2",
"homepage": "https://github.com/illniyar/visor",
"main": "./release/visor.js",
"dependencies": {
"angular": "~1.3.0"
"angular": ">= 1.2.0"
},
"devDependencies": {
"angular-ui-router": "~0.2.13",
"angular-mocks": "~1.3.0",
"angular-route": "~1.3.0",
"angular-cookies": "~1.3.0"
"angular-ui-router": ">= 0.2.13",
"angular-mocks": ">= 1.2.0",
"angular-route": ">= 1.2.0",
"angular-cookies": ">= 1.2.0"
},

@@ -16,0 +16,0 @@ "ignore": [

@@ -1,9 +0,26 @@

<a name"0.1.1"></a>
### 0.1.1 (2015-07-08)
<a name"0.1.2"></a>
### 0.1.2 (2015-12-07)
#### Bug Fixes
* **visor:** next parameter now overrides existing parameters ([b0c89109](https://github.com/illniyar/visor/commit/b0c89109), closes [#14](https://github.com/illniyar/visor/issues/14))
#### Features
* **visor:** allow changing next parameter name ([04d5d5d0](https://github.com/illniyar/visor/commit/04d5d5d0))
<a name"0.1.0"></a>
## 0.1.0 (2015-07-08)
### 0.1.0 (2015-07-08)
#### Bug Fixes
* **ui-router:** state inheritance with dot notation does work with two levels of inheritance ([b7b05d5fce7dafd9f1047dc1e01ec2f4fd483ed5](https://github.com/illniyar/visor/commit/b7b05d5fce7dafd9f1047dc1e01ec2f4fd483ed5))
#### Features
* **visor.allowed:** add directives to add/remove classes from an element based on route restriction ([84f443bda058a6a950470899cd1331342ae05c69](https://github.com/illniyar/visor/commit/84f443bda058a6a950470899cd1331342ae05c69))
<a name"0.0.6"></a>

@@ -10,0 +27,0 @@ ### 0.0.6 (2015-06-17)

@@ -74,3 +74,11 @@ module.exports = function (grunt) {

dest: '<%=releasedir%>/'
}]
},
{src: 'bower_components/angular/angular.js',
dest:'sample/lib/angular.js'},
{src: 'bower_components/angular-ui-router/release/angular-ui-router.js',
dest:'sample/lib/angular-ui-router.js'},
{src: 'bower_components/angular-route/angular-route.js',
dest:'sample/lib/angular-route.js'},
{src: 'bower_components/angular-cookies/angular-cookies.js',
dest:'sample/lib/angular-cookies.js'}]
},

@@ -162,6 +170,6 @@ site: {

grunt.registerTask('site', 'Build and create site', ['dist', 'copy:site', 'ngdocs:all']);
grunt.registerTask('gh-pages', 'Build, create site and push to gh-pages', ['gh-pages', 'clean:gh-pages']);
grunt.registerTask('build-gh-pages', 'Build, create site and push to gh-pages', ['gh-pages', 'clean:gh-pages']);
grunt.registerTask('push-to-git', 'Add, commit, create tag and push to git', ['gitadd:release', 'gitcommit:master', 'gittag:release', 'gitpush:origin']);
grunt.registerTask('publish', 'Builds and publishes to all relevent repositories',
['bumpup:patch', 'site', 'changelog', 'push-to-git', 'npm-publish'])
['bumpup:patch', 'site', 'changelog', 'push-to-git', 'npm-publish','build-gh-pages'])
}
{
"name": "angular-visor",
"author": "Illniyar",
"version": "0.1.1",
"version": "0.1.2",
"main": "release/visor.js",

@@ -42,4 +42,4 @@ "description": "Angular authentication and authorization library",

"dependencies": {
"angular": "^1.3.16"
"angular": ">= 1.2.0"
}
}
/**visor
* Angular authentication and authorization library
* @version v0.1.1
* @version v0.1.2
* @link https://github.com/illniyar/visor.git

@@ -319,13 +319,4 @@ * @license MIT License, http://www.opensource.org/licenses/MIT

.provider("visor", [function () {
function addNextToUrl(url, $location, restrictedUrl) {
if (config.shouldAddNext) {
if (url.indexOf("?") >= 0) {
return url.replace(/\?/, "?next=" + encodeURIComponent(restrictedUrl) + "&");
}
return url + "?next=" + encodeURIComponent(restrictedUrl);
} else {
return url;
}
}
var config = this;

@@ -399,4 +390,18 @@ /**

config.shouldAddNext = true;
/**
* @ngdoc property
* @name visor.visorProvider#nextParameterName
* @propertyOf visor.visorProvider
*
* @description
*
* The name of the parameter where the url that was restricted will be added to determine redirections
* when using {@link visor.visorProvider#shouldAddNext `visorProvider.shouldAddNext`}
*
* See {@link visor.visorProvider#shouldAddNext `visorProvider.shouldAddNext`} for more.
*
* Defaults to 'next'
*/
config.nextParameterName = 'next';
/**
* @ngdoc function

@@ -459,3 +464,6 @@ * @name visor.visorProvider#authenticate

config.doOnNotAuthenticated = ["$location", "restrictedUrl", function ($location, restrictedUrl) {
$location.url(addNextToUrl(config.loginRoute, $location, restrictedUrl))
$location.url(config.loginRoute);
if (config.shouldAddNext) {
$location.search(config.nextParameterName,restrictedUrl);
}
}];

@@ -485,3 +493,3 @@ /**

config.doAfterManualAuthentication = ["$location", function ($location) {
$location.url($location.search().next || config.homeRoute);
$location.url($location.search()[config.nextParameterName] || config.homeRoute);
}];

@@ -488,0 +496,0 @@ /**

/**visor
* Angular authentication and authorization library
* @version v0.1.1
* @version v0.1.2
* @link https://github.com/illniyar/visor.git

@@ -8,2 +8,2 @@ * @license MIT License, http://www.opensource.org/licenses/MIT

"undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="visor"),function(a,b,c){!function(){"use strict";b.module("delayLocationChange",[]).service("delayLocationChange",["$rootScope","$q","$timeout","$location","$injector",function(a,b,c,d,e){function f(){m--,o&&0>=m&&g()}function g(){d.absUrl()===i?a.$broadcast("$locationChangeSuccess",i,j):d.url(k)}function h(a){m++,a["finally"](f)}var i,j,k,l=function(a){a.then?h(a):o?h(e.invoke(fn)):n.push(a)},m=0,n=[],o=!1,p=a.$on("$locationChangeStart",function(a,b,g){o=!0,k=d.url(),p(),a.preventDefault(),n.forEach(function(a){h(e.invoke(a))}),0!==m||i||(m++,c(f,1)),i=b,j=g});return l}])}(),function(){"use strict";b.module("visor.allowed",["visor.permissions"]).directive("showIfAllowed",["visorPermissions","$animate",function(a,b){return{restrict:"A",link:function(c,d,e){function f(c){var e=a.checkPermissionsForRoute(c);b[e?"removeClass":"addClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})}var g=a.notifyOnCacheClear(function(){f(e.showIfAllowed)});e.$observe("showIfAllowed",f),c.$on("$destroy",g)}}}]).directive("classIfRestricted",["visorPermissions","$animate",function(a,b){return{restrict:"A",link:function(c,d,e){function f(c){var f=a.checkPermissionsForRoute(c);b[f?"removeClass":"addClass"](d,e.restrictedClass||"visor-restricted")}var g=a.notifyOnCacheClear(function(){f(e.classIfRestricted)});e.$observe("classIfRestricted",f),c.$on("$destroy",g)}}}])}(),function(){"use strict";b.module("visor",["visor.permissions","visor.ui-router","visor.ngRoute","delayLocationChange","visor.allowed"]).constant("authenticatedOnly",function(a){return!!a}).constant("notForAuthenticated",function(a){return a===c}).provider("visor",[function(){function a(a,c,d){return b.shouldAddNext?a.indexOf("?")>=0?a.replace(/\?/,"?next="+encodeURIComponent(d)+"&"):a+"?next="+encodeURIComponent(d):a}var b=this;b.authenticateOnStartup=!0,b.loginRoute="/login",b.homeRoute="/",b.notAuthorizedRoute="/access_denied",b.shouldAddNext=!0,b.authenticate=function(){throw new Error("visorProvider.authenticate must be defined to use visor")},b.doOnNotAuthenticated=["$location","restrictedUrl",function(c,d){c.url(a(b.loginRoute,c,d))}],b.doAfterManualAuthentication=["$location",function(a){a.url(a.search().next||b.homeRoute)}],b.doOnNotAuthorized=["$location",function(a){a.url(b.notAuthorizedRoute)}],this.$get=["$injector","$q","$rootScope","$location","visorPermissions",function(a,d,e,f,g){function h(a){k.authData=a,g.invokeParameters=[k.authData],g.clearPermissionCache()}function i(){k.authData=c,g.invokeParameters=[],g.clearPermissionCache()}var j=!1,k={authenticate:function(c){if(j&&!c)return j;var e=d.defer();return j=e.promise,a.invoke(b.authenticate).then(h,i)["finally"](function(){e.resolve(k.authData)}),e.promise},setAuthenticated:function(c){h(c),j=d.when(c),a.invoke(b.doAfterManualAuthentication,null,{authData:c})},isAuthenticated:function(){return!!k.authData},onNotAllowed:function(c){k.isAuthenticated()?a.invoke(b.doOnNotAuthorized,null,{restrictedUrl:c}):a.invoke(b.doOnNotAuthenticated,null,{restrictedUrl:c})},setUnauthenticated:function(){i()},config:b};return k}]}]).run(["visor","delayLocationChange",function(a,b){a.config.authenticateOnStartup&&b(a.authenticate())}]).config(["visorPermissionsProvider",function(a){a.doBeforeFirstCheck.push(["visor",function(a){return a.authenticate()}]),a.onNotAllowed=["visor","restrictedUrl",function(a,b){a.onNotAllowed(b)}]}])}(),function(){b.module("visor.ngRoute",["visor.permissions"]).run(["$rootScope","visorPermissions","$injector",function(a,b,c){var d=!1,e=null;try{e=c.get("$route"),d=!0}catch(f){}d&&(b.getRoute=function(a){for(var b in e.routes){var c=e.routes[b];if(c.regexp.exec(a))return c}return null},a.$on("$routeChangeStart",function(a,c){c.resolve=c.resolve||{},b.onRouteChange(c,function(a){c.resolve._visorDelay=function(){return a}})}))}])}(),function(){b.module("visor.permissions",[]).provider("visorPermissions",[function(){var a=this;a.getPermissionsFromNext=function(a){return a.restrict?[a.restrict]:[]},a.doBeforeFirstCheck=[],a.onNotAllowed=function(){},a.invokeParameters=[],a.getRoute=function(a){throw new Error("method not implemented")};var d=!1;this.$get=["$q","$injector","$location",function(e,f,g){function h(a){if(!a||0===a.length)return!0;b.isArray(a)||(a=[a]);var c=!0;return a.forEach(function(a){c=c&&a.apply(null,l.invokeParameters)}),c}function i(b,c){var d=h(c);return d?!0:(l.invokeNotAllowed(a.onNotAllowed),!1)}var j=[],k={},l={onRouteChange:function(b,c){var g=l.getPermissionsFromNext(b);if(!g||0==g.length)return!0;if(d)return i(b,g);var h=e.defer();return c(h.promise),e.all(a.doBeforeFirstCheck.map(function(a){return f.invoke(a)}))["finally"](function(){d=!0,i(b,g)?h.resolve(!0):h.reject(!1)}),"delayed"},getPermissionsFromNext:a.getPermissionsFromNext,checkPermissionsForRoute:function(a){var b=k[a];if(b!==c)return b;var d=l.getRoute(a);if(!d)return c;var e=l.getPermissionsFromNext(d);return b=h(e),k[a]=b,b},clearPermissionCache:function(){k={},j.forEach(function(a){a&&a()})},notifyOnCacheClear:function(a){return j.push(a),function(){var b=j.indexOf(a);-1!=b&&j.splice(b,1)}},getRoute:a.getRoute,invokeParameters:a.invokeParameters,invokeNotAllowed:function(a){f.invoke(a,null,{restrictedUrl:g.url()})}};return l}]}])}(),function(){b.module("visor.ui-router",["visor.permissions"]).run(["$rootScope","visorPermissions","$injector","$timeout","$location",function(a,b,c,d,e){var f=!1;try{c.get("$state"),f=!0}catch(g){}f&&c.invoke(["$state",function(e){b.getPermissionsFromNext=function(a){for(var b=[];a;)if(a.restrict&&b.unshift(a.restrict),a.parent)a=e.get(a.parent);else if(a.name.indexOf(".")>0){var c=a.name.split(".");c.pop();var d=c.join(".");a=e.get(d)}else a=null;return b};var f=(c.get("$urlRouter"),null),g=!1;a.$on("$stateChangeStart",function(a,c,d){if(g)return void(g=!1);f=e.href(c,d).replace(/^#/,"");var h=b.onRouteChange(c,function(a){a.then(function(){g=!0,e.go(c,d)})});h&&"delayed"!==h||a.preventDefault()}),b.invokeNotAllowed=function(a){d(function(){c.invoke(a,null,{restrictedUrl:f})},0)},b.getRoute=function(a){return e.get(a)}}])}])}()}(window,window.angular);
"undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="visor"),function(a,b,c){!function(){"use strict";b.module("delayLocationChange",[]).service("delayLocationChange",["$rootScope","$q","$timeout","$location","$injector",function(a,b,c,d,e){function f(){m--,o&&0>=m&&g()}function g(){d.absUrl()===i?a.$broadcast("$locationChangeSuccess",i,j):d.url(k)}function h(a){m++,a["finally"](f)}var i,j,k,l=function(a){a.then?h(a):o?h(e.invoke(fn)):n.push(a)},m=0,n=[],o=!1,p=a.$on("$locationChangeStart",function(a,b,g){o=!0,k=d.url(),p(),a.preventDefault(),n.forEach(function(a){h(e.invoke(a))}),0!==m||i||(m++,c(f,1)),i=b,j=g});return l}])}(),function(){"use strict";b.module("visor.allowed",["visor.permissions"]).directive("showIfAllowed",["visorPermissions","$animate",function(a,b){return{restrict:"A",link:function(c,d,e){function f(c){var e=a.checkPermissionsForRoute(c);b[e?"removeClass":"addClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})}var g=a.notifyOnCacheClear(function(){f(e.showIfAllowed)});e.$observe("showIfAllowed",f),c.$on("$destroy",g)}}}]).directive("classIfRestricted",["visorPermissions","$animate",function(a,b){return{restrict:"A",link:function(c,d,e){function f(c){var f=a.checkPermissionsForRoute(c);b[f?"removeClass":"addClass"](d,e.restrictedClass||"visor-restricted")}var g=a.notifyOnCacheClear(function(){f(e.classIfRestricted)});e.$observe("classIfRestricted",f),c.$on("$destroy",g)}}}])}(),function(){"use strict";b.module("visor",["visor.permissions","visor.ui-router","visor.ngRoute","delayLocationChange","visor.allowed"]).constant("authenticatedOnly",function(a){return!!a}).constant("notForAuthenticated",function(a){return a===c}).provider("visor",[function(){var a=this;a.authenticateOnStartup=!0,a.loginRoute="/login",a.homeRoute="/",a.notAuthorizedRoute="/access_denied",a.shouldAddNext=!0,a.nextParameterName="next",a.authenticate=function(){throw new Error("visorProvider.authenticate must be defined to use visor")},a.doOnNotAuthenticated=["$location","restrictedUrl",function(b,c){b.url(a.loginRoute),a.shouldAddNext&&b.search(a.nextParameterName,c)}],a.doAfterManualAuthentication=["$location",function(b){b.url(b.search()[a.nextParameterName]||a.homeRoute)}],a.doOnNotAuthorized=["$location",function(b){b.url(a.notAuthorizedRoute)}],this.$get=["$injector","$q","$rootScope","$location","visorPermissions",function(b,d,e,f,g){function h(a){k.authData=a,g.invokeParameters=[k.authData],g.clearPermissionCache()}function i(){k.authData=c,g.invokeParameters=[],g.clearPermissionCache()}var j=!1,k={authenticate:function(c){if(j&&!c)return j;var e=d.defer();return j=e.promise,b.invoke(a.authenticate).then(h,i)["finally"](function(){e.resolve(k.authData)}),e.promise},setAuthenticated:function(c){h(c),j=d.when(c),b.invoke(a.doAfterManualAuthentication,null,{authData:c})},isAuthenticated:function(){return!!k.authData},onNotAllowed:function(c){k.isAuthenticated()?b.invoke(a.doOnNotAuthorized,null,{restrictedUrl:c}):b.invoke(a.doOnNotAuthenticated,null,{restrictedUrl:c})},setUnauthenticated:function(){i()},config:a};return k}]}]).run(["visor","delayLocationChange",function(a,b){a.config.authenticateOnStartup&&b(a.authenticate())}]).config(["visorPermissionsProvider",function(a){a.doBeforeFirstCheck.push(["visor",function(a){return a.authenticate()}]),a.onNotAllowed=["visor","restrictedUrl",function(a,b){a.onNotAllowed(b)}]}])}(),function(){b.module("visor.ngRoute",["visor.permissions"]).run(["$rootScope","visorPermissions","$injector",function(a,b,c){var d=!1,e=null;try{e=c.get("$route"),d=!0}catch(f){}d&&(b.getRoute=function(a){for(var b in e.routes){var c=e.routes[b];if(c.regexp.exec(a))return c}return null},a.$on("$routeChangeStart",function(a,c){c.resolve=c.resolve||{},b.onRouteChange(c,function(a){c.resolve._visorDelay=function(){return a}})}))}])}(),function(){b.module("visor.permissions",[]).provider("visorPermissions",[function(){var a=this;a.getPermissionsFromNext=function(a){return a.restrict?[a.restrict]:[]},a.doBeforeFirstCheck=[],a.onNotAllowed=function(){},a.invokeParameters=[],a.getRoute=function(a){throw new Error("method not implemented")};var d=!1;this.$get=["$q","$injector","$location",function(e,f,g){function h(a){if(!a||0===a.length)return!0;b.isArray(a)||(a=[a]);var c=!0;return a.forEach(function(a){c=c&&a.apply(null,l.invokeParameters)}),c}function i(b,c){var d=h(c);return d?!0:(l.invokeNotAllowed(a.onNotAllowed),!1)}var j=[],k={},l={onRouteChange:function(b,c){var g=l.getPermissionsFromNext(b);if(!g||0==g.length)return!0;if(d)return i(b,g);var h=e.defer();return c(h.promise),e.all(a.doBeforeFirstCheck.map(function(a){return f.invoke(a)}))["finally"](function(){d=!0,i(b,g)?h.resolve(!0):h.reject(!1)}),"delayed"},getPermissionsFromNext:a.getPermissionsFromNext,checkPermissionsForRoute:function(a){var b=k[a];if(b!==c)return b;var d=l.getRoute(a);if(!d)return c;var e=l.getPermissionsFromNext(d);return b=h(e),k[a]=b,b},clearPermissionCache:function(){k={},j.forEach(function(a){a&&a()})},notifyOnCacheClear:function(a){return j.push(a),function(){var b=j.indexOf(a);-1!=b&&j.splice(b,1)}},getRoute:a.getRoute,invokeParameters:a.invokeParameters,invokeNotAllowed:function(a){f.invoke(a,null,{restrictedUrl:g.url()})}};return l}]}])}(),function(){b.module("visor.ui-router",["visor.permissions"]).run(["$rootScope","visorPermissions","$injector","$timeout","$location",function(a,b,c,d,e){var f=!1;try{c.get("$state"),f=!0}catch(g){}f&&c.invoke(["$state",function(e){b.getPermissionsFromNext=function(a){for(var b=[];a;)if(a.restrict&&b.unshift(a.restrict),a.parent)a=e.get(a.parent);else if(a.name.indexOf(".")>0){var c=a.name.split(".");c.pop();var d=c.join(".");a=e.get(d)}else a=null;return b};var f=(c.get("$urlRouter"),null),g=!1;a.$on("$stateChangeStart",function(a,c,d){if(g)return void(g=!1);f=e.href(c,d).replace(/^#/,"");var h=b.onRouteChange(c,function(a){a.then(function(){g=!0,e.go(c,d)})});h&&"delayed"!==h||a.preventDefault()}),b.invokeNotAllowed=function(a){d(function(){c.invoke(a,null,{restrictedUrl:f})},0)},b.getRoute=function(a){return e.get(a)}}])}])}()}(window,window.angular);
/**
* @license AngularJS v1.3.4
* (c) 2010-2014 Google, Inc. http://angularjs.org
* @license AngularJS v1.4.8
* (c) 2010-2015 Google, Inc. http://angularjs.org
* License: MIT
*/
(function (window, angular, undefined) {
'use strict';
(function(window, angular, undefined) {'use strict';
/**
* @ngdoc module
* @name ngCookies
* @description
*
* # ngCookies
*
* The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
*
*
* <div doc-module-components="ngCookies"></div>
*
* See {@link ngCookies.$cookies `$cookies`} for usage.
*/
angular.module('ngCookies', ['ng']).
/**
* @ngdoc provider
* @name $cookiesProvider
* @description
* Use `$cookiesProvider` to change the default behavior of the {@link ngCookies.$cookies $cookies} service.
* */
provider('$cookies', [function $CookiesProvider() {
/**
* @ngdoc module
* @name ngCookies
* @ngdoc property
* @name $cookiesProvider#defaults
* @description
*
* # ngCookies
* Object containing default options to pass when setting cookies.
*
* The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
* The object may have following properties:
*
* - **path** - `{string}` - The cookie will be available only for this path and its
* sub-paths. By default, this would be the URL that appears in your base tag.
* - **domain** - `{string}` - The cookie will be available only for this domain and
* its sub-domains. For obvious security reasons the user agent will not accept the
* cookie if the current domain is not a sub domain or equals to the requested domain.
* - **expires** - `{string|Date}` - String of the form "Wdy, DD Mon YYYY HH:MM:SS GMT"
* or a Date object indicating the exact date/time this cookie will expire.
* - **secure** - `{boolean}` - The cookie will be available only in secured connection.
*
* <div doc-module-components="ngCookies"></div>
* Note: by default the address that appears in your `<base>` tag will be used as path.
* This is important so that cookies will be visible for all routes in case html5mode is enabled
*
* See {@link ngCookies.$cookies `$cookies`} and
* {@link ngCookies.$cookieStore `$cookieStore`} for usage.
*/
**/
var defaults = this.defaults = {};
function calcOptions(options) {
return options ? angular.extend({}, defaults, options) : defaults;
}
angular.module('ngCookies', ['ng']).
/**

@@ -34,5 +67,7 @@ * @ngdoc service

*
* Only a simple Object is exposed and by adding or removing properties to/from this object, new
* cookies are created/deleted at the end of current $eval.
* The object's properties can only be strings.
* <div class="alert alert-info">
* Up until Angular 1.3, `$cookies` exposed properties that represented the
* current browser cookie values. In version 1.4, this behavior has changed, and
* `$cookies` now provides a standard api of getters, setters etc.
* </div>
*

@@ -46,164 +81,243 @@ * Requires the {@link ngCookies `ngCookies`} module to be installed.

* .controller('ExampleController', ['$cookies', function($cookies) {
* // Retrieving a cookie
* var favoriteCookie = $cookies.myFavorite;
* // Setting a cookie
* $cookies.myFavorite = 'oatmeal';
* }]);
* // Retrieving a cookie
* var favoriteCookie = $cookies.get('myFavorite');
* // Setting a cookie
* $cookies.put('myFavorite', 'oatmeal');
* }]);
* ```
*/
factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {
var cookies = {},
lastCookies = {},
lastBrowserCookies,
runEval = false,
copy = angular.copy,
isUndefined = angular.isUndefined;
this.$get = ['$$cookieReader', '$$cookieWriter', function($$cookieReader, $$cookieWriter) {
return {
/**
* @ngdoc method
* @name $cookies#get
*
* @description
* Returns the value of given cookie key
*
* @param {string} key Id to use for lookup.
* @returns {string} Raw cookie value.
*/
get: function(key) {
return $$cookieReader()[key];
},
//creates a poller fn that copies all cookies from the $browser to service & inits the service
$browser.addPollFn(function () {
var currentCookies = $browser.cookies();
if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl
lastBrowserCookies = currentCookies;
copy(currentCookies, lastCookies);
copy(currentCookies, cookies);
if (runEval) $rootScope.$apply();
}
})();
/**
* @ngdoc method
* @name $cookies#getObject
*
* @description
* Returns the deserialized value of given cookie key
*
* @param {string} key Id to use for lookup.
* @returns {Object} Deserialized cookie value.
*/
getObject: function(key) {
var value = this.get(key);
return value ? angular.fromJson(value) : value;
},
runEval = true;
/**
* @ngdoc method
* @name $cookies#getAll
*
* @description
* Returns a key value object with all the cookies
*
* @returns {Object} All cookies
*/
getAll: function() {
return $$cookieReader();
},
//at the end of each eval, push cookies
//TODO: this should happen before the "delayed" watches fire, because if some cookies are not
// strings or browser refuses to store some cookies, we update the model in the push fn.
$rootScope.$watch(push);
/**
* @ngdoc method
* @name $cookies#put
*
* @description
* Sets a value for given cookie key
*
* @param {string} key Id for the `value`.
* @param {string} value Raw value to be stored.
* @param {Object=} options Options object.
* See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
*/
put: function(key, value, options) {
$$cookieWriter(key, value, calcOptions(options));
},
return cookies;
/**
* @ngdoc method
* @name $cookies#putObject
*
* @description
* Serializes and sets a value for given cookie key
*
* @param {string} key Id for the `value`.
* @param {Object} value Value to be stored.
* @param {Object=} options Options object.
* See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
*/
putObject: function(key, value, options) {
this.put(key, angular.toJson(value), options);
},
/**
* @ngdoc method
* @name $cookies#remove
*
* @description
* Remove given cookie
*
* @param {string} key Id of the key-value pair to delete.
* @param {Object=} options Options object.
* See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
*/
remove: function(key, options) {
$$cookieWriter(key, undefined, calcOptions(options));
}
};
}];
}]);
/**
* Pushes all the cookies from the service to the browser and verifies if all cookies were
* stored.
*/
function push() {
var name,
value,
browserCookies,
updated;
angular.module('ngCookies').
/**
* @ngdoc service
* @name $cookieStore
* @deprecated
* @requires $cookies
*
* @description
* Provides a key-value (string-object) storage, that is backed by session cookies.
* Objects put or retrieved from this storage are automatically serialized or
* deserialized by angular's toJson/fromJson.
*
* Requires the {@link ngCookies `ngCookies`} module to be installed.
*
* <div class="alert alert-danger">
* **Note:** The $cookieStore service is **deprecated**.
* Please use the {@link ngCookies.$cookies `$cookies`} service instead.
* </div>
*
* @example
*
* ```js
* angular.module('cookieStoreExample', ['ngCookies'])
* .controller('ExampleController', ['$cookieStore', function($cookieStore) {
* // Put cookie
* $cookieStore.put('myFavorite','oatmeal');
* // Get cookie
* var favoriteCookie = $cookieStore.get('myFavorite');
* // Removing a cookie
* $cookieStore.remove('myFavorite');
* }]);
* ```
*/
factory('$cookieStore', ['$cookies', function($cookies) {
//delete any cookies deleted in $cookies
for (name in lastCookies) {
if (isUndefined(cookies[name])) {
$browser.cookies(name, undefined);
}
}
return {
/**
* @ngdoc method
* @name $cookieStore#get
*
* @description
* Returns the value of given cookie key
*
* @param {string} key Id to use for lookup.
* @returns {Object} Deserialized cookie value, undefined if the cookie does not exist.
*/
get: function(key) {
return $cookies.getObject(key);
},
//update all cookies updated in $cookies
for (name in cookies) {
value = cookies[name];
if (!angular.isString(value)) {
value = '' + value;
cookies[name] = value;
}
if (value !== lastCookies[name]) {
$browser.cookies(name, value);
updated = true;
}
}
/**
* @ngdoc method
* @name $cookieStore#put
*
* @description
* Sets a value for given cookie key
*
* @param {string} key Id for the `value`.
* @param {Object} value Value to be stored.
*/
put: function(key, value) {
$cookies.putObject(key, value);
},
//verify what was actually stored
if (updated) {
updated = false;
browserCookies = $browser.cookies();
/**
* @ngdoc method
* @name $cookieStore#remove
*
* @description
* Remove given cookie
*
* @param {string} key Id of the key-value pair to delete.
*/
remove: function(key) {
$cookies.remove(key);
}
};
for (name in cookies) {
if (cookies[name] !== browserCookies[name]) {
//delete or reset all cookies that the browser dropped from $cookies
if (isUndefined(browserCookies[name])) {
delete cookies[name];
} else {
cookies[name] = browserCookies[name];
}
updated = true;
}
}
}
}
}]).
}]);
/**
* @name $$cookieWriter
* @requires $document
*
* @description
* This is a private service for writing cookies
*
* @param {string} name Cookie name
* @param {string=} value Cookie value (if undefined, cookie will be deleted)
* @param {Object=} options Object with options that need to be stored for the cookie.
*/
function $$CookieWriter($document, $log, $browser) {
var cookiePath = $browser.baseHref();
var rawDocument = $document[0];
/**
* @ngdoc service
* @name $cookieStore
* @requires $cookies
*
* @description
* Provides a key-value (string-object) storage, that is backed by session cookies.
* Objects put or retrieved from this storage are automatically serialized or
* deserialized by angular's toJson/fromJson.
*
* Requires the {@link ngCookies `ngCookies`} module to be installed.
*
* @example
*
* ```js
* angular.module('cookieStoreExample', ['ngCookies'])
* .controller('ExampleController', ['$cookieStore', function($cookieStore) {
* // Put cookie
* $cookieStore.put('myFavorite','oatmeal');
* // Get cookie
* var favoriteCookie = $cookieStore.get('myFavorite');
* // Removing a cookie
* $cookieStore.remove('myFavorite');
* }]);
* ```
*/
factory('$cookieStore', ['$cookies', function ($cookies) {
function buildCookieString(name, value, options) {
var path, expires;
options = options || {};
expires = options.expires;
path = angular.isDefined(options.path) ? options.path : cookiePath;
if (angular.isUndefined(value)) {
expires = 'Thu, 01 Jan 1970 00:00:00 GMT';
value = '';
}
if (angular.isString(expires)) {
expires = new Date(expires);
}
return {
/**
* @ngdoc method
* @name $cookieStore#get
*
* @description
* Returns the value of given cookie key
*
* @param {string} key Id to use for lookup.
* @returns {Object} Deserialized cookie value.
*/
get: function (key) {
var value = $cookies[key];
return value ? angular.fromJson(value) : value;
},
var str = encodeURIComponent(name) + '=' + encodeURIComponent(value);
str += path ? ';path=' + path : '';
str += options.domain ? ';domain=' + options.domain : '';
str += expires ? ';expires=' + expires.toUTCString() : '';
str += options.secure ? ';secure' : '';
/**
* @ngdoc method
* @name $cookieStore#put
*
* @description
* Sets a value for given cookie key
*
* @param {string} key Id for the `value`.
* @param {Object} value Value to be stored.
*/
put: function (key, value) {
$cookies[key] = angular.toJson(value);
},
// per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
// - 300 cookies
// - 20 cookies per unique domain
// - 4096 bytes per cookie
var cookieLength = str.length + 1;
if (cookieLength > 4096) {
$log.warn("Cookie '" + name +
"' possibly not set or overflowed because it was too large (" +
cookieLength + " > 4096 bytes)!");
}
/**
* @ngdoc method
* @name $cookieStore#remove
*
* @description
* Remove given cookie
*
* @param {string} key Id of the key-value pair to delete.
*/
remove: function (key) {
delete $cookies[key];
}
};
return str;
}
}]);
return function(name, value, options) {
rawDocument.cookie = buildCookieString(name, value, options);
};
}
$$CookieWriter.$inject = ['$document', '$log', '$browser'];
angular.module('ngCookies').provider('$$cookieWriter', function $$CookieWriterProvider() {
this.$get = $$CookieWriter;
});
})(window, window.angular);
/**
* @license AngularJS v1.3.4
* (c) 2010-2014 Google, Inc. http://angularjs.org
* @license AngularJS v1.4.8
* (c) 2010-2015 Google, Inc. http://angularjs.org
* License: MIT
*/
(function (window, angular, undefined) {
'use strict';
(function(window, angular, undefined) {'use strict';
/**
* @ngdoc module
* @name ngRoute
* @description
*
* # ngRoute
*
* The `ngRoute` module provides routing and deeplinking services and directives for angular apps.
*
* ## Example
* See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
*
*
* <div doc-module-components="ngRoute"></div>
*/
/* global -ngRouteModule */
var ngRouteModule = angular.module('ngRoute', ['ng']).
provider('$route', $RouteProvider),
$routeMinErr = angular.$$minErr('ngRoute');
/**
* @ngdoc module
* @name ngRoute
* @description
*
* # ngRoute
*
* The `ngRoute` module provides routing and deeplinking services and directives for angular apps.
*
* ## Example
* See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
*
*
* <div doc-module-components="ngRoute"></div>
*/
/* global -ngRouteModule */
var ngRouteModule = angular.module('ngRoute', ['ng']).
provider('$route', $RouteProvider),
$routeMinErr = angular.$$minErr('ngRoute');
/**
* @ngdoc provider
* @name $routeProvider
*
* @description
*
* Used for configuring routes.
*
* ## Example
* See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
*
* ## Dependencies
* Requires the {@link ngRoute `ngRoute`} module to be installed.
*/
function $RouteProvider() {
function inherit(parent, extra) {
return angular.extend(Object.create(parent), extra);
}
/**
* @ngdoc provider
* @name $routeProvider
*
* @description
*
* Used for configuring routes.
*
* ## Example
* See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
*
* ## Dependencies
* Requires the {@link ngRoute `ngRoute`} module to be installed.
*/
function $RouteProvider() {
function inherit(parent, extra) {
return angular.extend(Object.create(parent), extra);
}
var routes = {};
var routes = {};
/**
* @ngdoc method
* @name $routeProvider#when
*
* @param {string} path Route path (matched against `$location.path`). If `$location.path`
* contains redundant trailing slash or is missing one, the route will still match and the
* `$location.path` will be updated to add or drop the trailing slash to exactly match the
* route definition.
*
* * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up
* to the next slash are matched and stored in `$routeParams` under the given `name`
* when the route matches.
* * `path` can contain named groups starting with a colon and ending with a star:
* e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`
* when the route matches.
* * `path` can contain optional named groups with a question mark: e.g.`:name?`.
*
* For example, routes like `/color/:color/largecode/:largecode*\/edit` will match
* `/color/brown/largecode/code/with/slashes/edit` and extract:
*
* * `color: brown`
* * `largecode: code/with/slashes`.
*
*
* @param {Object} route Mapping information to be assigned to `$route.current` on route
* match.
*
* Object properties:
*
* - `controller` – `{(string|function()=}` – Controller fn that should be associated with
* newly created scope or the name of a {@link angular.Module#controller registered
/**
* @ngdoc method
* @name $routeProvider#when
*
* @param {string} path Route path (matched against `$location.path`). If `$location.path`
* contains redundant trailing slash or is missing one, the route will still match and the
* `$location.path` will be updated to add or drop the trailing slash to exactly match the
* route definition.
*
* * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up
* to the next slash are matched and stored in `$routeParams` under the given `name`
* when the route matches.
* * `path` can contain named groups starting with a colon and ending with a star:
* e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`
* when the route matches.
* * `path` can contain optional named groups with a question mark: e.g.`:name?`.
*
* For example, routes like `/color/:color/largecode/:largecode*\/edit` will match
* `/color/brown/largecode/code/with/slashes/edit` and extract:
*
* * `color: brown`
* * `largecode: code/with/slashes`.
*
*
* @param {Object} route Mapping information to be assigned to `$route.current` on route
* match.
*
* Object properties:
*
* - `controller` – `{(string|function()=}` – Controller fn that should be associated with
* newly created scope or the name of a {@link angular.Module#controller registered
* controller} if passed as a string.
* - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be
* published to scope under the `controllerAs` name.
* - `template` – `{string=|function()=}` – html template as a string or a function that
* returns an html template as a string which should be used by {@link
* ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
* This property takes precedence over `templateUrl`.
*
* If `template` is a function, it will be called with the following parameters:
*
* - `{Array.<Object>}` - route parameters extracted from the current
* `$location.path()` by applying the current route
*
* - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
* template that should be used by {@link ngRoute.directive:ngView ngView}.
*
* If `templateUrl` is a function, it will be called with the following parameters:
*
* - `{Array.<Object>}` - route parameters extracted from the current
* `$location.path()` by applying the current route
*
* - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
* be injected into the controller. If any of these dependencies are promises, the router
* will wait for them all to be resolved or one to be rejected before the controller is
* instantiated.
* If all the promises are resolved successfully, the values of the resolved promises are
* injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is
* fired. If any of the promises are rejected the
* {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object
* is:
*
* - `key` – `{string}`: a name of a dependency to be injected into the controller.
* - `factory` - `{string|function}`: If `string` then it is an alias for a service.
* Otherwise if function, then it is {@link auto.$injector#invoke injected}
* and the return value is treated as the dependency. If the result is a promise, it is
* resolved before its value is injected into the controller. Be aware that
* `ngRoute.$routeParams` will still refer to the previous route within these resolve
* functions. Use `$route.current.params` to access the new route parameters, instead.
*
* - `redirectTo` – {(string|function())=} – value to update
* {@link ng.$location $location} path with and trigger route redirection.
*
* If `redirectTo` is a function, it will be called with the following parameters:
*
* - `{Object.<string>}` - route parameters extracted from the current
* `$location.path()` by applying the current route templateUrl.
* - `{string}` - current `$location.path()`
* - `{Object}` - current `$location.search()`
*
* The custom `redirectTo` function is expected to return a string which will be used
* to update `$location.path()` and `$location.search()`.
*
* - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()`
* or `$location.hash()` changes.
*
* If the option is set to `false` and url in the browser changes, then
* `$routeUpdate` event is broadcasted on the root scope.
*
* - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive
*
* If the option is set to `true`, then the particular route can be matched without being
* case sensitive
*
* @returns {Object} self
*
* @description
* Adds a new route definition to the `$route` service.
*/
this.when = function (path, route) {
//copy original route object to preserve params inherited from proto chain
var routeCopy = angular.copy(route);
if (angular.isUndefined(routeCopy.reloadOnSearch)) {
routeCopy.reloadOnSearch = true;
}
if (angular.isUndefined(routeCopy.caseInsensitiveMatch)) {
routeCopy.caseInsensitiveMatch = this.caseInsensitiveMatch;
}
routes[path] = angular.extend(
routeCopy,
path && pathRegExp(path, routeCopy)
);
* - `controllerAs` – `{string=}` – An identifier name for a reference to the controller.
* If present, the controller will be published to scope under the `controllerAs` name.
* - `template` – `{string=|function()=}` – html template as a string or a function that
* returns an html template as a string which should be used by {@link
* ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
* This property takes precedence over `templateUrl`.
*
* If `template` is a function, it will be called with the following parameters:
*
* - `{Array.<Object>}` - route parameters extracted from the current
* `$location.path()` by applying the current route
*
* - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
* template that should be used by {@link ngRoute.directive:ngView ngView}.
*
* If `templateUrl` is a function, it will be called with the following parameters:
*
* - `{Array.<Object>}` - route parameters extracted from the current
* `$location.path()` by applying the current route
*
* - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
* be injected into the controller. If any of these dependencies are promises, the router
* will wait for them all to be resolved or one to be rejected before the controller is
* instantiated.
* If all the promises are resolved successfully, the values of the resolved promises are
* injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is
* fired. If any of the promises are rejected the
* {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object
* is:
*
* - `key` – `{string}`: a name of a dependency to be injected into the controller.
* - `factory` - `{string|function}`: If `string` then it is an alias for a service.
* Otherwise if function, then it is {@link auto.$injector#invoke injected}
* and the return value is treated as the dependency. If the result is a promise, it is
* resolved before its value is injected into the controller. Be aware that
* `ngRoute.$routeParams` will still refer to the previous route within these resolve
* functions. Use `$route.current.params` to access the new route parameters, instead.
*
* - `redirectTo` – {(string|function())=} – value to update
* {@link ng.$location $location} path with and trigger route redirection.
*
* If `redirectTo` is a function, it will be called with the following parameters:
*
* - `{Object.<string>}` - route parameters extracted from the current
* `$location.path()` by applying the current route templateUrl.
* - `{string}` - current `$location.path()`
* - `{Object}` - current `$location.search()`
*
* The custom `redirectTo` function is expected to return a string which will be used
* to update `$location.path()` and `$location.search()`.
*
* - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()`
* or `$location.hash()` changes.
*
* If the option is set to `false` and url in the browser changes, then
* `$routeUpdate` event is broadcasted on the root scope.
*
* - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive
*
* If the option is set to `true`, then the particular route can be matched without being
* case sensitive
*
* @returns {Object} self
*
* @description
* Adds a new route definition to the `$route` service.
*/
this.when = function(path, route) {
//copy original route object to preserve params inherited from proto chain
var routeCopy = angular.copy(route);
if (angular.isUndefined(routeCopy.reloadOnSearch)) {
routeCopy.reloadOnSearch = true;
}
if (angular.isUndefined(routeCopy.caseInsensitiveMatch)) {
routeCopy.caseInsensitiveMatch = this.caseInsensitiveMatch;
}
routes[path] = angular.extend(
routeCopy,
path && pathRegExp(path, routeCopy)
);
// create redirection for trailing slashes
if (path) {
var redirectPath = (path[path.length - 1] == '/')
? path.substr(0, path.length - 1)
: path + '/';
// create redirection for trailing slashes
if (path) {
var redirectPath = (path[path.length - 1] == '/')
? path.substr(0, path.length - 1)
: path + '/';
routes[redirectPath] = angular.extend(
{redirectTo: path},
pathRegExp(redirectPath, routeCopy)
);
}
routes[redirectPath] = angular.extend(
{redirectTo: path},
pathRegExp(redirectPath, routeCopy)
);
}
return this;
};
return this;
};
/**
* @ngdoc property
* @name $routeProvider#caseInsensitiveMatch
* @description
*
* A boolean property indicating if routes defined
* using this provider should be matched using a case sensitive
* algorithm. Defaults to `false`.
*/
this.caseInsensitiveMatch = false;
/**
* @ngdoc property
* @name $routeProvider#caseInsensitiveMatch
* @description
*
* A boolean property indicating if routes defined
* using this provider should be matched using a case insensitive
* algorithm. Defaults to `false`.
*/
this.caseInsensitiveMatch = false;
/**
* @param path {string} path
* @param opts {Object} options
* @return {?Object}
*
* @description
* Normalizes the given path, returning a regular expression
* and the original path.
*
* Inspired by pathRexp in visionmedia/express/lib/utils.js.
*/
function pathRegExp(path, opts) {
var insensitive = opts.caseInsensitiveMatch,
ret = {
originalPath: path,
regexp: path
},
keys = ret.keys = [];
/**
* @param path {string} path
* @param opts {Object} options
* @return {?Object}
*
* @description
* Normalizes the given path, returning a regular expression
* and the original path.
*
* Inspired by pathRexp in visionmedia/express/lib/utils.js.
*/
function pathRegExp(path, opts) {
var insensitive = opts.caseInsensitiveMatch,
ret = {
originalPath: path,
regexp: path
},
keys = ret.keys = [];
path = path
.replace(/([().])/g, '\\$1')
.replace(/(\/)?:(\w+)([\?\*])?/g, function (_, slash, key, option) {
var optional = option === '?' ? option : null;
var star = option === '*' ? option : null;
keys.push({name: key, optional: !!optional});
slash = slash || '';
return ''
+ (optional ? '' : slash)
+ '(?:'
+ (optional ? slash : '')
+ (star && '(.+?)' || '([^/]+)')
+ (optional || '')
+ ')'
+ (optional || '');
})
.replace(/([\/$\*])/g, '\\$1');
path = path
.replace(/([().])/g, '\\$1')
.replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option) {
var optional = option === '?' ? option : null;
var star = option === '*' ? option : null;
keys.push({ name: key, optional: !!optional });
slash = slash || '';
return ''
+ (optional ? '' : slash)
+ '(?:'
+ (optional ? slash : '')
+ (star && '(.+?)' || '([^/]+)')
+ (optional || '')
+ ')'
+ (optional || '');
})
.replace(/([\/$\*])/g, '\\$1');
ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : '');
return ret;
}
ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : '');
return ret;
}
/**
* @ngdoc method
* @name $routeProvider#otherwise
*
* @description
* Sets route definition that will be used on route change when no other route definition
* is matched.
*
* @param {Object|string} params Mapping information to be assigned to `$route.current`.
* If called with a string, the value maps to `redirectTo`.
* @returns {Object} self
*/
this.otherwise = function (params) {
if (typeof params === 'string') {
params = {redirectTo: params};
}
this.when(null, params);
return this;
};
/**
* @ngdoc method
* @name $routeProvider#otherwise
*
* @description
* Sets route definition that will be used on route change when no other route definition
* is matched.
*
* @param {Object|string} params Mapping information to be assigned to `$route.current`.
* If called with a string, the value maps to `redirectTo`.
* @returns {Object} self
*/
this.otherwise = function(params) {
if (typeof params === 'string') {
params = {redirectTo: params};
}
this.when(null, params);
return this;
};
this.$get = ['$rootScope',
'$location',
'$routeParams',
'$q',
'$injector',
'$templateRequest',
'$sce',
function ($rootScope, $location, $routeParams, $q, $injector, $templateRequest, $sce) {
this.$get = ['$rootScope',
'$location',
'$routeParams',
'$q',
'$injector',
'$templateRequest',
'$sce',
function($rootScope, $location, $routeParams, $q, $injector, $templateRequest, $sce) {
/**
* @ngdoc service
* @name $route
* @requires $location
* @requires $routeParams
*
* @property {Object} current Reference to the current route definition.
* The route definition contains:
*
* - `controller`: The controller constructor as define in route definition.
* - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for
* controller instantiation. The `locals` contain
* the resolved values of the `resolve` map. Additionally the `locals` also contain:
*
* - `$scope` - The current route scope.
* - `$template` - The current route template HTML.
*
* @property {Object} routes Object with all route configuration Objects as its properties.
*
* @description
* `$route` is used for deep-linking URLs to controllers and views (HTML partials).
* It watches `$location.url()` and tries to map the path to an existing route definition.
*
* Requires the {@link ngRoute `ngRoute`} module to be installed.
*
* You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API.
*
* The `$route` service is typically used in conjunction with the
* {@link ngRoute.directive:ngView `ngView`} directive and the
* {@link ngRoute.$routeParams `$routeParams`} service.
*
* @example
* This example shows how changing the URL hash causes the `$route` to match a route against the
* URL, and the `ngView` pulls in the partial.
*
* <example name="$route-service" module="ngRouteExample"
* deps="angular-route.js" fixBase="true">
* <file name="index.html">
* <div ng-controller="MainController">
* Choose:
* <a href="Book/Moby">Moby</a> |
* <a href="Book/Moby/ch/1">Moby: Ch1</a> |
* <a href="Book/Gatsby">Gatsby</a> |
* <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
* <a href="Book/Scarlet">Scarlet Letter</a><br/>
*
* <div ng-view></div>
*
* <hr />
*
* <pre>$location.path() = {{$location.path()}}</pre>
* <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
* <pre>$route.current.params = {{$route.current.params}}</pre>
* <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
* <pre>$routeParams = {{$routeParams}}</pre>
* </div>
* </file>
*
* <file name="book.html">
* controller: {{name}}<br />
* Book Id: {{params.bookId}}<br />
* </file>
*
* <file name="chapter.html">
* controller: {{name}}<br />
* Book Id: {{params.bookId}}<br />
* Chapter Id: {{params.chapterId}}
* </file>
*
* <file name="script.js">
* angular.module('ngRouteExample', ['ngRoute'])
*
* .controller('MainController', function($scope, $route, $routeParams, $location) {
/**
* @ngdoc service
* @name $route
* @requires $location
* @requires $routeParams
*
* @property {Object} current Reference to the current route definition.
* The route definition contains:
*
* - `controller`: The controller constructor as define in route definition.
* - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for
* controller instantiation. The `locals` contain
* the resolved values of the `resolve` map. Additionally the `locals` also contain:
*
* - `$scope` - The current route scope.
* - `$template` - The current route template HTML.
*
* @property {Object} routes Object with all route configuration Objects as its properties.
*
* @description
* `$route` is used for deep-linking URLs to controllers and views (HTML partials).
* It watches `$location.url()` and tries to map the path to an existing route definition.
*
* Requires the {@link ngRoute `ngRoute`} module to be installed.
*
* You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API.
*
* The `$route` service is typically used in conjunction with the
* {@link ngRoute.directive:ngView `ngView`} directive and the
* {@link ngRoute.$routeParams `$routeParams`} service.
*
* @example
* This example shows how changing the URL hash causes the `$route` to match a route against the
* URL, and the `ngView` pulls in the partial.
*
* <example name="$route-service" module="ngRouteExample"
* deps="angular-route.js" fixBase="true">
* <file name="index.html">
* <div ng-controller="MainController">
* Choose:
* <a href="Book/Moby">Moby</a> |
* <a href="Book/Moby/ch/1">Moby: Ch1</a> |
* <a href="Book/Gatsby">Gatsby</a> |
* <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
* <a href="Book/Scarlet">Scarlet Letter</a><br/>
*
* <div ng-view></div>
*
* <hr />
*
* <pre>$location.path() = {{$location.path()}}</pre>
* <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
* <pre>$route.current.params = {{$route.current.params}}</pre>
* <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
* <pre>$routeParams = {{$routeParams}}</pre>
* </div>
* </file>
*
* <file name="book.html">
* controller: {{name}}<br />
* Book Id: {{params.bookId}}<br />
* </file>
*
* <file name="chapter.html">
* controller: {{name}}<br />
* Book Id: {{params.bookId}}<br />
* Chapter Id: {{params.chapterId}}
* </file>
*
* <file name="script.js">
* angular.module('ngRouteExample', ['ngRoute'])
*
* .controller('MainController', function($scope, $route, $routeParams, $location) {
* $scope.$route = $route;

@@ -337,14 +336,14 @@ * $scope.$location = $location;

* })
*
* .controller('BookController', function($scope, $routeParams) {
*
* .controller('BookController', function($scope, $routeParams) {
* $scope.name = "BookController";
* $scope.params = $routeParams;
* })
*
* .controller('ChapterController', function($scope, $routeParams) {
*
* .controller('ChapterController', function($scope, $routeParams) {
* $scope.name = "ChapterController";
* $scope.params = $routeParams;
* })
*
* .config(function($routeProvider, $locationProvider) {
*
* .config(function($routeProvider, $locationProvider) {
* $routeProvider

@@ -371,7 +370,7 @@ * .when('/Book/:bookId', {

* });
*
* </file>
*
* <file name="protractor.js" type="protractor">
* it('should load and compile correct template', function() {
*
* </file>
*
* <file name="protractor.js" type="protractor">
* it('should load and compile correct template', function() {
* element(by.linkText('Moby: Ch1')).click();

@@ -389,411 +388,404 @@ * var content = element(by.css('[ng-view]')).getText();

* });
* </file>
* </example>
*/
* </file>
* </example>
*/
/**
* @ngdoc event
* @name $route#$routeChangeStart
* @eventType broadcast on root scope
* @description
* Broadcasted before a route change. At this point the route services starts
* resolving all of the dependencies needed for the route change to occur.
* Typically this involves fetching the view template as well as any dependencies
* defined in `resolve` route property. Once all of the dependencies are resolved
* `$routeChangeSuccess` is fired.
*
* The route change (and the `$location` change that triggered it) can be prevented
* by calling `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on}
* for more details about event object.
*
* @param {Object} angularEvent Synthetic event object.
* @param {Route} next Future route information.
* @param {Route} current Current route information.
*/
/**
* @ngdoc event
* @name $route#$routeChangeStart
* @eventType broadcast on root scope
* @description
* Broadcasted before a route change. At this point the route services starts
* resolving all of the dependencies needed for the route change to occur.
* Typically this involves fetching the view template as well as any dependencies
* defined in `resolve` route property. Once all of the dependencies are resolved
* `$routeChangeSuccess` is fired.
*
* The route change (and the `$location` change that triggered it) can be prevented
* by calling `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on}
* for more details about event object.
*
* @param {Object} angularEvent Synthetic event object.
* @param {Route} next Future route information.
* @param {Route} current Current route information.
*/
/**
* @ngdoc event
* @name $route#$routeChangeSuccess
* @eventType broadcast on root scope
* @description
* Broadcasted after a route dependencies are resolved.
* {@link ngRoute.directive:ngView ngView} listens for the directive
* to instantiate the controller and render the view.
*
* @param {Object} angularEvent Synthetic event object.
* @param {Route} current Current route information.
* @param {Route|Undefined} previous Previous route information, or undefined if current is
* first route entered.
*/
/**
* @ngdoc event
* @name $route#$routeChangeSuccess
* @eventType broadcast on root scope
* @description
* Broadcasted after a route change has happened successfully.
* The `resolve` dependencies are now available in the `current.locals` property.
*
* {@link ngRoute.directive:ngView ngView} listens for the directive
* to instantiate the controller and render the view.
*
* @param {Object} angularEvent Synthetic event object.
* @param {Route} current Current route information.
* @param {Route|Undefined} previous Previous route information, or undefined if current is
* first route entered.
*/
/**
* @ngdoc event
* @name $route#$routeChangeError
* @eventType broadcast on root scope
* @description
* Broadcasted if any of the resolve promises are rejected.
*
* @param {Object} angularEvent Synthetic event object
* @param {Route} current Current route information.
* @param {Route} previous Previous route information.
* @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.
*/
/**
* @ngdoc event
* @name $route#$routeChangeError
* @eventType broadcast on root scope
* @description
* Broadcasted if any of the resolve promises are rejected.
*
* @param {Object} angularEvent Synthetic event object
* @param {Route} current Current route information.
* @param {Route} previous Previous route information.
* @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.
*/
/**
* @ngdoc event
* @name $route#$routeUpdate
* @eventType broadcast on root scope
* @description
*
* The `reloadOnSearch` property has been set to false, and we are reusing the same
* instance of the Controller.
*/
/**
* @ngdoc event
* @name $route#$routeUpdate
* @eventType broadcast on root scope
* @description
* The `reloadOnSearch` property has been set to false, and we are reusing the same
* instance of the Controller.
*
* @param {Object} angularEvent Synthetic event object
* @param {Route} current Current/previous route information.
*/
var forceReload = false,
preparedRoute,
preparedRouteIsUpdateOnly,
$route = {
routes: routes,
var forceReload = false,
preparedRoute,
preparedRouteIsUpdateOnly,
$route = {
routes: routes,
/**
* @ngdoc method
* @name $route#reload
*
* @description
* Causes `$route` service to reload the current route even if
* {@link ng.$location $location} hasn't changed.
*
* As a result of that, {@link ngRoute.directive:ngView ngView}
* creates new scope and reinstantiates the controller.
*/
reload: function () {
forceReload = true;
$rootScope.$evalAsync(function () {
// Don't support cancellation of a reload for now...
prepareRoute();
commitRoute();
});
},
/**
* @ngdoc method
* @name $route#reload
*
* @description
* Causes `$route` service to reload the current route even if
* {@link ng.$location $location} hasn't changed.
*
* As a result of that, {@link ngRoute.directive:ngView ngView}
* creates new scope and reinstantiates the controller.
*/
reload: function() {
forceReload = true;
$rootScope.$evalAsync(function() {
// Don't support cancellation of a reload for now...
prepareRoute();
commitRoute();
});
},
/**
* @ngdoc method
* @name $route#updateParams
*
* @description
* Causes `$route` service to update the current URL, replacing
* current route parameters with those specified in `newParams`.
* Provided property names that match the route's path segment
* definitions will be interpolated into the location's path, while
* remaining properties will be treated as query params.
*
* @param {Object} newParams mapping of URL parameter names to values
*/
updateParams: function (newParams) {
if (this.current && this.current.$$route) {
var searchParams = {}, self = this;
/**
* @ngdoc method
* @name $route#updateParams
*
* @description
* Causes `$route` service to update the current URL, replacing
* current route parameters with those specified in `newParams`.
* Provided property names that match the route's path segment
* definitions will be interpolated into the location's path, while
* remaining properties will be treated as query params.
*
* @param {!Object<string, string>} newParams mapping of URL parameter names to values
*/
updateParams: function(newParams) {
if (this.current && this.current.$$route) {
newParams = angular.extend({}, this.current.params, newParams);
$location.path(interpolate(this.current.$$route.originalPath, newParams));
// interpolate modifies newParams, only query params are left
$location.search(newParams);
} else {
throw $routeMinErr('norout', 'Tried updating route when with no current route');
}
}
};
angular.forEach(Object.keys(newParams), function (key) {
if (!self.current.pathParams[key]) searchParams[key] = newParams[key];
});
$rootScope.$on('$locationChangeStart', prepareRoute);
$rootScope.$on('$locationChangeSuccess', commitRoute);
newParams = angular.extend({}, this.current.params, newParams);
$location.path(interpolate(this.current.$$route.originalPath, newParams));
$location.search(angular.extend({}, $location.search(), searchParams));
}
else {
throw $routeMinErr('norout', 'Tried updating route when with no current route');
}
}
};
return $route;
$rootScope.$on('$locationChangeStart', prepareRoute);
$rootScope.$on('$locationChangeSuccess', commitRoute);
/////////////////////////////////////////////////////
return $route;
/**
* @param on {string} current url
* @param route {Object} route regexp to match the url against
* @return {?Object}
*
* @description
* Check if the route matches the current url.
*
* Inspired by match in
* visionmedia/express/lib/router/router.js.
*/
function switchRouteMatcher(on, route) {
var keys = route.keys,
params = {};
/////////////////////////////////////////////////////
if (!route.regexp) return null;
/**
* @param on {string} current url
* @param route {Object} route regexp to match the url against
* @return {?Object}
*
* @description
* Check if the route matches the current url.
*
* Inspired by match in
* visionmedia/express/lib/router/router.js.
*/
function switchRouteMatcher(on, route) {
var keys = route.keys,
params = {};
var m = route.regexp.exec(on);
if (!m) return null;
if (!route.regexp) return null;
for (var i = 1, len = m.length; i < len; ++i) {
var key = keys[i - 1];
var m = route.regexp.exec(on);
if (!m) return null;
var val = m[i];
for (var i = 1, len = m.length; i < len; ++i) {
var key = keys[i - 1];
if (key && val) {
params[key.name] = val;
}
}
return params;
}
var val = m[i];
function prepareRoute($locationEvent) {
var lastRoute = $route.current;
if (key && val) {
params[key.name] = val;
}
}
return params;
}
preparedRoute = parseRoute();
preparedRouteIsUpdateOnly = preparedRoute && lastRoute && preparedRoute.$$route === lastRoute.$$route
&& angular.equals(preparedRoute.pathParams, lastRoute.pathParams)
&& !preparedRoute.reloadOnSearch && !forceReload;
function prepareRoute($locationEvent) {
var lastRoute = $route.current;
if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) {
if ($rootScope.$broadcast('$routeChangeStart', preparedRoute, lastRoute).defaultPrevented) {
if ($locationEvent) {
$locationEvent.preventDefault();
}
}
}
}
preparedRoute = parseRoute();
preparedRouteIsUpdateOnly = preparedRoute && lastRoute && preparedRoute.$$route === lastRoute.$$route
&& angular.equals(preparedRoute.pathParams, lastRoute.pathParams)
&& !preparedRoute.reloadOnSearch && !forceReload;
function commitRoute() {
var lastRoute = $route.current;
var nextRoute = preparedRoute;
if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) {
if ($rootScope.$broadcast('$routeChangeStart', preparedRoute, lastRoute).defaultPrevented) {
if ($locationEvent) {
$locationEvent.preventDefault();
}
}
}
}
if (preparedRouteIsUpdateOnly) {
lastRoute.params = nextRoute.params;
angular.copy(lastRoute.params, $routeParams);
$rootScope.$broadcast('$routeUpdate', lastRoute);
} else if (nextRoute || lastRoute) {
forceReload = false;
$route.current = nextRoute;
if (nextRoute) {
if (nextRoute.redirectTo) {
if (angular.isString(nextRoute.redirectTo)) {
$location.path(interpolate(nextRoute.redirectTo, nextRoute.params)).search(nextRoute.params)
.replace();
} else {
$location.url(nextRoute.redirectTo(nextRoute.pathParams, $location.path(), $location.search()))
.replace();
}
}
}
function commitRoute() {
var lastRoute = $route.current;
var nextRoute = preparedRoute;
$q.when(nextRoute).
then(function() {
if (nextRoute) {
var locals = angular.extend({}, nextRoute.resolve),
template, templateUrl;
if (preparedRouteIsUpdateOnly) {
lastRoute.params = nextRoute.params;
angular.copy(lastRoute.params, $routeParams);
$rootScope.$broadcast('$routeUpdate', lastRoute);
} else if (nextRoute || lastRoute) {
forceReload = false;
$route.current = nextRoute;
if (nextRoute) {
if (nextRoute.redirectTo) {
if (angular.isString(nextRoute.redirectTo)) {
$location.path(interpolate(nextRoute.redirectTo, nextRoute.params)).search(nextRoute.params)
.replace();
} else {
$location.url(nextRoute.redirectTo(nextRoute.pathParams, $location.path(), $location.search()))
.replace();
}
}
}
angular.forEach(locals, function(value, key) {
locals[key] = angular.isString(value) ?
$injector.get(value) : $injector.invoke(value, null, null, key);
});
$q.when(nextRoute).
then(function () {
if (nextRoute) {
var locals = angular.extend({}, nextRoute.resolve),
template, templateUrl;
angular.forEach(locals, function (value, key) {
locals[key] = angular.isString(value) ?
$injector.get(value) : $injector.invoke(value, null, null, key);
});
if (angular.isDefined(template = nextRoute.template)) {
if (angular.isFunction(template)) {
template = template(nextRoute.params);
}
} else if (angular.isDefined(templateUrl = nextRoute.templateUrl)) {
if (angular.isFunction(templateUrl)) {
templateUrl = templateUrl(nextRoute.params);
}
templateUrl = $sce.getTrustedResourceUrl(templateUrl);
if (angular.isDefined(templateUrl)) {
nextRoute.loadedTemplateUrl = templateUrl;
template = $templateRequest(templateUrl);
}
}
if (angular.isDefined(template)) {
locals['$template'] = template;
}
return $q.all(locals);
}
}).
// after route change
then(function (locals) {
if (nextRoute == $route.current) {
if (nextRoute) {
nextRoute.locals = locals;
angular.copy(nextRoute.params, $routeParams);
}
$rootScope.$broadcast('$routeChangeSuccess', nextRoute, lastRoute);
}
}, function (error) {
if (nextRoute == $route.current) {
$rootScope.$broadcast('$routeChangeError', nextRoute, lastRoute, error);
}
});
}
if (angular.isDefined(template = nextRoute.template)) {
if (angular.isFunction(template)) {
template = template(nextRoute.params);
}
/**
* @returns {Object} the current active route, by matching it against the URL
*/
function parseRoute() {
// Match a route
var params, match;
angular.forEach(routes, function (route, path) {
if (!match && (params = switchRouteMatcher($location.path(), route))) {
match = inherit(route, {
params: angular.extend({}, $location.search(), params),
pathParams: params
});
match.$$route = route;
}
});
// No route matched; fallback to "otherwise" route
return match || routes[null] && inherit(routes[null], {params: {}, pathParams: {}});
} else if (angular.isDefined(templateUrl = nextRoute.templateUrl)) {
if (angular.isFunction(templateUrl)) {
templateUrl = templateUrl(nextRoute.params);
}
/**
* @returns {string} interpolation of the redirect path with the parameters
*/
function interpolate(string, params) {
var result = [];
angular.forEach((string || '').split(':'), function (segment, i) {
if (i === 0) {
result.push(segment);
} else {
var segmentMatch = segment.match(/(\w+)(?:[?*])?(.*)/);
var key = segmentMatch[1];
result.push(params[key]);
result.push(segmentMatch[2] || '');
delete params[key];
}
});
return result.join('');
if (angular.isDefined(templateUrl)) {
nextRoute.loadedTemplateUrl = $sce.valueOf(templateUrl);
template = $templateRequest(templateUrl);
}
}];
}
if (angular.isDefined(template)) {
locals['$template'] = template;
}
return $q.all(locals);
}
}).
then(function(locals) {
// after route change
if (nextRoute == $route.current) {
if (nextRoute) {
nextRoute.locals = locals;
angular.copy(nextRoute.params, $routeParams);
}
$rootScope.$broadcast('$routeChangeSuccess', nextRoute, lastRoute);
}
}, function(error) {
if (nextRoute == $route.current) {
$rootScope.$broadcast('$routeChangeError', nextRoute, lastRoute, error);
}
});
}
}
ngRouteModule.provider('$routeParams', $RouteParamsProvider);
/**
* @returns {Object} the current active route, by matching it against the URL
*/
function parseRoute() {
// Match a route
var params, match;
angular.forEach(routes, function(route, path) {
if (!match && (params = switchRouteMatcher($location.path(), route))) {
match = inherit(route, {
params: angular.extend({}, $location.search(), params),
pathParams: params});
match.$$route = route;
}
});
// No route matched; fallback to "otherwise" route
return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});
}
/**
* @ngdoc service
* @name $routeParams
* @requires $route
*
* @description
* The `$routeParams` service allows you to retrieve the current set of route parameters.
*
* Requires the {@link ngRoute `ngRoute`} module to be installed.
*
* The route parameters are a combination of {@link ng.$location `$location`}'s
* {@link ng.$location#search `search()`} and {@link ng.$location#path `path()`}.
* The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched.
*
* In case of parameter name collision, `path` params take precedence over `search` params.
*
* The service guarantees that the identity of the `$routeParams` object will remain unchanged
* (but its properties will likely change) even when a route change occurs.
*
* Note that the `$routeParams` are only updated *after* a route change completes successfully.
* This means that you cannot rely on `$routeParams` being correct in route resolve functions.
* Instead you can use `$route.current.params` to access the new route's parameters.
*
* @example
* ```js
* // Given:
* // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
* // Route: /Chapter/:chapterId/Section/:sectionId
* //
* // Then
* $routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'}
* ```
* @returns {string} interpolation of the redirect path with the parameters
*/
function $RouteParamsProvider() {
this.$get = function () {
return {};
};
function interpolate(string, params) {
var result = [];
angular.forEach((string || '').split(':'), function(segment, i) {
if (i === 0) {
result.push(segment);
} else {
var segmentMatch = segment.match(/(\w+)(?:[?*])?(.*)/);
var key = segmentMatch[1];
result.push(params[key]);
result.push(segmentMatch[2] || '');
delete params[key];
}
});
return result.join('');
}
}];
}
ngRouteModule.directive('ngView', ngViewFactory);
ngRouteModule.directive('ngView', ngViewFillContentFactory);
ngRouteModule.provider('$routeParams', $RouteParamsProvider);
/**
* @ngdoc directive
* @name ngView
* @restrict ECA
*
* @description
* # Overview
* `ngView` is a directive that complements the {@link ngRoute.$route $route} service by
* including the rendered template of the current route into the main layout (`index.html`) file.
* Every time the current route changes, the included view changes with it according to the
* configuration of the `$route` service.
*
* Requires the {@link ngRoute `ngRoute`} module to be installed.
*
* @animations
* enter - animation is used to bring new content into the browser.
* leave - animation is used to animate existing content away.
*
* The enter and leave animation occur concurrently.
*
* @scope
* @priority 400
* @param {string=} onload Expression to evaluate whenever the view updates.
*
* @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll
/**
* @ngdoc service
* @name $routeParams
* @requires $route
*
* @description
* The `$routeParams` service allows you to retrieve the current set of route parameters.
*
* Requires the {@link ngRoute `ngRoute`} module to be installed.
*
* The route parameters are a combination of {@link ng.$location `$location`}'s
* {@link ng.$location#search `search()`} and {@link ng.$location#path `path()`}.
* The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched.
*
* In case of parameter name collision, `path` params take precedence over `search` params.
*
* The service guarantees that the identity of the `$routeParams` object will remain unchanged
* (but its properties will likely change) even when a route change occurs.
*
* Note that the `$routeParams` are only updated *after* a route change completes successfully.
* This means that you cannot rely on `$routeParams` being correct in route resolve functions.
* Instead you can use `$route.current.params` to access the new route's parameters.
*
* @example
* ```js
* // Given:
* // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
* // Route: /Chapter/:chapterId/Section/:sectionId
* //
* // Then
* $routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'}
* ```
*/
function $RouteParamsProvider() {
this.$get = function() { return {}; };
}
ngRouteModule.directive('ngView', ngViewFactory);
ngRouteModule.directive('ngView', ngViewFillContentFactory);
/**
* @ngdoc directive
* @name ngView
* @restrict ECA
*
* @description
* # Overview
* `ngView` is a directive that complements the {@link ngRoute.$route $route} service by
* including the rendered template of the current route into the main layout (`index.html`) file.
* Every time the current route changes, the included view changes with it according to the
* configuration of the `$route` service.
*
* Requires the {@link ngRoute `ngRoute`} module to be installed.
*
* @animations
* enter - animation is used to bring new content into the browser.
* leave - animation is used to animate existing content away.
*
* The enter and leave animation occur concurrently.
*
* @scope
* @priority 400
* @param {string=} onload Expression to evaluate whenever the view updates.
*
* @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll
* $anchorScroll} to scroll the viewport after the view is updated.
*
* - If the attribute is not set, disable scrolling.
* - If the attribute is set without value, enable scrolling.
* - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated
* as an expression yields a truthy value.
* @example
<example name="ngView-directive" module="ngViewExample"
deps="angular-route.js;angular-animate.js"
animations="true" fixBase="true">
<file name="index.html">
<div ng-controller="MainCtrl as main">
Choose:
<a href="Book/Moby">Moby</a> |
<a href="Book/Moby/ch/1">Moby: Ch1</a> |
<a href="Book/Gatsby">Gatsby</a> |
<a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
<a href="Book/Scarlet">Scarlet Letter</a><br/>
*
* - If the attribute is not set, disable scrolling.
* - If the attribute is set without value, enable scrolling.
* - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated
* as an expression yields a truthy value.
* @example
<example name="ngView-directive" module="ngViewExample"
deps="angular-route.js;angular-animate.js"
animations="true" fixBase="true">
<file name="index.html">
<div ng-controller="MainCtrl as main">
Choose:
<a href="Book/Moby">Moby</a> |
<a href="Book/Moby/ch/1">Moby: Ch1</a> |
<a href="Book/Gatsby">Gatsby</a> |
<a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
<a href="Book/Scarlet">Scarlet Letter</a><br/>
<div class="view-animate-container">
<div ng-view class="view-animate"></div>
</div>
<hr />
<div class="view-animate-container">
<div ng-view class="view-animate"></div>
</div>
<hr />
<pre>$location.path() = {{main.$location.path()}}</pre>
<pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre>
<pre>$route.current.params = {{main.$route.current.params}}</pre>
<pre>$routeParams = {{main.$routeParams}}</pre>
</div>
</file>
<pre>$location.path() = {{main.$location.path()}}</pre>
<pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre>
<pre>$route.current.params = {{main.$route.current.params}}</pre>
<pre>$routeParams = {{main.$routeParams}}</pre>
</div>
</file>
<file name="book.html">
<div>
controller: {{book.name}}<br />
Book Id: {{book.params.bookId}}<br />
</div>
</file>
<file name="book.html">
<div>
controller: {{book.name}}<br />
Book Id: {{book.params.bookId}}<br />
</div>
</file>
<file name="chapter.html">
<div>
controller: {{chapter.name}}<br />
Book Id: {{chapter.params.bookId}}<br />
Chapter Id: {{chapter.params.chapterId}}
</div>
</file>
<file name="chapter.html">
<div>
controller: {{chapter.name}}<br />
Book Id: {{chapter.params.bookId}}<br />
Chapter Id: {{chapter.params.chapterId}}
</div>
</file>
<file name="animations.css">
.view-animate-container {
<file name="animations.css">
.view-animate-container {
position:relative;
height:100px!important;
position:relative;
background:white;

@@ -805,8 +797,7 @@ border:1px solid black;

.view-animate {
.view-animate {
padding:10px;
}
.view-animate.ng-enter, .view-animate.ng-leave {
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
.view-animate.ng-enter, .view-animate.ng-leave {
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;

@@ -826,17 +817,17 @@

.view-animate.ng-enter {
.view-animate.ng-enter {
left:100%;
}
.view-animate.ng-enter.ng-enter-active {
.view-animate.ng-enter.ng-enter-active {
left:0;
}
.view-animate.ng-leave.ng-leave-active {
.view-animate.ng-leave.ng-leave-active {
left:-100%;
}
</file>
</file>
<file name="script.js">
angular.module('ngViewExample', ['ngRoute', 'ngAnimate'])
.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
<file name="script.js">
angular.module('ngViewExample', ['ngRoute', 'ngAnimate'])
.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider

@@ -856,4 +847,4 @@ .when('/Book/:bookId', {

}])
.controller('MainCtrl', ['$route', '$routeParams', '$location',
function($route, $routeParams, $location) {
.controller('MainCtrl', ['$route', '$routeParams', '$location',
function($route, $routeParams, $location) {
this.$route = $route;

@@ -863,7 +854,7 @@ this.$location = $location;

}])
.controller('BookCtrl', ['$routeParams', function($routeParams) {
.controller('BookCtrl', ['$routeParams', function($routeParams) {
this.name = "BookCtrl";
this.params = $routeParams;
}])
.controller('ChapterCtrl', ['$routeParams', function($routeParams) {
.controller('ChapterCtrl', ['$routeParams', function($routeParams) {
this.name = "ChapterCtrl";

@@ -873,6 +864,6 @@ this.params = $routeParams;

</file>
</file>
<file name="protractor.js" type="protractor">
it('should load and compile correct template', function() {
<file name="protractor.js" type="protractor">
it('should load and compile correct template', function() {
element(by.linkText('Moby: Ch1')).click();

@@ -890,85 +881,85 @@ var content = element(by.css('[ng-view]')).getText();

});
</file>
</example>
*/
</file>
</example>
*/
/**
* @ngdoc event
* @name ngView#$viewContentLoaded
* @eventType emit on the current ngView scope
* @description
* Emitted every time the ngView content is reloaded.
*/
ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
function ngViewFactory($route, $anchorScroll, $animate) {
return {
restrict: 'ECA',
terminal: true,
priority: 400,
transclude: 'element',
link: function (scope, $element, attr, ctrl, $transclude) {
var currentScope,
currentElement,
previousLeaveAnimation,
autoScrollExp = attr.autoscroll,
onloadExp = attr.onload || '';
/**
* @ngdoc event
* @name ngView#$viewContentLoaded
* @eventType emit on the current ngView scope
* @description
* Emitted every time the ngView content is reloaded.
*/
ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
function ngViewFactory($route, $anchorScroll, $animate) {
return {
restrict: 'ECA',
terminal: true,
priority: 400,
transclude: 'element',
link: function(scope, $element, attr, ctrl, $transclude) {
var currentScope,
currentElement,
previousLeaveAnimation,
autoScrollExp = attr.autoscroll,
onloadExp = attr.onload || '';
scope.$on('$routeChangeSuccess', update);
update();
scope.$on('$routeChangeSuccess', update);
update();
function cleanupLastView() {
if (previousLeaveAnimation) {
$animate.cancel(previousLeaveAnimation);
previousLeaveAnimation = null;
}
function cleanupLastView() {
if (previousLeaveAnimation) {
$animate.cancel(previousLeaveAnimation);
previousLeaveAnimation = null;
}
if (currentScope) {
currentScope.$destroy();
currentScope = null;
}
if (currentElement) {
previousLeaveAnimation = $animate.leave(currentElement);
previousLeaveAnimation.then(function () {
previousLeaveAnimation = null;
});
currentElement = null;
}
}
if (currentScope) {
currentScope.$destroy();
currentScope = null;
}
if (currentElement) {
previousLeaveAnimation = $animate.leave(currentElement);
previousLeaveAnimation.then(function() {
previousLeaveAnimation = null;
});
currentElement = null;
}
}
function update() {
var locals = $route.current && $route.current.locals,
template = locals && locals.$template;
function update() {
var locals = $route.current && $route.current.locals,
template = locals && locals.$template;
if (angular.isDefined(template)) {
var newScope = scope.$new();
var current = $route.current;
if (angular.isDefined(template)) {
var newScope = scope.$new();
var current = $route.current;
// Note: This will also link all children of ng-view that were contained in the original
// html. If that content contains controllers, ... they could pollute/change the scope.
// However, using ng-view on an element with additional content does not make sense...
// Note: We can't remove them in the cloneAttchFn of $transclude as that
// function is called before linking the content, which would apply child
// directives to non existing elements.
var clone = $transclude(newScope, function (clone) {
$animate.enter(clone, null, currentElement || $element).then(function onNgViewEnter() {
if (angular.isDefined(autoScrollExp)
&& (!autoScrollExp || scope.$eval(autoScrollExp))) {
$anchorScroll();
}
});
cleanupLastView();
});
// Note: This will also link all children of ng-view that were contained in the original
// html. If that content contains controllers, ... they could pollute/change the scope.
// However, using ng-view on an element with additional content does not make sense...
// Note: We can't remove them in the cloneAttchFn of $transclude as that
// function is called before linking the content, which would apply child
// directives to non existing elements.
var clone = $transclude(newScope, function(clone) {
$animate.enter(clone, null, currentElement || $element).then(function onNgViewEnter() {
if (angular.isDefined(autoScrollExp)
&& (!autoScrollExp || scope.$eval(autoScrollExp))) {
$anchorScroll();
}
});
cleanupLastView();
});
currentElement = clone;
currentScope = current.scope = newScope;
currentScope.$emit('$viewContentLoaded');
currentScope.$eval(onloadExp);
} else {
cleanupLastView();
}
}
}
};
currentElement = clone;
currentScope = current.scope = newScope;
currentScope.$emit('$viewContentLoaded');
currentScope.$eval(onloadExp);
} else {
cleanupLastView();
}
}
}
};
}

@@ -980,31 +971,31 @@ // This directive is called during the $transclude call of the first `ngView` directive.

// is called.
ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];
function ngViewFillContentFactory($compile, $controller, $route) {
return {
restrict: 'ECA',
priority: -400,
link: function (scope, $element) {
var current = $route.current,
locals = current.locals;
ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];
function ngViewFillContentFactory($compile, $controller, $route) {
return {
restrict: 'ECA',
priority: -400,
link: function(scope, $element) {
var current = $route.current,
locals = current.locals;
$element.html(locals.$template);
$element.html(locals.$template);
var link = $compile($element.contents());
var link = $compile($element.contents());
if (current.controller) {
locals.$scope = scope;
var controller = $controller(current.controller, locals);
if (current.controllerAs) {
scope[current.controllerAs] = controller;
}
$element.data('$ngControllerController', controller);
$element.children().data('$ngControllerController', controller);
}
if (current.controller) {
locals.$scope = scope;
var controller = $controller(current.controller, locals);
if (current.controllerAs) {
scope[current.controllerAs] = controller;
}
$element.data('$ngControllerController', controller);
$element.children().data('$ngControllerController', controller);
}
link(scope);
}
};
link(scope);
}
};
}
})(window, window.angular);

@@ -95,13 +95,4 @@ (function () {

.provider("visor", [function () {
function addNextToUrl(url, $location, restrictedUrl) {
if (config.shouldAddNext) {
if (url.indexOf("?") >= 0) {
return url.replace(/\?/, "?next=" + encodeURIComponent(restrictedUrl) + "&");
}
return url + "?next=" + encodeURIComponent(restrictedUrl);
} else {
return url;
}
}
var config = this;

@@ -175,4 +166,18 @@ /**

config.shouldAddNext = true;
/**
* @ngdoc property
* @name visor.visorProvider#nextParameterName
* @propertyOf visor.visorProvider
*
* @description
*
* The name of the parameter where the url that was restricted will be added to determine redirections
* when using {@link visor.visorProvider#shouldAddNext `visorProvider.shouldAddNext`}
*
* See {@link visor.visorProvider#shouldAddNext `visorProvider.shouldAddNext`} for more.
*
* Defaults to 'next'
*/
config.nextParameterName = 'next';
/**
* @ngdoc function

@@ -235,3 +240,6 @@ * @name visor.visorProvider#authenticate

config.doOnNotAuthenticated = ["$location", "restrictedUrl", function ($location, restrictedUrl) {
$location.url(addNextToUrl(config.loginRoute, $location, restrictedUrl))
$location.url(config.loginRoute);
if (config.shouldAddNext) {
$location.search(config.nextParameterName,restrictedUrl);
}
}];

@@ -261,3 +269,3 @@ /**

config.doAfterManualAuthentication = ["$location", function ($location) {
$location.url($location.search().next || config.homeRoute);
$location.url($location.search()[config.nextParameterName] || config.homeRoute);
}];

@@ -264,0 +272,0 @@ /**

@@ -308,3 +308,2 @@ 'use strict';

$rootScope.$apply();
$timeout.flush();
//should redirect back to original route automatically

@@ -329,2 +328,169 @@ expect($location.url()).toEqual("/private_url");

});
describe('next url',function(){
it('should add nextUrl to loginRoute with existing parameters', function () {
angular.module("test.nextUrl.1", ['ui.router', 'visor'])
.config(function ($stateProvider, visorProvider, authenticatedOnly) {
$stateProvider.state("private", {
url: "/private_url",
restrict: authenticatedOnly
})
.state("diffLogin", {
url: "/diffLogin?name"
})
visorProvider.loginRoute = "/diffLogin?name=myName#myHash"
visorProvider.authenticate = function ($q) {
return $q.reject("not authenticated");
};
});
module("test.nextUrl.1");
inject(function ($rootScope, $state, $q, $location, visor, $timeout) {
$location.url("/private_url");
$rootScope.$apply();
$timeout.flush();
expect($state.current.name).toEqual("diffLogin");
expect($location.search().next).toEqual("/private_url");
expect($location.search().name).toEqual("myName");
expect($location.hash()).toEqual("myHash");
visor.setAuthenticated({username: "some_name"});
$rootScope.$apply();
//should redirect back to original route automatically
expect($location.url()).toEqual("/private_url");
});
});
it('should add nextUrl to loginRoute if shouldAddNext option is disabled', function () {
angular.module("test.nextUrl.2", ['ui.router', 'visor'])
.config(function ($stateProvider, visorProvider, authenticatedOnly) {
$stateProvider.state("private", {
url: "/private_url",
restrict: authenticatedOnly
})
.state("login", {
url: "/login"
})
visorProvider.shouldAddNext = false;
visorProvider.authenticate = function ($q) {
return $q.reject("not authenticated");
};
});
module("test.nextUrl.2");
inject(function ($rootScope, $state, $q, $location, visor, $timeout) {
$location.url("/private_url");
$rootScope.$apply();
$timeout.flush();
expect($state.current.name).toEqual("login");
expect($location.search().next).toBe(undefined);
});
});
it('should override next parameter in loginUrl', function () {
angular.module("test.nextUrl.3", ['ui.router', 'visor'])
.config(function ($stateProvider, visorProvider, authenticatedOnly) {
$stateProvider.state("private", {
url: "/private_url",
restrict: authenticatedOnly
})
.state("login", {
url: "/login?next"
})
visorProvider.loginRoute = "/login?next=bad"
visorProvider.authenticate = function ($q) {
return $q.reject("not authenticated");
};
});
module("test.nextUrl.3");
inject(function ($rootScope, $state, $q, $location, visor, $timeout) {
$location.url("/private_url");
$rootScope.$apply();
$timeout.flush();
expect($state.current.name).toEqual("login");
expect($location.search().next).toEqual("/private_url");
});
});
it('should not override next parameter in loginUrl if shouldAddNext is disabled', function () {
angular.module("test.nextUrl.4", ['ui.router', 'visor'])
.config(function ($stateProvider, visorProvider, authenticatedOnly) {
$stateProvider.state("private", {
url: "/private_url",
restrict: authenticatedOnly
})
.state("login", {
url: "/login?next"
})
visorProvider.loginRoute = "/login?next=bad"
visorProvider.shouldAddNext = false;
visorProvider.authenticate = function ($q) {
return $q.reject("not authenticated");
};
});
module("test.nextUrl.4");
inject(function ($rootScope, $state, $q, $location, visor, $timeout) {
$location.url("/private_url");
$rootScope.$apply();
$timeout.flush();
expect($state.current.name).toEqual("login");
expect($location.search().next).toEqual("bad");
});
});
it('should allow next parameter to be replaced with different name', function () {
angular.module("test.nextUrl.5", ['ui.router', 'visor'])
.config(function ($stateProvider, visorProvider, authenticatedOnly) {
$stateProvider.state("private", {
url: "/private_url",
restrict: authenticatedOnly
})
.state("login", {
url: "/login?next"
})
visorProvider.loginRoute = "/login?next=shouldStay"
visorProvider.nextParameterName = "newNext"
visorProvider.authenticate = function ($q) {
return $q.reject("not authenticated");
};
});
module("test.nextUrl.5");
inject(function ($rootScope, $state, $q, $location, visor, $timeout) {
$location.url("/private_url");
$rootScope.$apply();
$timeout.flush();
expect($state.current.name).toEqual("login");
expect($location.search().next).toEqual("shouldStay");
expect($location.search().newNext).toEqual("/private_url");
visor.setAuthenticated({username: "some_name"});
$rootScope.$apply();
//should redirect back to original route automatically
expect($location.url()).toEqual("/private_url");
});
});
it('should allow changing next url manually', function () {
angular.module("test.nextUrl.6", ['ui.router', 'visor'])
.config(function ($stateProvider, visorProvider, authenticatedOnly,$urlRouterProvider) {
$stateProvider.state("dashboard", {
url: "/dashboard",
restrict: authenticatedOnly
}).state("private", {
url: "/private",
restrict: authenticatedOnly
})
.state("login", {
url: "/login"
})
visorProvider.authenticate = function ($q) {
return $q.reject("not authenticated");
};
});
module("test.nextUrl.6");
inject(function ($rootScope, $state, $q, $location, visor, $timeout) {
$location.url("/dashboard");
$rootScope.$apply();
$timeout.flush();
expect($state.current.name).toEqual("login");
expect($location.search().next).toEqual("/dashboard");
$location.search('next','/private');
visor.setAuthenticated({username: "some_name"});
$rootScope.$apply();
//should redirect back to original route automatically
expect($location.url()).toEqual("/private");
});
});
})
});

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc