Update XStatic-Angular to 1.4.10
Change-Id: Ie61a6282f792a8721674014dc11f2e2a2ec1245b
This commit is contained in:
parent
aee8cd393d
commit
65cde9c212
@ -11,9 +11,9 @@ NAME = __name__.split('.')[-1] # package name (e.g. 'foo' or 'foo_bar')
|
|||||||
# please use a all-lowercase valid python
|
# please use a all-lowercase valid python
|
||||||
# package name
|
# package name
|
||||||
|
|
||||||
VERSION = '1.3.18' # version of the packaged files, please use the upstream
|
VERSION = '1.4.10' # version of the packaged files, please use the upstream
|
||||||
# version number
|
# version number
|
||||||
BUILD = '1' # our package build number, so we can release new builds
|
BUILD = '0' # our package build number, so we can release new builds
|
||||||
# with fixes for xstatic stuff.
|
# with fixes for xstatic stuff.
|
||||||
PACKAGE_VERSION = VERSION + '.' + BUILD # version used for PyPi
|
PACKAGE_VERSION = VERSION + '.' + BUILD # version used for PyPi
|
||||||
|
|
||||||
|
5936
xstatic/pkg/angular/data/angular-animate.js
vendored
5936
xstatic/pkg/angular/data/angular-animate.js
vendored
File diff suppressed because it is too large
Load Diff
89
xstatic/pkg/angular/data/angular-aria.js
vendored
89
xstatic/pkg/angular/data/angular-aria.js
vendored
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @license AngularJS v1.3.18
|
* @license AngularJS v1.4.10
|
||||||
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
* (c) 2010-2015 Google, Inc. http://angularjs.org
|
||||||
* License: MIT
|
* License: MIT
|
||||||
*/
|
*/
|
||||||
(function(window, angular, undefined) {'use strict';
|
(function(window, angular, undefined) {'use strict';
|
||||||
@ -19,8 +19,8 @@
|
|||||||
*
|
*
|
||||||
* ## Usage
|
* ## Usage
|
||||||
*
|
*
|
||||||
* For ngAria to do its magic, simply include the module as a dependency. The directives supported
|
* For ngAria to do its magic, simply include the module `ngAria` as a dependency. The following
|
||||||
* by ngAria are:
|
* directives are supported:
|
||||||
* `ngModel`, `ngDisabled`, `ngShow`, `ngHide`, `ngClick`, `ngDblClick`, and `ngMessages`.
|
* `ngModel`, `ngDisabled`, `ngShow`, `ngHide`, `ngClick`, `ngDblClick`, and `ngMessages`.
|
||||||
*
|
*
|
||||||
* Below is a more detailed breakdown of the attributes handled by ngAria:
|
* Below is a more detailed breakdown of the attributes handled by ngAria:
|
||||||
@ -57,6 +57,16 @@
|
|||||||
var ngAriaModule = angular.module('ngAria', ['ng']).
|
var ngAriaModule = angular.module('ngAria', ['ng']).
|
||||||
provider('$aria', $AriaProvider);
|
provider('$aria', $AriaProvider);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal Utilities
|
||||||
|
*/
|
||||||
|
var nodeBlackList = ['BUTTON', 'A', 'INPUT', 'TEXTAREA', 'SELECT', 'DETAILS', 'SUMMARY'];
|
||||||
|
|
||||||
|
var isNodeOneOf = function(elem, nodeTypeArray) {
|
||||||
|
if (nodeTypeArray.indexOf(elem[0].nodeName) !== -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* @ngdoc provider
|
* @ngdoc provider
|
||||||
* @name $ariaProvider
|
* @name $ariaProvider
|
||||||
@ -88,7 +98,8 @@ function $AriaProvider() {
|
|||||||
ariaMultiline: true,
|
ariaMultiline: true,
|
||||||
ariaValue: true,
|
ariaValue: true,
|
||||||
tabindex: true,
|
tabindex: true,
|
||||||
bindKeypress: true
|
bindKeypress: true,
|
||||||
|
bindRoleForClick: true
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,6 +118,8 @@ function $AriaProvider() {
|
|||||||
* - **tabindex** – `{boolean}` – Enables/disables tabindex tags
|
* - **tabindex** – `{boolean}` – Enables/disables tabindex tags
|
||||||
* - **bindKeypress** – `{boolean}` – Enables/disables keypress event binding on `<div>` and
|
* - **bindKeypress** – `{boolean}` – Enables/disables keypress event binding on `<div>` and
|
||||||
* `<li>` elements with ng-click
|
* `<li>` elements with ng-click
|
||||||
|
* - **bindRoleForClick** – `{boolean}` – Adds role=button to non-interactive elements like `div`
|
||||||
|
* using ng-click, making them more accessible to users of assistive technologies
|
||||||
*
|
*
|
||||||
* @description
|
* @description
|
||||||
* Enables/disables various ARIA attributes
|
* Enables/disables various ARIA attributes
|
||||||
@ -115,20 +128,18 @@ function $AriaProvider() {
|
|||||||
config = angular.extend(config, newConfig);
|
config = angular.extend(config, newConfig);
|
||||||
};
|
};
|
||||||
|
|
||||||
function watchExpr(attrName, ariaAttr, negate) {
|
function watchExpr(attrName, ariaAttr, nodeBlackList, negate) {
|
||||||
return function(scope, elem, attr) {
|
return function(scope, elem, attr) {
|
||||||
var ariaCamelName = attr.$normalize(ariaAttr);
|
var ariaCamelName = attr.$normalize(ariaAttr);
|
||||||
if (config[ariaCamelName] && !attr[ariaCamelName]) {
|
if (config[ariaCamelName] && !isNodeOneOf(elem, nodeBlackList) && !attr[ariaCamelName]) {
|
||||||
scope.$watch(attr[attrName], function(boolVal) {
|
scope.$watch(attr[attrName], function(boolVal) {
|
||||||
if (negate) {
|
// ensure boolean value
|
||||||
boolVal = !boolVal;
|
boolVal = negate ? !boolVal : !!boolVal;
|
||||||
}
|
|
||||||
elem.attr(ariaAttr, boolVal);
|
elem.attr(ariaAttr, boolVal);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc service
|
* @ngdoc service
|
||||||
* @name $aria
|
* @name $aria
|
||||||
@ -187,10 +198,10 @@ function $AriaProvider() {
|
|||||||
|
|
||||||
|
|
||||||
ngAriaModule.directive('ngShow', ['$aria', function($aria) {
|
ngAriaModule.directive('ngShow', ['$aria', function($aria) {
|
||||||
return $aria.$$watchExpr('ngShow', 'aria-hidden', true);
|
return $aria.$$watchExpr('ngShow', 'aria-hidden', [], true);
|
||||||
}])
|
}])
|
||||||
.directive('ngHide', ['$aria', function($aria) {
|
.directive('ngHide', ['$aria', function($aria) {
|
||||||
return $aria.$$watchExpr('ngHide', 'aria-hidden', false);
|
return $aria.$$watchExpr('ngHide', 'aria-hidden', [], false);
|
||||||
}])
|
}])
|
||||||
.directive('ngModel', ['$aria', function($aria) {
|
.directive('ngModel', ['$aria', function($aria) {
|
||||||
|
|
||||||
@ -229,7 +240,8 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
post: function(scope, elem, attr, ngModel) {
|
post: function(scope, elem, attr, ngModel) {
|
||||||
var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem);
|
var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem)
|
||||||
|
&& !isNodeOneOf(elem, nodeBlackList);
|
||||||
|
|
||||||
function ngAriaWatchModelValue() {
|
function ngAriaWatchModelValue() {
|
||||||
return ngModel.$modelValue;
|
return ngModel.$modelValue;
|
||||||
@ -264,24 +276,40 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
|
|||||||
scope.$watch(ngAriaWatchModelValue, shape === 'radio' ?
|
scope.$watch(ngAriaWatchModelValue, shape === 'radio' ?
|
||||||
getRadioReaction() : ngAriaCheckboxReaction);
|
getRadioReaction() : ngAriaCheckboxReaction);
|
||||||
}
|
}
|
||||||
|
if (needsTabIndex) {
|
||||||
|
elem.attr('tabindex', 0);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'range':
|
case 'range':
|
||||||
if (shouldAttachRole(shape, elem)) {
|
if (shouldAttachRole(shape, elem)) {
|
||||||
elem.attr('role', 'slider');
|
elem.attr('role', 'slider');
|
||||||
}
|
}
|
||||||
if ($aria.config('ariaValue')) {
|
if ($aria.config('ariaValue')) {
|
||||||
if (attr.min && !elem.attr('aria-valuemin')) {
|
var needsAriaValuemin = !elem.attr('aria-valuemin') &&
|
||||||
elem.attr('aria-valuemin', attr.min);
|
(attr.hasOwnProperty('min') || attr.hasOwnProperty('ngMin'));
|
||||||
|
var needsAriaValuemax = !elem.attr('aria-valuemax') &&
|
||||||
|
(attr.hasOwnProperty('max') || attr.hasOwnProperty('ngMax'));
|
||||||
|
var needsAriaValuenow = !elem.attr('aria-valuenow');
|
||||||
|
|
||||||
|
if (needsAriaValuemin) {
|
||||||
|
attr.$observe('min', function ngAriaValueMinReaction(newVal) {
|
||||||
|
elem.attr('aria-valuemin', newVal);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (attr.max && !elem.attr('aria-valuemax')) {
|
if (needsAriaValuemax) {
|
||||||
elem.attr('aria-valuemax', attr.max);
|
attr.$observe('max', function ngAriaValueMinReaction(newVal) {
|
||||||
|
elem.attr('aria-valuemax', newVal);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (!elem.attr('aria-valuenow')) {
|
if (needsAriaValuenow) {
|
||||||
scope.$watch(ngAriaWatchModelValue, function ngAriaValueNowReaction(newVal) {
|
scope.$watch(ngAriaWatchModelValue, function ngAriaValueNowReaction(newVal) {
|
||||||
elem.attr('aria-valuenow', newVal);
|
elem.attr('aria-valuenow', newVal);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (needsTabIndex) {
|
||||||
|
elem.attr('tabindex', 0);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'multiline':
|
case 'multiline':
|
||||||
if (shouldAttachAttr('aria-multiline', 'ariaMultiline', elem)) {
|
if (shouldAttachAttr('aria-multiline', 'ariaMultiline', elem)) {
|
||||||
@ -290,10 +318,6 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needsTabIndex) {
|
|
||||||
elem.attr('tabindex', 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ngModel.$validators.required && shouldAttachAttr('aria-required', 'ariaRequired', elem)) {
|
if (ngModel.$validators.required && shouldAttachAttr('aria-required', 'ariaRequired', elem)) {
|
||||||
scope.$watch(function ngAriaRequiredWatch() {
|
scope.$watch(function ngAriaRequiredWatch() {
|
||||||
return ngModel.$error.required;
|
return ngModel.$error.required;
|
||||||
@ -315,7 +339,7 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
|
|||||||
};
|
};
|
||||||
}])
|
}])
|
||||||
.directive('ngDisabled', ['$aria', function($aria) {
|
.directive('ngDisabled', ['$aria', function($aria) {
|
||||||
return $aria.$$watchExpr('ngDisabled', 'aria-disabled');
|
return $aria.$$watchExpr('ngDisabled', 'aria-disabled', []);
|
||||||
}])
|
}])
|
||||||
.directive('ngMessages', function() {
|
.directive('ngMessages', function() {
|
||||||
return {
|
return {
|
||||||
@ -335,14 +359,9 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
|
|||||||
var fn = $parse(attr.ngClick, /* interceptorFn */ null, /* expensiveChecks */ true);
|
var fn = $parse(attr.ngClick, /* interceptorFn */ null, /* expensiveChecks */ true);
|
||||||
return function(scope, elem, attr) {
|
return function(scope, elem, attr) {
|
||||||
|
|
||||||
var nodeBlackList = ['BUTTON', 'A', 'INPUT', 'TEXTAREA'];
|
if (!isNodeOneOf(elem, nodeBlackList)) {
|
||||||
|
|
||||||
function isNodeOneOf(elem, nodeTypeArray) {
|
if ($aria.config('bindRoleForClick') && !elem.attr('role')) {
|
||||||
if (nodeTypeArray.indexOf(elem[0].nodeName) !== -1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!elem.attr('role') && !isNodeOneOf(elem, nodeBlackList)) {
|
|
||||||
elem.attr('role', 'button');
|
elem.attr('role', 'button');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,9 +369,10 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
|
|||||||
elem.attr('tabindex', 0);
|
elem.attr('tabindex', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($aria.config('bindKeypress') && !attr.ngKeypress && !isNodeOneOf(elem, nodeBlackList)) {
|
if ($aria.config('bindKeypress') && !attr.ngKeypress) {
|
||||||
elem.on('keypress', function(event) {
|
elem.on('keypress', function(event) {
|
||||||
if (event.keyCode === 32 || event.keyCode === 13) {
|
var keyCode = event.which || event.keyCode;
|
||||||
|
if (keyCode === 32 || keyCode === 13) {
|
||||||
scope.$apply(callback);
|
scope.$apply(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,13 +381,14 @@ ngAriaModule.directive('ngShow', ['$aria', function($aria) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}])
|
}])
|
||||||
.directive('ngDblclick', ['$aria', function($aria) {
|
.directive('ngDblclick', ['$aria', function($aria) {
|
||||||
return function(scope, elem, attr) {
|
return function(scope, elem, attr) {
|
||||||
if ($aria.config('tabindex') && !elem.attr('tabindex')) {
|
if ($aria.config('tabindex') && !elem.attr('tabindex') && !isNodeOneOf(elem, nodeBlackList)) {
|
||||||
elem.attr('tabindex', 0);
|
elem.attr('tabindex', 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
287
xstatic/pkg/angular/data/angular-cookies.js
vendored
287
xstatic/pkg/angular/data/angular-cookies.js
vendored
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @license AngularJS v1.3.18
|
* @license AngularJS v1.4.10
|
||||||
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
* (c) 2010-2015 Google, Inc. http://angularjs.org
|
||||||
* License: MIT
|
* License: MIT
|
||||||
*/
|
*/
|
||||||
(function(window, angular, undefined) {'use strict';
|
(function(window, angular, undefined) {'use strict';
|
||||||
@ -17,12 +17,47 @@
|
|||||||
*
|
*
|
||||||
* <div doc-module-components="ngCookies"></div>
|
* <div doc-module-components="ngCookies"></div>
|
||||||
*
|
*
|
||||||
* See {@link ngCookies.$cookies `$cookies`} and
|
* See {@link ngCookies.$cookies `$cookies`} for usage.
|
||||||
* {@link ngCookies.$cookieStore `$cookieStore`} for usage.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
angular.module('ngCookies', ['ng']).
|
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 property
|
||||||
|
* @name $cookiesProvider#defaults
|
||||||
|
* @description
|
||||||
|
*
|
||||||
|
* Object containing default options to pass when setting 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 is the URL that appears in your `<base>` tag.
|
||||||
|
* - **domain** - `{string}` - The cookie will be available only for this domain and
|
||||||
|
* its sub-domains. For security reasons the user agent will not accept the cookie
|
||||||
|
* if the current domain is not a sub-domain of this domain or equal to it.
|
||||||
|
* - **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}` - If `true`, then the cookie will only be available through a
|
||||||
|
* secured connection.
|
||||||
|
*
|
||||||
|
* Note: By default, the address that appears in your `<base>` tag will be used as the path.
|
||||||
|
* This is important so that cookies will be visible for all routes when html5mode is enabled.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
var defaults = this.defaults = {};
|
||||||
|
|
||||||
|
function calcOptions(options) {
|
||||||
|
return options ? angular.extend({}, defaults, options) : defaults;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc service
|
* @ngdoc service
|
||||||
* @name $cookies
|
* @name $cookies
|
||||||
@ -30,9 +65,11 @@ angular.module('ngCookies', ['ng']).
|
|||||||
* @description
|
* @description
|
||||||
* Provides read/write access to browser's cookies.
|
* Provides read/write access to browser's cookies.
|
||||||
*
|
*
|
||||||
* Only a simple Object is exposed and by adding or removing properties to/from this object, new
|
* <div class="alert alert-info">
|
||||||
* cookies are created/deleted at the end of current $eval.
|
* Up until Angular 1.3, `$cookies` exposed properties that represented the
|
||||||
* The object's properties can only be strings.
|
* current browser cookie values. In version 1.4, this behavior has changed, and
|
||||||
|
* `$cookies` now provides a standard api of getters, setters etc.
|
||||||
|
* </div>
|
||||||
*
|
*
|
||||||
* Requires the {@link ngCookies `ngCookies`} module to be installed.
|
* Requires the {@link ngCookies `ngCookies`} module to be installed.
|
||||||
*
|
*
|
||||||
@ -42,96 +79,111 @@ angular.module('ngCookies', ['ng']).
|
|||||||
* angular.module('cookiesExample', ['ngCookies'])
|
* angular.module('cookiesExample', ['ngCookies'])
|
||||||
* .controller('ExampleController', ['$cookies', function($cookies) {
|
* .controller('ExampleController', ['$cookies', function($cookies) {
|
||||||
* // Retrieving a cookie
|
* // Retrieving a cookie
|
||||||
* var favoriteCookie = $cookies.myFavorite;
|
* var favoriteCookie = $cookies.get('myFavorite');
|
||||||
* // Setting a cookie
|
* // Setting a cookie
|
||||||
* $cookies.myFavorite = 'oatmeal';
|
* $cookies.put('myFavorite', 'oatmeal');
|
||||||
* }]);
|
* }]);
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
factory('$cookies', ['$rootScope', '$browser', function($rootScope, $browser) {
|
this.$get = ['$$cookieReader', '$$cookieWriter', function($$cookieReader, $$cookieWriter) {
|
||||||
var cookies = {},
|
return {
|
||||||
lastCookies = {},
|
/**
|
||||||
lastBrowserCookies,
|
* @ngdoc method
|
||||||
runEval = false,
|
* @name $cookies#get
|
||||||
copy = angular.copy,
|
*
|
||||||
isUndefined = angular.isUndefined;
|
* @description
|
||||||
|
* Returns the value of given cookie key
|
||||||
//creates a poller fn that copies all cookies from the $browser to service & inits the service
|
*
|
||||||
$browser.addPollFn(function() {
|
* @param {string} key Id to use for lookup.
|
||||||
var currentCookies = $browser.cookies();
|
* @returns {string} Raw cookie value.
|
||||||
if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl
|
*/
|
||||||
lastBrowserCookies = currentCookies;
|
get: function(key) {
|
||||||
copy(currentCookies, lastCookies);
|
return $$cookieReader()[key];
|
||||||
copy(currentCookies, cookies);
|
},
|
||||||
if (runEval) $rootScope.$apply();
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
runEval = true;
|
|
||||||
|
|
||||||
//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);
|
|
||||||
|
|
||||||
return cookies;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pushes all the cookies from the service to the browser and verifies if all cookies were
|
* @ngdoc method
|
||||||
* stored.
|
* @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.
|
||||||
*/
|
*/
|
||||||
function push() {
|
getObject: function(key) {
|
||||||
var name,
|
var value = this.get(key);
|
||||||
value,
|
return value ? angular.fromJson(value) : value;
|
||||||
browserCookies,
|
},
|
||||||
updated;
|
|
||||||
|
|
||||||
//delete any cookies deleted in $cookies
|
/**
|
||||||
for (name in lastCookies) {
|
* @ngdoc method
|
||||||
if (isUndefined(cookies[name])) {
|
* @name $cookies#getAll
|
||||||
$browser.cookies(name, undefined);
|
*
|
||||||
delete lastCookies[name];
|
* @description
|
||||||
}
|
* Returns a key value object with all the cookies
|
||||||
}
|
*
|
||||||
|
* @returns {Object} All cookies
|
||||||
|
*/
|
||||||
|
getAll: function() {
|
||||||
|
return $$cookieReader();
|
||||||
|
},
|
||||||
|
|
||||||
//update all cookies updated in $cookies
|
/**
|
||||||
for (name in cookies) {
|
* @ngdoc method
|
||||||
value = cookies[name];
|
* @name $cookies#put
|
||||||
if (!angular.isString(value)) {
|
*
|
||||||
value = '' + value;
|
* @description
|
||||||
cookies[name] = value;
|
* Sets a value for given cookie key
|
||||||
}
|
*
|
||||||
if (value !== lastCookies[name]) {
|
* @param {string} key Id for the `value`.
|
||||||
$browser.cookies(name, value);
|
* @param {string} value Raw value to be stored.
|
||||||
lastCookies[name] = value;
|
* @param {Object=} options Options object.
|
||||||
updated = true;
|
* See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
|
||||||
}
|
*/
|
||||||
}
|
put: function(key, value, options) {
|
||||||
|
$$cookieWriter(key, value, calcOptions(options));
|
||||||
|
},
|
||||||
|
|
||||||
//verify what was actually stored
|
/**
|
||||||
if (updated) {
|
* @ngdoc method
|
||||||
browserCookies = $browser.cookies();
|
* @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);
|
||||||
|
},
|
||||||
|
|
||||||
for (name in cookies) {
|
/**
|
||||||
if (cookies[name] !== browserCookies[name]) {
|
* @ngdoc method
|
||||||
//delete or reset all cookies that the browser dropped from $cookies
|
* @name $cookies#remove
|
||||||
if (isUndefined(browserCookies[name])) {
|
*
|
||||||
delete cookies[name];
|
* @description
|
||||||
delete lastCookies[name];
|
* Remove given cookie
|
||||||
} else {
|
*
|
||||||
cookies[name] = lastCookies[name] = browserCookies[name];
|
* @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));
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}];
|
||||||
}
|
}]);
|
||||||
}
|
|
||||||
}]).
|
|
||||||
|
|
||||||
|
|
||||||
|
angular.module('ngCookies').
|
||||||
/**
|
/**
|
||||||
* @ngdoc service
|
* @ngdoc service
|
||||||
* @name $cookieStore
|
* @name $cookieStore
|
||||||
|
* @deprecated
|
||||||
* @requires $cookies
|
* @requires $cookies
|
||||||
*
|
*
|
||||||
* @description
|
* @description
|
||||||
@ -141,6 +193,11 @@ angular.module('ngCookies', ['ng']).
|
|||||||
*
|
*
|
||||||
* Requires the {@link ngCookies `ngCookies`} module to be installed.
|
* 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
|
* @example
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
@ -166,11 +223,10 @@ angular.module('ngCookies', ['ng']).
|
|||||||
* Returns the value of given cookie key
|
* Returns the value of given cookie key
|
||||||
*
|
*
|
||||||
* @param {string} key Id to use for lookup.
|
* @param {string} key Id to use for lookup.
|
||||||
* @returns {Object} Deserialized cookie value.
|
* @returns {Object} Deserialized cookie value, undefined if the cookie does not exist.
|
||||||
*/
|
*/
|
||||||
get: function(key) {
|
get: function(key) {
|
||||||
var value = $cookies[key];
|
return $cookies.getObject(key);
|
||||||
return value ? angular.fromJson(value) : value;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -184,7 +240,7 @@ angular.module('ngCookies', ['ng']).
|
|||||||
* @param {Object} value Value to be stored.
|
* @param {Object} value Value to be stored.
|
||||||
*/
|
*/
|
||||||
put: function(key, value) {
|
put: function(key, value) {
|
||||||
$cookies[key] = angular.toJson(value);
|
$cookies.putObject(key, value);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -197,11 +253,70 @@ angular.module('ngCookies', ['ng']).
|
|||||||
* @param {string} key Id of the key-value pair to delete.
|
* @param {string} key Id of the key-value pair to delete.
|
||||||
*/
|
*/
|
||||||
remove: function(key) {
|
remove: function(key) {
|
||||||
delete $cookies[key];
|
$cookies.remove(key);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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];
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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' : '';
|
||||||
|
|
||||||
|
// 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)!");
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
})(window, window.angular);
|
||||||
|
@ -11,3 +11,11 @@
|
|||||||
ng\:form {
|
ng\:form {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ng-animate-shim {
|
||||||
|
visibility:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ng-anchor {
|
||||||
|
position:absolute;
|
||||||
|
}
|
||||||
|
113
xstatic/pkg/angular/data/angular-loader.js
vendored
113
xstatic/pkg/angular/data/angular-loader.js
vendored
@ -1,10 +1,39 @@
|
|||||||
/**
|
/**
|
||||||
* @license AngularJS v1.3.18
|
* @license AngularJS v1.4.10
|
||||||
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
* (c) 2010-2015 Google, Inc. http://angularjs.org
|
||||||
* License: MIT
|
* License: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(function() {'use strict';
|
(function() {'use strict';
|
||||||
|
function isFunction(value) {return typeof value === 'function';};
|
||||||
|
|
||||||
|
/* global: toDebugString: true */
|
||||||
|
|
||||||
|
function serializeObject(obj) {
|
||||||
|
var seen = [];
|
||||||
|
|
||||||
|
return JSON.stringify(obj, function(key, val) {
|
||||||
|
val = toJsonReplacer(key, val);
|
||||||
|
if (isObject(val)) {
|
||||||
|
|
||||||
|
if (seen.indexOf(val) >= 0) return '...';
|
||||||
|
|
||||||
|
seen.push(val);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function toDebugString(obj) {
|
||||||
|
if (typeof obj === 'function') {
|
||||||
|
return obj.toString().replace(/ \{[\s\S]*$/, '');
|
||||||
|
} else if (isUndefined(obj)) {
|
||||||
|
return 'undefined';
|
||||||
|
} else if (typeof obj !== 'string') {
|
||||||
|
return serializeObject(obj);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
@ -39,28 +68,33 @@
|
|||||||
function minErr(module, ErrorConstructor) {
|
function minErr(module, ErrorConstructor) {
|
||||||
ErrorConstructor = ErrorConstructor || Error;
|
ErrorConstructor = ErrorConstructor || Error;
|
||||||
return function() {
|
return function() {
|
||||||
var code = arguments[0],
|
var SKIP_INDEXES = 2;
|
||||||
prefix = '[' + (module ? module + ':' : '') + code + '] ',
|
|
||||||
template = arguments[1],
|
|
||||||
templateArgs = arguments,
|
|
||||||
|
|
||||||
message, i;
|
var templateArgs = arguments,
|
||||||
|
code = templateArgs[0],
|
||||||
|
message = '[' + (module ? module + ':' : '') + code + '] ',
|
||||||
|
template = templateArgs[1],
|
||||||
|
paramPrefix, i;
|
||||||
|
|
||||||
message = prefix + template.replace(/\{\d+\}/g, function(match) {
|
message += template.replace(/\{\d+\}/g, function(match) {
|
||||||
var index = +match.slice(1, -1), arg;
|
var index = +match.slice(1, -1),
|
||||||
|
shiftedIndex = index + SKIP_INDEXES;
|
||||||
|
|
||||||
if (index + 2 < templateArgs.length) {
|
if (shiftedIndex < templateArgs.length) {
|
||||||
return toDebugString(templateArgs[index + 2]);
|
return toDebugString(templateArgs[shiftedIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return match;
|
return match;
|
||||||
});
|
});
|
||||||
|
|
||||||
message = message + '\nhttp://errors.angularjs.org/1.3.18/' +
|
message += '\nhttp://errors.angularjs.org/1.4.10/' +
|
||||||
(module ? module + '/' : '') + code;
|
(module ? module + '/' : '') + code;
|
||||||
for (i = 2; i < arguments.length; i++) {
|
|
||||||
message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' +
|
for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
|
||||||
encodeURIComponent(toDebugString(arguments[i]));
|
message += paramPrefix + 'p' + (i - SKIP_INDEXES) + '=' +
|
||||||
|
encodeURIComponent(toDebugString(templateArgs[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ErrorConstructor(message);
|
return new ErrorConstructor(message);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -103,8 +137,8 @@ function setupModuleLoader(window) {
|
|||||||
* All modules (angular core or 3rd party) that should be available to an application must be
|
* All modules (angular core or 3rd party) that should be available to an application must be
|
||||||
* registered using this mechanism.
|
* registered using this mechanism.
|
||||||
*
|
*
|
||||||
* When passed two or more arguments, a new module is created. If passed only one argument, an
|
* Passing one argument retrieves an existing {@link angular.Module},
|
||||||
* existing module (the name passed as the first argument to `module`) is retrieved.
|
* whereas passing more than one argument creates a new {@link angular.Module}
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* # Module
|
* # Module
|
||||||
@ -141,7 +175,7 @@ function setupModuleLoader(window) {
|
|||||||
* unspecified then the module is being retrieved for further configuration.
|
* unspecified then the module is being retrieved for further configuration.
|
||||||
* @param {Function=} configFn Optional configuration function for the module. Same as
|
* @param {Function=} configFn Optional configuration function for the module. Same as
|
||||||
* {@link angular.Module#config Module#config()}.
|
* {@link angular.Module#config Module#config()}.
|
||||||
* @returns {module} new module with the {@link angular.Module} api.
|
* @returns {angular.Module} new module with the {@link angular.Module} api.
|
||||||
*/
|
*/
|
||||||
return function module(name, requires, configFn) {
|
return function module(name, requires, configFn) {
|
||||||
var assertNotHasOwnProperty = function(name, context) {
|
var assertNotHasOwnProperty = function(name, context) {
|
||||||
@ -211,7 +245,7 @@ function setupModuleLoader(window) {
|
|||||||
* @description
|
* @description
|
||||||
* See {@link auto.$provide#provider $provide.provider()}.
|
* See {@link auto.$provide#provider $provide.provider()}.
|
||||||
*/
|
*/
|
||||||
provider: invokeLater('$provide', 'provider'),
|
provider: invokeLaterAndSetModuleName('$provide', 'provider'),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc method
|
* @ngdoc method
|
||||||
@ -222,7 +256,7 @@ function setupModuleLoader(window) {
|
|||||||
* @description
|
* @description
|
||||||
* See {@link auto.$provide#factory $provide.factory()}.
|
* See {@link auto.$provide#factory $provide.factory()}.
|
||||||
*/
|
*/
|
||||||
factory: invokeLater('$provide', 'factory'),
|
factory: invokeLaterAndSetModuleName('$provide', 'factory'),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc method
|
* @ngdoc method
|
||||||
@ -233,7 +267,7 @@ function setupModuleLoader(window) {
|
|||||||
* @description
|
* @description
|
||||||
* See {@link auto.$provide#service $provide.service()}.
|
* See {@link auto.$provide#service $provide.service()}.
|
||||||
*/
|
*/
|
||||||
service: invokeLater('$provide', 'service'),
|
service: invokeLaterAndSetModuleName('$provide', 'service'),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc method
|
* @ngdoc method
|
||||||
@ -253,11 +287,23 @@ function setupModuleLoader(window) {
|
|||||||
* @param {string} name constant name
|
* @param {string} name constant name
|
||||||
* @param {*} object Constant value.
|
* @param {*} object Constant value.
|
||||||
* @description
|
* @description
|
||||||
* Because the constant are fixed, they get applied before other provide methods.
|
* Because the constants are fixed, they get applied before other provide methods.
|
||||||
* See {@link auto.$provide#constant $provide.constant()}.
|
* See {@link auto.$provide#constant $provide.constant()}.
|
||||||
*/
|
*/
|
||||||
constant: invokeLater('$provide', 'constant', 'unshift'),
|
constant: invokeLater('$provide', 'constant', 'unshift'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc method
|
||||||
|
* @name angular.Module#decorator
|
||||||
|
* @module ng
|
||||||
|
* @param {string} The name of the service to decorate.
|
||||||
|
* @param {Function} This function will be invoked when the service needs to be
|
||||||
|
* instantiated and should return the decorated service instance.
|
||||||
|
* @description
|
||||||
|
* See {@link auto.$provide#decorator $provide.decorator()}.
|
||||||
|
*/
|
||||||
|
decorator: invokeLaterAndSetModuleName('$provide', 'decorator'),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc method
|
* @ngdoc method
|
||||||
* @name angular.Module#animation
|
* @name angular.Module#animation
|
||||||
@ -271,7 +317,7 @@ function setupModuleLoader(window) {
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Defines an animation hook that can be later used with
|
* Defines an animation hook that can be later used with
|
||||||
* {@link ngAnimate.$animate $animate} service and directives that use this service.
|
* {@link $animate $animate} service and directives that use this service.
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* module.animation('.animation-name', function($inject1, $inject2) {
|
* module.animation('.animation-name', function($inject1, $inject2) {
|
||||||
@ -290,7 +336,7 @@ function setupModuleLoader(window) {
|
|||||||
* See {@link ng.$animateProvider#register $animateProvider.register()} and
|
* See {@link ng.$animateProvider#register $animateProvider.register()} and
|
||||||
* {@link ngAnimate ngAnimate module} for more information.
|
* {@link ngAnimate ngAnimate module} for more information.
|
||||||
*/
|
*/
|
||||||
animation: invokeLater('$animateProvider', 'register'),
|
animation: invokeLaterAndSetModuleName('$animateProvider', 'register'),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc method
|
* @ngdoc method
|
||||||
@ -308,7 +354,7 @@ function setupModuleLoader(window) {
|
|||||||
* (`myapp_subsection_filterx`).
|
* (`myapp_subsection_filterx`).
|
||||||
* </div>
|
* </div>
|
||||||
*/
|
*/
|
||||||
filter: invokeLater('$filterProvider', 'register'),
|
filter: invokeLaterAndSetModuleName('$filterProvider', 'register'),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc method
|
* @ngdoc method
|
||||||
@ -320,7 +366,7 @@ function setupModuleLoader(window) {
|
|||||||
* @description
|
* @description
|
||||||
* See {@link ng.$controllerProvider#register $controllerProvider.register()}.
|
* See {@link ng.$controllerProvider#register $controllerProvider.register()}.
|
||||||
*/
|
*/
|
||||||
controller: invokeLater('$controllerProvider', 'register'),
|
controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc method
|
* @ngdoc method
|
||||||
@ -333,7 +379,7 @@ function setupModuleLoader(window) {
|
|||||||
* @description
|
* @description
|
||||||
* See {@link ng.$compileProvider#directive $compileProvider.directive()}.
|
* See {@link ng.$compileProvider#directive $compileProvider.directive()}.
|
||||||
*/
|
*/
|
||||||
directive: invokeLater('$compileProvider', 'directive'),
|
directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc method
|
* @ngdoc method
|
||||||
@ -383,6 +429,19 @@ function setupModuleLoader(window) {
|
|||||||
return moduleInstance;
|
return moduleInstance;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} provider
|
||||||
|
* @param {string} method
|
||||||
|
* @returns {angular.Module}
|
||||||
|
*/
|
||||||
|
function invokeLaterAndSetModuleName(provider, method) {
|
||||||
|
return function(recipeName, factoryFunction) {
|
||||||
|
if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name;
|
||||||
|
invokeQueue.push([provider, method, arguments]);
|
||||||
|
return moduleInstance;
|
||||||
|
};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
980
xstatic/pkg/angular/data/angular-message-format.js
vendored
Normal file
980
xstatic/pkg/angular/data/angular-message-format.js
vendored
Normal file
@ -0,0 +1,980 @@
|
|||||||
|
/**
|
||||||
|
* @license AngularJS v1.4.10
|
||||||
|
* (c) 2010-2015 Google, Inc. http://angularjs.org
|
||||||
|
* License: MIT
|
||||||
|
*/
|
||||||
|
(function(window, angular, undefined) {'use strict';
|
||||||
|
|
||||||
|
// NOTE: ADVANCED_OPTIMIZATIONS mode.
|
||||||
|
//
|
||||||
|
// This file is compiled with Closure compiler's ADVANCED_OPTIMIZATIONS flag! Be wary of using
|
||||||
|
// constructs incompatible with that mode.
|
||||||
|
|
||||||
|
var $interpolateMinErr = window['angular']['$interpolateMinErr'];
|
||||||
|
|
||||||
|
var noop = window['angular']['noop'],
|
||||||
|
isFunction = window['angular']['isFunction'],
|
||||||
|
toJson = window['angular']['toJson'];
|
||||||
|
|
||||||
|
function stringify(value) {
|
||||||
|
if (value == null /* null/undefined */) { return ''; }
|
||||||
|
switch (typeof value) {
|
||||||
|
case 'string': return value;
|
||||||
|
case 'number': return '' + value;
|
||||||
|
default: return toJson(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert an index into the string into line/column for use in error messages
|
||||||
|
// As such, this doesn't have to be efficient.
|
||||||
|
function indexToLineAndColumn(text, index) {
|
||||||
|
var lines = text.split(/\n/g);
|
||||||
|
for (var i=0; i < lines.length; i++) {
|
||||||
|
var line=lines[i];
|
||||||
|
if (index >= line.length) {
|
||||||
|
index -= line.length;
|
||||||
|
} else {
|
||||||
|
return { line: i + 1, column: index + 1 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var PARSE_CACHE_FOR_TEXT_LITERALS = Object.create(null);
|
||||||
|
|
||||||
|
function parseTextLiteral(text) {
|
||||||
|
var cachedFn = PARSE_CACHE_FOR_TEXT_LITERALS[text];
|
||||||
|
if (cachedFn != null) {
|
||||||
|
return cachedFn;
|
||||||
|
}
|
||||||
|
function parsedFn(context) { return text; }
|
||||||
|
parsedFn['$$watchDelegate'] = function watchDelegate(scope, listener, objectEquality) {
|
||||||
|
var unwatch = scope['$watch'](noop,
|
||||||
|
function textLiteralWatcher() {
|
||||||
|
if (isFunction(listener)) { listener.call(null, text, text, scope); }
|
||||||
|
unwatch();
|
||||||
|
},
|
||||||
|
objectEquality);
|
||||||
|
return unwatch;
|
||||||
|
};
|
||||||
|
PARSE_CACHE_FOR_TEXT_LITERALS[text] = parsedFn;
|
||||||
|
parsedFn['exp'] = text; // Needed to pretend to be $interpolate for tests copied from interpolateSpec.js
|
||||||
|
parsedFn['expressions'] = []; // Require this to call $compile.$$addBindingInfo() which allows Protractor to find elements by binding.
|
||||||
|
return parsedFn;
|
||||||
|
}
|
||||||
|
|
||||||
|
function subtractOffset(expressionFn, offset) {
|
||||||
|
if (offset === 0) {
|
||||||
|
return expressionFn;
|
||||||
|
}
|
||||||
|
function minusOffset(value) {
|
||||||
|
return (value == void 0) ? value : value - offset;
|
||||||
|
}
|
||||||
|
function parsedFn(context) { return minusOffset(expressionFn(context)); }
|
||||||
|
var unwatch;
|
||||||
|
parsedFn['$$watchDelegate'] = function watchDelegate(scope, listener, objectEquality) {
|
||||||
|
unwatch = scope['$watch'](expressionFn,
|
||||||
|
function pluralExpressionWatchListener(newValue, oldValue) {
|
||||||
|
if (isFunction(listener)) { listener.call(null, minusOffset(newValue), minusOffset(oldValue), scope); }
|
||||||
|
},
|
||||||
|
objectEquality);
|
||||||
|
return unwatch;
|
||||||
|
};
|
||||||
|
return parsedFn;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: ADVANCED_OPTIMIZATIONS mode.
|
||||||
|
//
|
||||||
|
// This file is compiled with Closure compiler's ADVANCED_OPTIMIZATIONS flag! Be wary of using
|
||||||
|
// constructs incompatible with that mode.
|
||||||
|
|
||||||
|
/* global $interpolateMinErr: false */
|
||||||
|
/* global isFunction: false */
|
||||||
|
/* global noop: false */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function MessageSelectorBase(expressionFn, choices) {
|
||||||
|
var self = this;
|
||||||
|
this.expressionFn = expressionFn;
|
||||||
|
this.choices = choices;
|
||||||
|
if (choices["other"] === void 0) {
|
||||||
|
throw $interpolateMinErr('reqother', '“other” is a required option.');
|
||||||
|
}
|
||||||
|
this.parsedFn = function(context) { return self.getResult(context); };
|
||||||
|
this.parsedFn['$$watchDelegate'] = function $$watchDelegate(scope, listener, objectEquality) {
|
||||||
|
return self.watchDelegate(scope, listener, objectEquality);
|
||||||
|
};
|
||||||
|
this.parsedFn['exp'] = expressionFn['exp'];
|
||||||
|
this.parsedFn['expressions'] = expressionFn['expressions'];
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageSelectorBase.prototype.getMessageFn = function getMessageFn(value) {
|
||||||
|
return this.choices[this.categorizeValue(value)];
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageSelectorBase.prototype.getResult = function getResult(context) {
|
||||||
|
return this.getMessageFn(this.expressionFn(context))(context);
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageSelectorBase.prototype.watchDelegate = function watchDelegate(scope, listener, objectEquality) {
|
||||||
|
var watchers = new MessageSelectorWatchers(this, scope, listener, objectEquality);
|
||||||
|
return function() { watchers.cancelWatch(); };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function MessageSelectorWatchers(msgSelector, scope, listener, objectEquality) {
|
||||||
|
var self = this;
|
||||||
|
this.scope = scope;
|
||||||
|
this.msgSelector = msgSelector;
|
||||||
|
this.listener = listener;
|
||||||
|
this.objectEquality = objectEquality;
|
||||||
|
this.lastMessage = void 0;
|
||||||
|
this.messageFnWatcher = noop;
|
||||||
|
var expressionFnListener = function(newValue, oldValue) { return self.expressionFnListener(newValue, oldValue); };
|
||||||
|
this.expressionFnWatcher = scope['$watch'](msgSelector.expressionFn, expressionFnListener, objectEquality);
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageSelectorWatchers.prototype.expressionFnListener = function expressionFnListener(newValue, oldValue) {
|
||||||
|
var self = this;
|
||||||
|
this.messageFnWatcher();
|
||||||
|
var messageFnListener = function(newMessage, oldMessage) { return self.messageFnListener(newMessage, oldMessage); };
|
||||||
|
var messageFn = this.msgSelector.getMessageFn(newValue);
|
||||||
|
this.messageFnWatcher = this.scope['$watch'](messageFn, messageFnListener, this.objectEquality);
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageSelectorWatchers.prototype.messageFnListener = function messageFnListener(newMessage, oldMessage) {
|
||||||
|
if (isFunction(this.listener)) {
|
||||||
|
this.listener.call(null, newMessage, newMessage === oldMessage ? newMessage : this.lastMessage, this.scope);
|
||||||
|
}
|
||||||
|
this.lastMessage = newMessage;
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageSelectorWatchers.prototype.cancelWatch = function cancelWatch() {
|
||||||
|
this.expressionFnWatcher();
|
||||||
|
this.messageFnWatcher();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @extends MessageSelectorBase
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function SelectMessage(expressionFn, choices) {
|
||||||
|
MessageSelectorBase.call(this, expressionFn, choices);
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectMessageProto() {}
|
||||||
|
SelectMessageProto.prototype = MessageSelectorBase.prototype;
|
||||||
|
|
||||||
|
SelectMessage.prototype = new SelectMessageProto();
|
||||||
|
SelectMessage.prototype.categorizeValue = function categorizeSelectValue(value) {
|
||||||
|
return (this.choices[value] !== void 0) ? value : "other";
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @extends MessageSelectorBase
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function PluralMessage(expressionFn, choices, offset, pluralCat) {
|
||||||
|
MessageSelectorBase.call(this, expressionFn, choices);
|
||||||
|
this.offset = offset;
|
||||||
|
this.pluralCat = pluralCat;
|
||||||
|
}
|
||||||
|
|
||||||
|
function PluralMessageProto() {}
|
||||||
|
PluralMessageProto.prototype = MessageSelectorBase.prototype;
|
||||||
|
|
||||||
|
PluralMessage.prototype = new PluralMessageProto();
|
||||||
|
PluralMessage.prototype.categorizeValue = function categorizePluralValue(value) {
|
||||||
|
if (isNaN(value)) {
|
||||||
|
return "other";
|
||||||
|
} else if (this.choices[value] !== void 0) {
|
||||||
|
return value;
|
||||||
|
} else {
|
||||||
|
var category = this.pluralCat(value - this.offset);
|
||||||
|
return (this.choices[category] !== void 0) ? category : "other";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// NOTE: ADVANCED_OPTIMIZATIONS mode.
|
||||||
|
//
|
||||||
|
// This file is compiled with Closure compiler's ADVANCED_OPTIMIZATIONS flag! Be wary of using
|
||||||
|
// constructs incompatible with that mode.
|
||||||
|
|
||||||
|
/* global $interpolateMinErr: false */
|
||||||
|
/* global isFunction: false */
|
||||||
|
/* global parseTextLiteral: false */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function InterpolationParts(trustedContext, allOrNothing) {
|
||||||
|
this.trustedContext = trustedContext;
|
||||||
|
this.allOrNothing = allOrNothing;
|
||||||
|
this.textParts = [];
|
||||||
|
this.expressionFns = [];
|
||||||
|
this.expressionIndices = [];
|
||||||
|
this.partialText = '';
|
||||||
|
this.concatParts = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
InterpolationParts.prototype.flushPartialText = function flushPartialText() {
|
||||||
|
if (this.partialText) {
|
||||||
|
if (this.concatParts == null) {
|
||||||
|
this.textParts.push(this.partialText);
|
||||||
|
} else {
|
||||||
|
this.textParts.push(this.concatParts.join(''));
|
||||||
|
this.concatParts = null;
|
||||||
|
}
|
||||||
|
this.partialText = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
InterpolationParts.prototype.addText = function addText(text) {
|
||||||
|
if (text.length) {
|
||||||
|
if (!this.partialText) {
|
||||||
|
this.partialText = text;
|
||||||
|
} else if (this.concatParts) {
|
||||||
|
this.concatParts.push(text);
|
||||||
|
} else {
|
||||||
|
this.concatParts = [this.partialText, text];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
InterpolationParts.prototype.addExpressionFn = function addExpressionFn(expressionFn) {
|
||||||
|
this.flushPartialText();
|
||||||
|
this.expressionIndices.push(this.textParts.length);
|
||||||
|
this.expressionFns.push(expressionFn);
|
||||||
|
this.textParts.push('');
|
||||||
|
};
|
||||||
|
|
||||||
|
InterpolationParts.prototype.getExpressionValues = function getExpressionValues(context) {
|
||||||
|
var expressionValues = new Array(this.expressionFns.length);
|
||||||
|
for (var i = 0; i < this.expressionFns.length; i++) {
|
||||||
|
expressionValues[i] = this.expressionFns[i](context);
|
||||||
|
}
|
||||||
|
return expressionValues;
|
||||||
|
};
|
||||||
|
|
||||||
|
InterpolationParts.prototype.getResult = function getResult(expressionValues) {
|
||||||
|
for (var i = 0; i < this.expressionIndices.length; i++) {
|
||||||
|
var expressionValue = expressionValues[i];
|
||||||
|
if (this.allOrNothing && expressionValue === void 0) return;
|
||||||
|
this.textParts[this.expressionIndices[i]] = expressionValue;
|
||||||
|
}
|
||||||
|
return this.textParts.join('');
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
InterpolationParts.prototype.toParsedFn = function toParsedFn(mustHaveExpression, originalText) {
|
||||||
|
var self = this;
|
||||||
|
this.flushPartialText();
|
||||||
|
if (mustHaveExpression && this.expressionFns.length === 0) {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
if (this.textParts.length === 0) {
|
||||||
|
return parseTextLiteral('');
|
||||||
|
}
|
||||||
|
if (this.trustedContext && this.textParts.length > 1) {
|
||||||
|
$interpolateMinErr['throwNoconcat'](originalText);
|
||||||
|
}
|
||||||
|
if (this.expressionFns.length === 0) {
|
||||||
|
if (this.textParts.length != 1) { this.errorInParseLogic(); }
|
||||||
|
return parseTextLiteral(this.textParts[0]);
|
||||||
|
}
|
||||||
|
var parsedFn = function(context) {
|
||||||
|
return self.getResult(self.getExpressionValues(context));
|
||||||
|
};
|
||||||
|
parsedFn['$$watchDelegate'] = function $$watchDelegate(scope, listener, objectEquality) {
|
||||||
|
return self.watchDelegate(scope, listener, objectEquality);
|
||||||
|
};
|
||||||
|
|
||||||
|
parsedFn['exp'] = originalText; // Needed to pretend to be $interpolate for tests copied from interpolateSpec.js
|
||||||
|
parsedFn['expressions'] = new Array(this.expressionFns.length); // Require this to call $compile.$$addBindingInfo() which allows Protractor to find elements by binding.
|
||||||
|
for (var i = 0; i < this.expressionFns.length; i++) {
|
||||||
|
parsedFn['expressions'][i] = this.expressionFns[i]['exp'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsedFn;
|
||||||
|
};
|
||||||
|
|
||||||
|
InterpolationParts.prototype.watchDelegate = function watchDelegate(scope, listener, objectEquality) {
|
||||||
|
var watcher = new InterpolationPartsWatcher(this, scope, listener, objectEquality);
|
||||||
|
return function() { watcher.cancelWatch(); };
|
||||||
|
};
|
||||||
|
|
||||||
|
function InterpolationPartsWatcher(interpolationParts, scope, listener, objectEquality) {
|
||||||
|
this.interpolationParts = interpolationParts;
|
||||||
|
this.scope = scope;
|
||||||
|
this.previousResult = (void 0);
|
||||||
|
this.listener = listener;
|
||||||
|
var self = this;
|
||||||
|
this.expressionFnsWatcher = scope['$watchGroup'](interpolationParts.expressionFns, function(newExpressionValues, oldExpressionValues) {
|
||||||
|
self.watchListener(newExpressionValues, oldExpressionValues);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
InterpolationPartsWatcher.prototype.watchListener = function watchListener(newExpressionValues, oldExpressionValues) {
|
||||||
|
var result = this.interpolationParts.getResult(newExpressionValues);
|
||||||
|
if (isFunction(this.listener)) {
|
||||||
|
this.listener.call(null, result, newExpressionValues === oldExpressionValues ? result : this.previousResult, this.scope);
|
||||||
|
}
|
||||||
|
this.previousResult = result;
|
||||||
|
};
|
||||||
|
|
||||||
|
InterpolationPartsWatcher.prototype.cancelWatch = function cancelWatch() {
|
||||||
|
this.expressionFnsWatcher();
|
||||||
|
};
|
||||||
|
|
||||||
|
// NOTE: ADVANCED_OPTIMIZATIONS mode.
|
||||||
|
//
|
||||||
|
// This file is compiled with Closure compiler's ADVANCED_OPTIMIZATIONS flag! Be wary of using
|
||||||
|
// constructs incompatible with that mode.
|
||||||
|
|
||||||
|
/* global $interpolateMinErr: false */
|
||||||
|
/* global indexToLineAndColumn: false */
|
||||||
|
/* global InterpolationParts: false */
|
||||||
|
/* global PluralMessage: false */
|
||||||
|
/* global SelectMessage: false */
|
||||||
|
/* global subtractOffset: false */
|
||||||
|
|
||||||
|
// The params src and dst are exactly one of two types: NestedParserState or MessageFormatParser.
|
||||||
|
// This function is fully optimized by V8. (inspect via IRHydra or --trace-deopt.)
|
||||||
|
// The idea behind writing it this way is to avoid repeating oneself. This is the ONE place where
|
||||||
|
// the parser state that is saved/restored when parsing nested mustaches is specified.
|
||||||
|
function copyNestedParserState(src, dst) {
|
||||||
|
dst.expressionFn = src.expressionFn;
|
||||||
|
dst.expressionMinusOffsetFn = src.expressionMinusOffsetFn;
|
||||||
|
dst.pluralOffset = src.pluralOffset;
|
||||||
|
dst.choices = src.choices;
|
||||||
|
dst.choiceKey = src.choiceKey;
|
||||||
|
dst.interpolationParts = src.interpolationParts;
|
||||||
|
dst.ruleChoiceKeyword = src.ruleChoiceKeyword;
|
||||||
|
dst.msgStartIndex = src.msgStartIndex;
|
||||||
|
dst.expressionStartIndex = src.expressionStartIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
function NestedParserState(parser) {
|
||||||
|
copyNestedParserState(parser, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function MessageFormatParser(text, startIndex, $parse, pluralCat, stringifier,
|
||||||
|
mustHaveExpression, trustedContext, allOrNothing) {
|
||||||
|
this.text = text;
|
||||||
|
this.index = startIndex || 0;
|
||||||
|
this.$parse = $parse;
|
||||||
|
this.pluralCat = pluralCat;
|
||||||
|
this.stringifier = stringifier;
|
||||||
|
this.mustHaveExpression = !!mustHaveExpression;
|
||||||
|
this.trustedContext = trustedContext;
|
||||||
|
this.allOrNothing = !!allOrNothing;
|
||||||
|
this.expressionFn = null;
|
||||||
|
this.expressionMinusOffsetFn = null;
|
||||||
|
this.pluralOffset = null;
|
||||||
|
this.choices = null;
|
||||||
|
this.choiceKey = null;
|
||||||
|
this.interpolationParts = null;
|
||||||
|
this.msgStartIndex = null;
|
||||||
|
this.nestedStateStack = [];
|
||||||
|
this.parsedFn = null;
|
||||||
|
this.rule = null;
|
||||||
|
this.ruleStack = null;
|
||||||
|
this.ruleChoiceKeyword = null;
|
||||||
|
this.interpNestLevel = null;
|
||||||
|
this.expressionStartIndex = null;
|
||||||
|
this.stringStartIndex = null;
|
||||||
|
this.stringQuote = null;
|
||||||
|
this.stringInterestsRe = null;
|
||||||
|
this.angularOperatorStack = null;
|
||||||
|
this.textPart = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// preserve v8 optimization.
|
||||||
|
var EMPTY_STATE = new NestedParserState(new MessageFormatParser(
|
||||||
|
/* text= */ '', /* startIndex= */ 0, /* $parse= */ null, /* pluralCat= */ null, /* stringifier= */ null,
|
||||||
|
/* mustHaveExpression= */ false, /* trustedContext= */ null, /* allOrNothing */ false));
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.pushState = function pushState() {
|
||||||
|
this.nestedStateStack.push(new NestedParserState(this));
|
||||||
|
copyNestedParserState(EMPTY_STATE, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.popState = function popState() {
|
||||||
|
if (this.nestedStateStack.length === 0) {
|
||||||
|
this.errorInParseLogic();
|
||||||
|
}
|
||||||
|
var previousState = this.nestedStateStack.pop();
|
||||||
|
copyNestedParserState(previousState, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Oh my JavaScript! Who knew you couldn't match a regex at a specific
|
||||||
|
// location in a string but will always search forward?!
|
||||||
|
// Apparently you'll be growing this ability via the sticky flag (y) in
|
||||||
|
// ES6. I'll just to work around you for now.
|
||||||
|
MessageFormatParser.prototype.matchRe = function matchRe(re, search) {
|
||||||
|
re.lastIndex = this.index;
|
||||||
|
var match = re.exec(this.text);
|
||||||
|
if (match != null && (search === true || (match.index == this.index))) {
|
||||||
|
this.index = re.lastIndex;
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.searchRe = function searchRe(re) {
|
||||||
|
return this.matchRe(re, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.consumeRe = function consumeRe(re) {
|
||||||
|
// Without the sticky flag, we can't use the .test() method to consume a
|
||||||
|
// match at the current index. Instead, we'll use the slower .exec() method
|
||||||
|
// and verify match.index.
|
||||||
|
return !!this.matchRe(re);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Run through our grammar avoiding deeply nested function call chains.
|
||||||
|
MessageFormatParser.prototype.run = function run(initialRule) {
|
||||||
|
this.ruleStack = [initialRule];
|
||||||
|
do {
|
||||||
|
this.rule = this.ruleStack.pop();
|
||||||
|
while (this.rule) {
|
||||||
|
this.rule();
|
||||||
|
}
|
||||||
|
this.assertRuleOrNull(this.rule);
|
||||||
|
} while (this.ruleStack.length > 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.errorInParseLogic = function errorInParseLogic() {
|
||||||
|
throw $interpolateMinErr('logicbug',
|
||||||
|
'The messageformat parser has encountered an internal error. Please file a github issue against the AngularJS project and provide this message text that triggers the bug. Text: “{0}”',
|
||||||
|
this.text);
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.assertRuleOrNull = function assertRuleOrNull(rule) {
|
||||||
|
if (rule === void 0) {
|
||||||
|
this.errorInParseLogic();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var NEXT_WORD_RE = /\s*(\w+)\s*/g;
|
||||||
|
MessageFormatParser.prototype.errorExpecting = function errorExpecting() {
|
||||||
|
// What was wrong with the syntax? Unsupported type, missing comma, or something else?
|
||||||
|
var match = this.matchRe(NEXT_WORD_RE), position;
|
||||||
|
if (match == null) {
|
||||||
|
position = indexToLineAndColumn(this.text, this.index);
|
||||||
|
throw $interpolateMinErr('reqarg',
|
||||||
|
'Expected one of “plural” or “select” at line {0}, column {1} of text “{2}”',
|
||||||
|
position.line, position.column, this.text);
|
||||||
|
}
|
||||||
|
var word = match[1];
|
||||||
|
if (word == "select" || word == "plural") {
|
||||||
|
position = indexToLineAndColumn(this.text, this.index);
|
||||||
|
throw $interpolateMinErr('reqcomma',
|
||||||
|
'Expected a comma after the keyword “{0}” at line {1}, column {2} of text “{3}”',
|
||||||
|
word, position.line, position.column, this.text);
|
||||||
|
} else {
|
||||||
|
position = indexToLineAndColumn(this.text, this.index);
|
||||||
|
throw $interpolateMinErr('unknarg',
|
||||||
|
'Unsupported keyword “{0}” at line {0}, column {1}. Only “plural” and “select” are currently supported. Text: “{3}”',
|
||||||
|
word, position.line, position.column, this.text);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var STRING_START_RE = /['"]/g;
|
||||||
|
MessageFormatParser.prototype.ruleString = function ruleString() {
|
||||||
|
var match = this.matchRe(STRING_START_RE);
|
||||||
|
if (match == null) {
|
||||||
|
var position = indexToLineAndColumn(this.text, this.index);
|
||||||
|
throw $interpolateMinErr('wantstring',
|
||||||
|
'Expected the beginning of a string at line {0}, column {1} in text “{2}”',
|
||||||
|
position.line, position.column, this.text);
|
||||||
|
}
|
||||||
|
this.startStringAtMatch(match);
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.startStringAtMatch = function startStringAtMatch(match) {
|
||||||
|
this.stringStartIndex = match.index;
|
||||||
|
this.stringQuote = match[0];
|
||||||
|
this.stringInterestsRe = this.stringQuote == "'" ? SQUOTED_STRING_INTEREST_RE : DQUOTED_STRING_INTEREST_RE;
|
||||||
|
this.rule = this.ruleInsideString;
|
||||||
|
};
|
||||||
|
|
||||||
|
var SQUOTED_STRING_INTEREST_RE = /\\(?:\\|'|u[0-9A-Fa-f]{4}|x[0-9A-Fa-f]{2}|[0-7]{3}|\r\n|\n|[\s\S])|'/g;
|
||||||
|
var DQUOTED_STRING_INTEREST_RE = /\\(?:\\|"|u[0-9A-Fa-f]{4}|x[0-9A-Fa-f]{2}|[0-7]{3}|\r\n|\n|[\s\S])|"/g;
|
||||||
|
MessageFormatParser.prototype.ruleInsideString = function ruleInsideString() {
|
||||||
|
var match = this.searchRe(this.stringInterestsRe);
|
||||||
|
if (match == null) {
|
||||||
|
var position = indexToLineAndColumn(this.text, this.stringStartIndex);
|
||||||
|
throw $interpolateMinErr('untermstr',
|
||||||
|
'The string beginning at line {0}, column {1} is unterminated in text “{2}”',
|
||||||
|
position.line, position.column, this.text);
|
||||||
|
}
|
||||||
|
var chars = match[0];
|
||||||
|
if (match == this.stringQuote) {
|
||||||
|
this.rule = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var PLURAL_OR_SELECT_ARG_TYPE_RE = /\s*(plural|select)\s*,\s*/g;
|
||||||
|
MessageFormatParser.prototype.rulePluralOrSelect = function rulePluralOrSelect() {
|
||||||
|
var match = this.searchRe(PLURAL_OR_SELECT_ARG_TYPE_RE);
|
||||||
|
if (match == null) {
|
||||||
|
this.errorExpecting();
|
||||||
|
}
|
||||||
|
var argType = match[1];
|
||||||
|
switch (argType) {
|
||||||
|
case "plural": this.rule = this.rulePluralStyle; break;
|
||||||
|
case "select": this.rule = this.ruleSelectStyle; break;
|
||||||
|
default: this.errorInParseLogic();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.rulePluralStyle = function rulePluralStyle() {
|
||||||
|
this.choices = Object.create(null);
|
||||||
|
this.ruleChoiceKeyword = this.rulePluralValueOrKeyword;
|
||||||
|
this.rule = this.rulePluralOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.ruleSelectStyle = function ruleSelectStyle() {
|
||||||
|
this.choices = Object.create(null);
|
||||||
|
this.ruleChoiceKeyword = this.ruleSelectKeyword;
|
||||||
|
this.rule = this.ruleSelectKeyword;
|
||||||
|
};
|
||||||
|
|
||||||
|
var NUMBER_RE = /[0]|(?:[1-9][0-9]*)/g;
|
||||||
|
var PLURAL_OFFSET_RE = new RegExp("\\s*offset\\s*:\\s*(" + NUMBER_RE.source + ")", "g");
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.rulePluralOffset = function rulePluralOffset() {
|
||||||
|
var match = this.matchRe(PLURAL_OFFSET_RE);
|
||||||
|
this.pluralOffset = (match == null) ? 0 : parseInt(match[1], 10);
|
||||||
|
this.expressionMinusOffsetFn = subtractOffset(this.expressionFn, this.pluralOffset);
|
||||||
|
this.rule = this.rulePluralValueOrKeyword;
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.assertChoiceKeyIsNew = function assertChoiceKeyIsNew(choiceKey, index) {
|
||||||
|
if (this.choices[choiceKey] !== void 0) {
|
||||||
|
var position = indexToLineAndColumn(this.text, index);
|
||||||
|
throw $interpolateMinErr('dupvalue',
|
||||||
|
'The choice “{0}” is specified more than once. Duplicate key is at line {1}, column {2} in text “{3}”',
|
||||||
|
choiceKey, position.line, position.column, this.text);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var SELECT_KEYWORD = /\s*(\w+)/g;
|
||||||
|
MessageFormatParser.prototype.ruleSelectKeyword = function ruleSelectKeyword() {
|
||||||
|
var match = this.matchRe(SELECT_KEYWORD);
|
||||||
|
if (match == null) {
|
||||||
|
this.parsedFn = new SelectMessage(this.expressionFn, this.choices).parsedFn;
|
||||||
|
this.rule = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.choiceKey = match[1];
|
||||||
|
this.assertChoiceKeyIsNew(this.choiceKey, match.index);
|
||||||
|
this.rule = this.ruleMessageText;
|
||||||
|
};
|
||||||
|
|
||||||
|
var EXPLICIT_VALUE_OR_KEYWORD_RE = new RegExp("\\s*(?:(?:=(" + NUMBER_RE.source + "))|(\\w+))", "g");
|
||||||
|
MessageFormatParser.prototype.rulePluralValueOrKeyword = function rulePluralValueOrKeyword() {
|
||||||
|
var match = this.matchRe(EXPLICIT_VALUE_OR_KEYWORD_RE);
|
||||||
|
if (match == null) {
|
||||||
|
this.parsedFn = new PluralMessage(this.expressionFn, this.choices, this.pluralOffset, this.pluralCat).parsedFn;
|
||||||
|
this.rule = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (match[1] != null) {
|
||||||
|
this.choiceKey = parseInt(match[1], 10);
|
||||||
|
} else {
|
||||||
|
this.choiceKey = match[2];
|
||||||
|
}
|
||||||
|
this.assertChoiceKeyIsNew(this.choiceKey, match.index);
|
||||||
|
this.rule = this.ruleMessageText;
|
||||||
|
};
|
||||||
|
|
||||||
|
var BRACE_OPEN_RE = /\s*{/g;
|
||||||
|
var BRACE_CLOSE_RE = /}/g;
|
||||||
|
MessageFormatParser.prototype.ruleMessageText = function ruleMessageText() {
|
||||||
|
if (!this.consumeRe(BRACE_OPEN_RE)) {
|
||||||
|
var position = indexToLineAndColumn(this.text, this.index);
|
||||||
|
throw $interpolateMinErr('reqopenbrace',
|
||||||
|
'The plural choice “{0}” must be followed by a message in braces at line {1}, column {2} in text “{3}”',
|
||||||
|
this.choiceKey, position.line, position.column, this.text);
|
||||||
|
}
|
||||||
|
this.msgStartIndex = this.index;
|
||||||
|
this.interpolationParts = new InterpolationParts(this.trustedContext, this.allOrNothing);
|
||||||
|
this.rule = this.ruleInInterpolationOrMessageText;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Note: Since "\" is used as an escape character, don't allow it to be part of the
|
||||||
|
// startSymbol/endSymbol when I add the feature to allow them to be redefined.
|
||||||
|
var INTERP_OR_END_MESSAGE_RE = /\\.|{{|}/g;
|
||||||
|
var INTERP_OR_PLURALVALUE_OR_END_MESSAGE_RE = /\\.|{{|#|}/g;
|
||||||
|
var ESCAPE_OR_MUSTACHE_BEGIN_RE = /\\.|{{/g;
|
||||||
|
MessageFormatParser.prototype.advanceInInterpolationOrMessageText = function advanceInInterpolationOrMessageText() {
|
||||||
|
var currentIndex = this.index, match, re;
|
||||||
|
if (this.ruleChoiceKeyword == null) { // interpolation
|
||||||
|
match = this.searchRe(ESCAPE_OR_MUSTACHE_BEGIN_RE);
|
||||||
|
if (match == null) { // End of interpolation text. Nothing more to process.
|
||||||
|
this.textPart = this.text.substring(currentIndex);
|
||||||
|
this.index = this.text.length;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match = this.searchRe(this.ruleChoiceKeyword == this.rulePluralValueOrKeyword ?
|
||||||
|
INTERP_OR_PLURALVALUE_OR_END_MESSAGE_RE : INTERP_OR_END_MESSAGE_RE);
|
||||||
|
if (match == null) {
|
||||||
|
var position = indexToLineAndColumn(this.text, this.msgStartIndex);
|
||||||
|
throw $interpolateMinErr('reqendbrace',
|
||||||
|
'The plural/select choice “{0}” message starting at line {1}, column {2} does not have an ending closing brace. Text “{3}”',
|
||||||
|
this.choiceKey, position.line, position.column, this.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// match is non-null.
|
||||||
|
var token = match[0];
|
||||||
|
this.textPart = this.text.substring(currentIndex, match.index);
|
||||||
|
return token;
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.ruleInInterpolationOrMessageText = function ruleInInterpolationOrMessageText() {
|
||||||
|
var currentIndex = this.index;
|
||||||
|
var token = this.advanceInInterpolationOrMessageText();
|
||||||
|
if (token == null) {
|
||||||
|
// End of interpolation text. Nothing more to process.
|
||||||
|
this.index = this.text.length;
|
||||||
|
this.interpolationParts.addText(this.text.substring(currentIndex));
|
||||||
|
this.rule = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (token[0] == "\\") {
|
||||||
|
// unescape next character and continue
|
||||||
|
this.interpolationParts.addText(this.textPart + token[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.interpolationParts.addText(this.textPart);
|
||||||
|
if (token == "{{") {
|
||||||
|
this.pushState();
|
||||||
|
this.ruleStack.push(this.ruleEndMustacheInInterpolationOrMessage);
|
||||||
|
this.rule = this.ruleEnteredMustache;
|
||||||
|
} else if (token == "}") {
|
||||||
|
this.choices[this.choiceKey] = this.interpolationParts.toParsedFn(/*mustHaveExpression=*/false, this.text);
|
||||||
|
this.rule = this.ruleChoiceKeyword;
|
||||||
|
} else if (token == "#") {
|
||||||
|
this.interpolationParts.addExpressionFn(this.expressionMinusOffsetFn);
|
||||||
|
} else {
|
||||||
|
this.errorInParseLogic();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.ruleInterpolate = function ruleInterpolate() {
|
||||||
|
this.interpolationParts = new InterpolationParts(this.trustedContext, this.allOrNothing);
|
||||||
|
this.rule = this.ruleInInterpolation;
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.ruleInInterpolation = function ruleInInterpolation() {
|
||||||
|
var currentIndex = this.index;
|
||||||
|
var match = this.searchRe(ESCAPE_OR_MUSTACHE_BEGIN_RE);
|
||||||
|
if (match == null) {
|
||||||
|
// End of interpolation text. Nothing more to process.
|
||||||
|
this.index = this.text.length;
|
||||||
|
this.interpolationParts.addText(this.text.substring(currentIndex));
|
||||||
|
this.parsedFn = this.interpolationParts.toParsedFn(this.mustHaveExpression, this.text);
|
||||||
|
this.rule = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var token = match[0];
|
||||||
|
if (token[0] == "\\") {
|
||||||
|
// unescape next character and continue
|
||||||
|
this.interpolationParts.addText(this.text.substring(currentIndex, match.index) + token[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.interpolationParts.addText(this.text.substring(currentIndex, match.index));
|
||||||
|
this.pushState();
|
||||||
|
this.ruleStack.push(this.ruleInterpolationEndMustache);
|
||||||
|
this.rule = this.ruleEnteredMustache;
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.ruleInterpolationEndMustache = function ruleInterpolationEndMustache() {
|
||||||
|
var expressionFn = this.parsedFn;
|
||||||
|
this.popState();
|
||||||
|
this.interpolationParts.addExpressionFn(expressionFn);
|
||||||
|
this.rule = this.ruleInInterpolation;
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.ruleEnteredMustache = function ruleEnteredMustache() {
|
||||||
|
this.parsedFn = null;
|
||||||
|
this.ruleStack.push(this.ruleEndMustache);
|
||||||
|
this.rule = this.ruleAngularExpression;
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.ruleEndMustacheInInterpolationOrMessage = function ruleEndMustacheInInterpolationOrMessage() {
|
||||||
|
var expressionFn = this.parsedFn;
|
||||||
|
this.popState();
|
||||||
|
this.interpolationParts.addExpressionFn(expressionFn);
|
||||||
|
this.rule = this.ruleInInterpolationOrMessageText;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var INTERP_END_RE = /\s*}}/g;
|
||||||
|
MessageFormatParser.prototype.ruleEndMustache = function ruleEndMustache() {
|
||||||
|
var match = this.matchRe(INTERP_END_RE);
|
||||||
|
if (match == null) {
|
||||||
|
var position = indexToLineAndColumn(this.text, this.index);
|
||||||
|
throw $interpolateMinErr('reqendinterp',
|
||||||
|
'Expecting end of interpolation symbol, “{0}”, at line {1}, column {2} in text “{3}”',
|
||||||
|
'}}', position.line, position.column, this.text);
|
||||||
|
}
|
||||||
|
if (this.parsedFn == null) {
|
||||||
|
// If we parsed a MessageFormat extension, (e.g. select/plural today, maybe more some other
|
||||||
|
// day), then the result *has* to be a string and those rules would have already set
|
||||||
|
// this.parsedFn. If there was no MessageFormat extension, then there is no requirement to
|
||||||
|
// stringify the result and parsedFn isn't set. We set it here. While we could have set it
|
||||||
|
// unconditionally when exiting the Angular expression, I intend for us to not just replace
|
||||||
|
// $interpolate, but also to replace $parse in a future version (so ng-bind can work), and in
|
||||||
|
// such a case we do not want to unnecessarily stringify something if it's not going to be used
|
||||||
|
// in a string context.
|
||||||
|
this.parsedFn = this.$parse(this.expressionFn, this.stringifier);
|
||||||
|
this.parsedFn['exp'] = this.expressionFn['exp']; // Needed to pretend to be $interpolate for tests copied from interpolateSpec.js
|
||||||
|
this.parsedFn['expressions'] = this.expressionFn['expressions']; // Require this to call $compile.$$addBindingInfo() which allows Protractor to find elements by binding.
|
||||||
|
}
|
||||||
|
this.rule = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageFormatParser.prototype.ruleAngularExpression = function ruleAngularExpression() {
|
||||||
|
this.angularOperatorStack = [];
|
||||||
|
this.expressionStartIndex = this.index;
|
||||||
|
this.rule = this.ruleInAngularExpression;
|
||||||
|
};
|
||||||
|
|
||||||
|
function getEndOperator(opBegin) {
|
||||||
|
switch (opBegin) {
|
||||||
|
case "{": return "}";
|
||||||
|
case "[": return "]";
|
||||||
|
case "(": return ")";
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBeginOperator(opEnd) {
|
||||||
|
switch (opEnd) {
|
||||||
|
case "}": return "{";
|
||||||
|
case "]": return "[";
|
||||||
|
case ")": return "(";
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(chirayu): The interpolation endSymbol must also be accounted for. It
|
||||||
|
// just so happens that "}" is an operator so it's in the list below. But we
|
||||||
|
// should support any other type of start/end interpolation symbol.
|
||||||
|
var INTERESTING_OPERATORS_RE = /[[\]{}()'",]/g;
|
||||||
|
MessageFormatParser.prototype.ruleInAngularExpression = function ruleInAngularExpression() {
|
||||||
|
var startIndex = this.index;
|
||||||
|
var match = this.searchRe(INTERESTING_OPERATORS_RE);
|
||||||
|
var position;
|
||||||
|
if (match == null) {
|
||||||
|
if (this.angularOperatorStack.length === 0) {
|
||||||
|
// This is the end of the Angular expression so this is actually a
|
||||||
|
// success. Note that when inside an interpolation, this means we even
|
||||||
|
// consumed the closing interpolation symbols if they were curlies. This
|
||||||
|
// is NOT an error at this point but will become an error further up the
|
||||||
|
// stack when the part that saw the opening curlies is unable to find the
|
||||||
|
// closing ones.
|
||||||
|
this.index = this.text.length;
|
||||||
|
this.expressionFn = this.$parse(this.text.substring(this.expressionStartIndex, this.index));
|
||||||
|
// Needed to pretend to be $interpolate for tests copied from interpolateSpec.js
|
||||||
|
this.expressionFn['exp'] = this.text.substring(this.expressionStartIndex, this.index);
|
||||||
|
this.expressionFn['expressions'] = this.expressionFn['expressions'];
|
||||||
|
this.rule = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var innermostOperator = this.angularOperatorStack[0];
|
||||||
|
throw $interpolateMinErr('badexpr',
|
||||||
|
'Unexpected end of Angular expression. Expecting operator “{0}” at the end of the text “{1}”',
|
||||||
|
this.getEndOperator(innermostOperator), this.text);
|
||||||
|
}
|
||||||
|
var operator = match[0];
|
||||||
|
if (operator == "'" || operator == '"') {
|
||||||
|
this.ruleStack.push(this.ruleInAngularExpression);
|
||||||
|
this.startStringAtMatch(match);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (operator == ",") {
|
||||||
|
if (this.trustedContext) {
|
||||||
|
position = indexToLineAndColumn(this.text, this.index);
|
||||||
|
throw $interpolateMinErr('unsafe',
|
||||||
|
'Use of select/plural MessageFormat syntax is currently disallowed in a secure context ({0}). At line {1}, column {2} of text “{3}”',
|
||||||
|
this.trustedContext, position.line, position.column, this.text);
|
||||||
|
}
|
||||||
|
// only the top level comma has relevance.
|
||||||
|
if (this.angularOperatorStack.length === 0) {
|
||||||
|
// todo: does this need to be trimmed?
|
||||||
|
this.expressionFn = this.$parse(this.text.substring(this.expressionStartIndex, match.index));
|
||||||
|
// Needed to pretend to be $interpolate for tests copied from interpolateSpec.js
|
||||||
|
this.expressionFn['exp'] = this.text.substring(this.expressionStartIndex, match.index);
|
||||||
|
this.expressionFn['expressions'] = this.expressionFn['expressions'];
|
||||||
|
this.rule = null;
|
||||||
|
this.rule = this.rulePluralOrSelect;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (getEndOperator(operator) != null) {
|
||||||
|
this.angularOperatorStack.unshift(operator);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var beginOperator = getBeginOperator(operator);
|
||||||
|
if (beginOperator == null) {
|
||||||
|
this.errorInParseLogic();
|
||||||
|
}
|
||||||
|
if (this.angularOperatorStack.length > 0) {
|
||||||
|
if (beginOperator == this.angularOperatorStack[0]) {
|
||||||
|
this.angularOperatorStack.shift();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
position = indexToLineAndColumn(this.text, this.index);
|
||||||
|
throw $interpolateMinErr('badexpr',
|
||||||
|
'Unexpected operator “{0}” at line {1}, column {2} in text. Was expecting “{3}”. Text: “{4}”',
|
||||||
|
operator, position.line, position.column, getEndOperator(this.angularOperatorStack[0]), this.text);
|
||||||
|
}
|
||||||
|
// We are trying to pop off the operator stack but there really isn't anything to pop off.
|
||||||
|
this.index = match.index;
|
||||||
|
this.expressionFn = this.$parse(this.text.substring(this.expressionStartIndex, this.index));
|
||||||
|
// Needed to pretend to be $interpolate for tests copied from interpolateSpec.js
|
||||||
|
this.expressionFn['exp'] = this.text.substring(this.expressionStartIndex, this.index);
|
||||||
|
this.expressionFn['expressions'] = this.expressionFn['expressions'];
|
||||||
|
this.rule = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// NOTE: ADVANCED_OPTIMIZATIONS mode.
|
||||||
|
//
|
||||||
|
// This file is compiled with Closure compiler's ADVANCED_OPTIMIZATIONS flag! Be wary of using
|
||||||
|
// constructs incompatible with that mode.
|
||||||
|
|
||||||
|
/* global $interpolateMinErr: false */
|
||||||
|
/* global MessageFormatParser: false */
|
||||||
|
/* global stringify: false */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc service
|
||||||
|
* @name $$messageFormat
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Angular internal service to recognize MessageFormat extensions in interpolation expressions.
|
||||||
|
* For more information, see:
|
||||||
|
* https://docs.google.com/a/google.com/document/d/1pbtW2yvtmFBikfRrJd8VAsabiFkKezmYZ_PbgdjQOVU/edit
|
||||||
|
*
|
||||||
|
* ## Example
|
||||||
|
*
|
||||||
|
* <example name="ngMessageFormat-example" module="msgFmtExample" deps="angular-message-format.min.js">
|
||||||
|
* <file name="index.html">
|
||||||
|
* <div ng-controller="AppController">
|
||||||
|
* <button ng-click="decreaseRecipients()" id="decreaseRecipients">decreaseRecipients</button><br>
|
||||||
|
* <span>{{recipients.length, plural, offset:1
|
||||||
|
* =0 {{{sender.name}} gave no gifts (\#=#)}
|
||||||
|
* =1 {{{sender.name}} gave one gift to {{recipients[0].name}} (\#=#)}
|
||||||
|
* one {{{sender.name}} gave {{recipients[0].name}} and one other person a gift (\#=#)}
|
||||||
|
* other {{{sender.name}} gave {{recipients[0].name}} and # other people a gift (\#=#)}
|
||||||
|
* }}</span>
|
||||||
|
* </div>
|
||||||
|
* </file>
|
||||||
|
*
|
||||||
|
* <file name="script.js">
|
||||||
|
* function Person(name, gender) {
|
||||||
|
* this.name = name;
|
||||||
|
* this.gender = gender;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* var alice = new Person("Alice", "female"),
|
||||||
|
* bob = new Person("Bob", "male"),
|
||||||
|
* charlie = new Person("Charlie", "male"),
|
||||||
|
* harry = new Person("Harry Potter", "male");
|
||||||
|
*
|
||||||
|
* angular.module('msgFmtExample', ['ngMessageFormat'])
|
||||||
|
* .controller('AppController', ['$scope', function($scope) {
|
||||||
|
* $scope.recipients = [alice, bob, charlie];
|
||||||
|
* $scope.sender = harry;
|
||||||
|
* $scope.decreaseRecipients = function() {
|
||||||
|
* --$scope.recipients.length;
|
||||||
|
* };
|
||||||
|
* }]);
|
||||||
|
* </file>
|
||||||
|
*
|
||||||
|
* <file name="protractor.js" type="protractor">
|
||||||
|
* describe('MessageFormat plural', function() {
|
||||||
|
* it('should pluralize initial values', function() {
|
||||||
|
* var messageElem = element(by.binding('recipients.length')), decreaseRecipientsBtn = element(by.id('decreaseRecipients'));
|
||||||
|
* expect(messageElem.getText()).toEqual('Harry Potter gave Alice and 2 other people a gift (#=2)');
|
||||||
|
* decreaseRecipientsBtn.click();
|
||||||
|
* expect(messageElem.getText()).toEqual('Harry Potter gave Alice and one other person a gift (#=1)');
|
||||||
|
* decreaseRecipientsBtn.click();
|
||||||
|
* expect(messageElem.getText()).toEqual('Harry Potter gave one gift to Alice (#=0)');
|
||||||
|
* decreaseRecipientsBtn.click();
|
||||||
|
* expect(messageElem.getText()).toEqual('Harry Potter gave no gifts (#=-1)');
|
||||||
|
* });
|
||||||
|
* });
|
||||||
|
* </file>
|
||||||
|
* </example>
|
||||||
|
*/
|
||||||
|
var $$MessageFormatFactory = ['$parse', '$locale', '$sce', '$exceptionHandler', function $$messageFormat(
|
||||||
|
$parse, $locale, $sce, $exceptionHandler) {
|
||||||
|
|
||||||
|
function getStringifier(trustedContext, allOrNothing, text) {
|
||||||
|
return function stringifier(value) {
|
||||||
|
try {
|
||||||
|
value = trustedContext ? $sce['getTrusted'](trustedContext, value) : $sce['valueOf'](value);
|
||||||
|
return allOrNothing && (value === void 0) ? value : stringify(value);
|
||||||
|
} catch (err) {
|
||||||
|
$exceptionHandler($interpolateMinErr['interr'](text, err));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {
|
||||||
|
var stringifier = getStringifier(trustedContext, allOrNothing, text);
|
||||||
|
var parser = new MessageFormatParser(text, 0, $parse, $locale['pluralCat'], stringifier,
|
||||||
|
mustHaveExpression, trustedContext, allOrNothing);
|
||||||
|
parser.run(parser.ruleInterpolate);
|
||||||
|
return parser.parsedFn;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
'interpolate': interpolate
|
||||||
|
};
|
||||||
|
}];
|
||||||
|
|
||||||
|
var $$interpolateDecorator = ['$$messageFormat', '$delegate', function $$interpolateDecorator($$messageFormat, $interpolate) {
|
||||||
|
if ($interpolate['startSymbol']() != "{{" || $interpolate['endSymbol']() != "}}") {
|
||||||
|
throw $interpolateMinErr('nochgmustache', 'angular-message-format.js currently does not allow you to use custom start and end symbols for interpolation.');
|
||||||
|
}
|
||||||
|
var interpolate = $$messageFormat['interpolate'];
|
||||||
|
interpolate['startSymbol'] = $interpolate['startSymbol'];
|
||||||
|
interpolate['endSymbol'] = $interpolate['endSymbol'];
|
||||||
|
return interpolate;
|
||||||
|
}];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc module
|
||||||
|
* @name ngMessageFormat
|
||||||
|
* @packageName angular-message-format
|
||||||
|
* @description
|
||||||
|
*/
|
||||||
|
var module = window['angular']['module']('ngMessageFormat', ['ng']);
|
||||||
|
module['factory']('$$messageFormat', $$MessageFormatFactory);
|
||||||
|
module['config'](['$provide', function($provide) {
|
||||||
|
$provide['decorator']('$interpolate', $$interpolateDecorator);
|
||||||
|
}]);
|
||||||
|
|
||||||
|
|
||||||
|
})(window, window.angular);
|
615
xstatic/pkg/angular/data/angular-messages.js
vendored
615
xstatic/pkg/angular/data/angular-messages.js
vendored
@ -1,10 +1,18 @@
|
|||||||
/**
|
/**
|
||||||
* @license AngularJS v1.3.18
|
* @license AngularJS v1.4.10
|
||||||
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
* (c) 2010-2015 Google, Inc. http://angularjs.org
|
||||||
* License: MIT
|
* License: MIT
|
||||||
*/
|
*/
|
||||||
(function(window, angular, undefined) {'use strict';
|
(function(window, angular, undefined) {'use strict';
|
||||||
|
|
||||||
|
/* jshint ignore:start */
|
||||||
|
// this code is in the core, but not in angular-messages.js
|
||||||
|
var isArray = angular.isArray;
|
||||||
|
var forEach = angular.forEach;
|
||||||
|
var isString = angular.isString;
|
||||||
|
var jqLite = angular.element;
|
||||||
|
/* jshint ignore:end */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc module
|
* @ngdoc module
|
||||||
* @name ngMessages
|
* @name ngMessages
|
||||||
@ -17,47 +25,77 @@
|
|||||||
* `ngMessage` directives are designed to handle the complexity, inheritance and priority
|
* `ngMessage` directives are designed to handle the complexity, inheritance and priority
|
||||||
* sequencing based on the order of how the messages are defined in the template.
|
* sequencing based on the order of how the messages are defined in the template.
|
||||||
*
|
*
|
||||||
* Currently, the ngMessages module only contains the code for the `ngMessages`
|
* Currently, the ngMessages module only contains the code for the `ngMessages`, `ngMessagesInclude`
|
||||||
* and `ngMessage` directives.
|
* `ngMessage` and `ngMessageExp` directives.
|
||||||
*
|
*
|
||||||
* # Usage
|
* # Usage
|
||||||
* The `ngMessages` directive listens on a key/value collection which is set on the ngMessages attribute.
|
* The `ngMessages` directive allows keys in a key/value collection to be associated with a child element
|
||||||
* Since the {@link ngModel ngModel} directive exposes an `$error` object, this error object can be
|
* (or 'message') that will show or hide based on the truthiness of that key's value in the collection. A common use
|
||||||
* used with `ngMessages` to display control error messages in an easier way than with just regular angular
|
* case for `ngMessages` is to display error messages for inputs using the `$error` object exposed by the
|
||||||
* template directives.
|
* {@link ngModel ngModel} directive.
|
||||||
|
*
|
||||||
|
* The child elements of the `ngMessages` directive are matched to the collection keys by a `ngMessage` or
|
||||||
|
* `ngMessageExp` directive. The value of these attributes must match a key in the collection that is provided by
|
||||||
|
* the `ngMessages` directive.
|
||||||
|
*
|
||||||
|
* Consider the following example, which illustrates a typical use case of `ngMessages`. Within the form `myForm` we
|
||||||
|
* have a text input named `myField` which is bound to the scope variable `field` using the {@link ngModel ngModel}
|
||||||
|
* directive.
|
||||||
|
*
|
||||||
|
* The `myField` field is a required input of type `email` with a maximum length of 15 characters.
|
||||||
*
|
*
|
||||||
* ```html
|
* ```html
|
||||||
* <form name="myForm">
|
* <form name="myForm">
|
||||||
* <input type="text" ng-model="field" name="myField" required minlength="5" />
|
* <label>
|
||||||
* <div ng-messages="myForm.myField.$error">
|
* Enter text:
|
||||||
* <div ng-message="required">You did not enter a field</div>
|
* <input type="email" ng-model="field" name="myField" required maxlength="15" />
|
||||||
* <div ng-message="minlength">The value entered is too short</div>
|
* </label>
|
||||||
|
* <div ng-messages="myForm.myField.$error" role="alert">
|
||||||
|
* <div ng-message="required">Please enter a value for this field.</div>
|
||||||
|
* <div ng-message="email">This field must be a valid email address.</div>
|
||||||
|
* <div ng-message="maxlength">This field can be at most 15 characters long.</div>
|
||||||
* </div>
|
* </div>
|
||||||
* </form>
|
* </form>
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* Now whatever key/value entries are present within the provided object (in this case `$error`) then
|
* In order to show error messages corresponding to `myField` we first create an element with an `ngMessages` attribute
|
||||||
* the ngMessages directive will render the inner first ngMessage directive (depending if the key values
|
* set to the `$error` object owned by the `myField` input in our `myForm` form.
|
||||||
* match the attribute value present on each ngMessage directive). In other words, if your errors
|
*
|
||||||
* object contains the following data:
|
* Within this element we then create separate elements for each of the possible errors that `myField` could have.
|
||||||
|
* The `ngMessage` attribute is used to declare which element(s) will appear for which error - for example,
|
||||||
|
* setting `ng-message="required"` specifies that this particular element should be displayed when there
|
||||||
|
* is no value present for the required field `myField` (because the key `required` will be `true` in the object
|
||||||
|
* `myForm.myField.$error`).
|
||||||
|
*
|
||||||
|
* ### Message order
|
||||||
|
*
|
||||||
|
* By default, `ngMessages` will only display one message for a particular key/value collection at any time. If more
|
||||||
|
* than one message (or error) key is currently true, then which message is shown is determined by the order of messages
|
||||||
|
* in the HTML template code (messages declared first are prioritised). This mechanism means the developer does not have
|
||||||
|
* to prioritise messages using custom JavaScript code.
|
||||||
|
*
|
||||||
|
* Given the following error object for our example (which informs us that the field `myField` currently has both the
|
||||||
|
* `required` and `email` errors):
|
||||||
*
|
*
|
||||||
* ```javascript
|
* ```javascript
|
||||||
* <!-- keep in mind that ngModel automatically sets these error flags -->
|
* <!-- keep in mind that ngModel automatically sets these error flags -->
|
||||||
* myField.$error = { minlength : true, required : false };
|
* myField.$error = { required : true, email: true, maxlength: false };
|
||||||
* ```
|
* ```
|
||||||
|
* The `required` message will be displayed to the user since it appears before the `email` message in the DOM.
|
||||||
|
* Once the user types a single character, the `required` message will disappear (since the field now has a value)
|
||||||
|
* but the `email` message will be visible because it is still applicable.
|
||||||
*
|
*
|
||||||
* Then the `required` message will be displayed first. When required is false then the `minlength` message
|
* ### Displaying multiple messages at the same time
|
||||||
* will be displayed right after (since these messages are ordered this way in the template HTML code).
|
|
||||||
* The prioritization of each message is determined by what order they're present in the DOM.
|
|
||||||
* Therefore, instead of having custom JavaScript code determine the priority of what errors are
|
|
||||||
* present before others, the presentation of the errors are handled within the template.
|
|
||||||
*
|
*
|
||||||
* By default, ngMessages will only display one error at a time. However, if you wish to display all
|
* While `ngMessages` will by default only display one error element at a time, the `ng-messages-multiple` attribute can
|
||||||
* messages then the `ng-messages-multiple` attribute flag can be used on the element containing the
|
* be applied to the `ngMessages` container element to cause it to display all applicable error messages at once:
|
||||||
* ngMessages directive to make this happen.
|
|
||||||
*
|
*
|
||||||
* ```html
|
* ```html
|
||||||
|
* <!-- attribute-style usage -->
|
||||||
* <div ng-messages="myForm.myField.$error" ng-messages-multiple>...</div>
|
* <div ng-messages="myForm.myField.$error" ng-messages-multiple>...</div>
|
||||||
|
*
|
||||||
|
* <!-- element-style usage -->
|
||||||
|
* <ng-messages for="myForm.myField.$error" multiple>...</ng-messages>
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* ## Reusing and Overriding Messages
|
* ## Reusing and Overriding Messages
|
||||||
@ -70,12 +108,15 @@
|
|||||||
* <div ng-message="required">This field is required</div>
|
* <div ng-message="required">This field is required</div>
|
||||||
* <div ng-message="minlength">This field is too short</div>
|
* <div ng-message="minlength">This field is too short</div>
|
||||||
* </script>
|
* </script>
|
||||||
* <div ng-messages="myForm.myField.$error" ng-messages-include="error-messages"></div>
|
*
|
||||||
|
* <div ng-messages="myForm.myField.$error" role="alert">
|
||||||
|
* <div ng-messages-include="error-messages"></div>
|
||||||
|
* </div>
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* However, including generic messages may not be useful enough to match all input fields, therefore,
|
* However, including generic messages may not be useful enough to match all input fields, therefore,
|
||||||
* `ngMessages` provides the ability to override messages defined in the remote template by redefining
|
* `ngMessages` provides the ability to override messages defined in the remote template by redefining
|
||||||
* then within the directive container.
|
* them within the directive container.
|
||||||
*
|
*
|
||||||
* ```html
|
* ```html
|
||||||
* <!-- a generic template of error messages known as "my-custom-messages" -->
|
* <!-- a generic template of error messages known as "my-custom-messages" -->
|
||||||
@ -85,19 +126,26 @@
|
|||||||
* </script>
|
* </script>
|
||||||
*
|
*
|
||||||
* <form name="myForm">
|
* <form name="myForm">
|
||||||
|
* <label>
|
||||||
|
* Email address
|
||||||
* <input type="email"
|
* <input type="email"
|
||||||
* id="email"
|
* id="email"
|
||||||
* name="myEmail"
|
* name="myEmail"
|
||||||
* ng-model="email"
|
* ng-model="email"
|
||||||
* minlength="5"
|
* minlength="5"
|
||||||
* required />
|
* required />
|
||||||
*
|
* </label>
|
||||||
* <div ng-messages="myForm.myEmail.$error" ng-messages-include="my-custom-messages">
|
* <!-- any ng-message elements that appear BEFORE the ng-messages-include will
|
||||||
|
* override the messages present in the ng-messages-include template -->
|
||||||
|
* <div ng-messages="myForm.myEmail.$error" role="alert">
|
||||||
* <!-- this required message has overridden the template message -->
|
* <!-- this required message has overridden the template message -->
|
||||||
* <div ng-message="required">You did not enter your email address</div>
|
* <div ng-message="required">You did not enter your email address</div>
|
||||||
*
|
*
|
||||||
* <!-- this is a brand new message and will appear last in the prioritization -->
|
* <!-- this is a brand new message and will appear last in the prioritization -->
|
||||||
* <div ng-message="email">Your email address is invalid</div>
|
* <div ng-message="email">Your email address is invalid</div>
|
||||||
|
*
|
||||||
|
* <!-- and here are the generic error messages -->
|
||||||
|
* <div ng-messages-include="my-custom-messages"></div>
|
||||||
* </div>
|
* </div>
|
||||||
* </form>
|
* </form>
|
||||||
* ```
|
* ```
|
||||||
@ -107,20 +155,80 @@
|
|||||||
* email addresses, date fields, autocomplete inputs, etc...), specialized error messages can be applied
|
* email addresses, date fields, autocomplete inputs, etc...), specialized error messages can be applied
|
||||||
* while more generic messages can be used to handle other, more general input errors.
|
* while more generic messages can be used to handle other, more general input errors.
|
||||||
*
|
*
|
||||||
|
* ## Dynamic Messaging
|
||||||
|
* ngMessages also supports using expressions to dynamically change key values. Using arrays and
|
||||||
|
* repeaters to list messages is also supported. This means that the code below will be able to
|
||||||
|
* fully adapt itself and display the appropriate message when any of the expression data changes:
|
||||||
|
*
|
||||||
|
* ```html
|
||||||
|
* <form name="myForm">
|
||||||
|
* <label>
|
||||||
|
* Email address
|
||||||
|
* <input type="email"
|
||||||
|
* name="myEmail"
|
||||||
|
* ng-model="email"
|
||||||
|
* minlength="5"
|
||||||
|
* required />
|
||||||
|
* </label>
|
||||||
|
* <div ng-messages="myForm.myEmail.$error" role="alert">
|
||||||
|
* <div ng-message="required">You did not enter your email address</div>
|
||||||
|
* <div ng-repeat="errorMessage in errorMessages">
|
||||||
|
* <!-- use ng-message-exp for a message whose key is given by an expression -->
|
||||||
|
* <div ng-message-exp="errorMessage.type">{{ errorMessage.text }}</div>
|
||||||
|
* </div>
|
||||||
|
* </div>
|
||||||
|
* </form>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The `errorMessage.type` expression can be a string value or it can be an array so
|
||||||
|
* that multiple errors can be associated with a single error message:
|
||||||
|
*
|
||||||
|
* ```html
|
||||||
|
* <label>
|
||||||
|
* Email address
|
||||||
|
* <input type="email"
|
||||||
|
* ng-model="data.email"
|
||||||
|
* name="myEmail"
|
||||||
|
* ng-minlength="5"
|
||||||
|
* ng-maxlength="100"
|
||||||
|
* required />
|
||||||
|
* </label>
|
||||||
|
* <div ng-messages="myForm.myEmail.$error" role="alert">
|
||||||
|
* <div ng-message-exp="'required'">You did not enter your email address</div>
|
||||||
|
* <div ng-message-exp="['minlength', 'maxlength']">
|
||||||
|
* Your email must be between 5 and 100 characters long
|
||||||
|
* </div>
|
||||||
|
* </div>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Feel free to use other structural directives such as ng-if and ng-switch to further control
|
||||||
|
* what messages are active and when. Be careful, if you place ng-message on the same element
|
||||||
|
* as these structural directives, Angular may not be able to determine if a message is active
|
||||||
|
* or not. Therefore it is best to place the ng-message on a child element of the structural
|
||||||
|
* directive.
|
||||||
|
*
|
||||||
|
* ```html
|
||||||
|
* <div ng-messages="myForm.myEmail.$error" role="alert">
|
||||||
|
* <div ng-if="showRequiredError">
|
||||||
|
* <div ng-message="required">Please enter something</div>
|
||||||
|
* </div>
|
||||||
|
* </div>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
* ## Animations
|
* ## Animations
|
||||||
* If the `ngAnimate` module is active within the application then both the `ngMessages` and
|
* If the `ngAnimate` module is active within the application then the `ngMessages`, `ngMessage` and
|
||||||
* `ngMessage` directives will trigger animations whenever any messages are added and removed
|
* `ngMessageExp` directives will trigger animations whenever any messages are added and removed from
|
||||||
* from the DOM by the `ngMessages` directive.
|
* the DOM by the `ngMessages` directive.
|
||||||
*
|
*
|
||||||
* Whenever the `ngMessages` directive contains one or more visible messages then the `.ng-active` CSS
|
* Whenever the `ngMessages` directive contains one or more visible messages then the `.ng-active` CSS
|
||||||
* class will be added to the element. The `.ng-inactive` CSS class will be applied when there are no
|
* class will be added to the element. The `.ng-inactive` CSS class will be applied when there are no
|
||||||
* animations present. Therefore, CSS transitions and keyframes as well as JavaScript animations can
|
* messages present. Therefore, CSS transitions and keyframes as well as JavaScript animations can
|
||||||
* hook into the animations whenever these classes are added/removed.
|
* hook into the animations whenever these classes are added/removed.
|
||||||
*
|
*
|
||||||
* Let's say that our HTML code for our messages container looks like so:
|
* Let's say that our HTML code for our messages container looks like so:
|
||||||
*
|
*
|
||||||
* ```html
|
* ```html
|
||||||
* <div ng-messages="myMessages" class="my-messages">
|
* <div ng-messages="myMessages" class="my-messages" role="alert">
|
||||||
* <div ng-message="alert" class="some-message">...</div>
|
* <div ng-message="alert" class="some-message">...</div>
|
||||||
* <div ng-message="fail" class="some-message">...</div>
|
* <div ng-message="fail" class="some-message">...</div>
|
||||||
* </div>
|
* </div>
|
||||||
@ -169,14 +277,14 @@ angular.module('ngMessages', [])
|
|||||||
*
|
*
|
||||||
* @description
|
* @description
|
||||||
* `ngMessages` is a directive that is designed to show and hide messages based on the state
|
* `ngMessages` is a directive that is designed to show and hide messages based on the state
|
||||||
* of a key/value object that it listens on. The directive itself compliments error message
|
* of a key/value object that it listens on. The directive itself complements error message
|
||||||
* reporting with the `ngModel` $error object (which stores a key/value state of validation errors).
|
* reporting with the `ngModel` $error object (which stores a key/value state of validation errors).
|
||||||
*
|
*
|
||||||
* `ngMessages` manages the state of internal messages within its container element. The internal
|
* `ngMessages` manages the state of internal messages within its container element. The internal
|
||||||
* messages use the `ngMessage` directive and will be inserted/removed from the page depending
|
* messages use the `ngMessage` directive and will be inserted/removed from the page depending
|
||||||
* on if they're present within the key/value object. By default, only one message will be displayed
|
* on if they're present within the key/value object. By default, only one message will be displayed
|
||||||
* at a time and this depends on the prioritization of the messages within the template. (This can
|
* at a time and this depends on the prioritization of the messages within the template. (This can
|
||||||
* be changed by using the ng-messages-multiple on the directive container.)
|
* be changed by using the `ng-messages-multiple` or `multiple` attribute on the directive container.)
|
||||||
*
|
*
|
||||||
* A remote template can also be used to promote message reusability and messages can also be
|
* A remote template can also be used to promote message reusability and messages can also be
|
||||||
* overridden.
|
* overridden.
|
||||||
@ -186,24 +294,23 @@ angular.module('ngMessages', [])
|
|||||||
* @usage
|
* @usage
|
||||||
* ```html
|
* ```html
|
||||||
* <!-- using attribute directives -->
|
* <!-- using attribute directives -->
|
||||||
* <ANY ng-messages="expression">
|
* <ANY ng-messages="expression" role="alert">
|
||||||
* <ANY ng-message="keyValue1">...</ANY>
|
* <ANY ng-message="stringValue">...</ANY>
|
||||||
* <ANY ng-message="keyValue2">...</ANY>
|
* <ANY ng-message="stringValue1, stringValue2, ...">...</ANY>
|
||||||
* <ANY ng-message="keyValue3">...</ANY>
|
* <ANY ng-message-exp="expressionValue">...</ANY>
|
||||||
* </ANY>
|
* </ANY>
|
||||||
*
|
*
|
||||||
* <!-- or by using element directives -->
|
* <!-- or by using element directives -->
|
||||||
* <ng-messages for="expression">
|
* <ng-messages for="expression" role="alert">
|
||||||
* <ng-message when="keyValue1">...</ng-message>
|
* <ng-message when="stringValue">...</ng-message>
|
||||||
* <ng-message when="keyValue2">...</ng-message>
|
* <ng-message when="stringValue1, stringValue2, ...">...</ng-message>
|
||||||
* <ng-message when="keyValue3">...</ng-message>
|
* <ng-message when-exp="expressionValue">...</ng-message>
|
||||||
* </ng-messages>
|
* </ng-messages>
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param {string} ngMessages an angular expression evaluating to a key/value object
|
* @param {string} ngMessages an angular expression evaluating to a key/value object
|
||||||
* (this is typically the $error object on an ngModel instance).
|
* (this is typically the $error object on an ngModel instance).
|
||||||
* @param {string=} ngMessagesMultiple|multiple when set, all messages will be displayed with true
|
* @param {string=} ngMessagesMultiple|multiple when set, all messages will be displayed with true
|
||||||
* @param {string=} ngMessagesInclude|include when set, the specified template will be included into the ng-messages container
|
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* <example name="ngMessages-directive" module="ngMessagesExample"
|
* <example name="ngMessages-directive" module="ngMessagesExample"
|
||||||
@ -211,17 +318,18 @@ angular.module('ngMessages', [])
|
|||||||
* animations="true" fixBase="true">
|
* animations="true" fixBase="true">
|
||||||
* <file name="index.html">
|
* <file name="index.html">
|
||||||
* <form name="myForm">
|
* <form name="myForm">
|
||||||
* <label>Enter your name:</label>
|
* <label>
|
||||||
|
* Enter your name:
|
||||||
* <input type="text"
|
* <input type="text"
|
||||||
* name="myName"
|
* name="myName"
|
||||||
* ng-model="name"
|
* ng-model="name"
|
||||||
* ng-minlength="5"
|
* ng-minlength="5"
|
||||||
* ng-maxlength="20"
|
* ng-maxlength="20"
|
||||||
* required />
|
* required />
|
||||||
*
|
* </label>
|
||||||
* <pre>myForm.myName.$error = {{ myForm.myName.$error | json }}</pre>
|
* <pre>myForm.myName.$error = {{ myForm.myName.$error | json }}</pre>
|
||||||
*
|
*
|
||||||
* <div ng-messages="myForm.myName.$error" style="color:maroon">
|
* <div ng-messages="myForm.myName.$error" style="color:maroon" role="alert">
|
||||||
* <div ng-message="required">You did not enter a field</div>
|
* <div ng-message="required">You did not enter a field</div>
|
||||||
* <div ng-message="minlength">Your field is too short</div>
|
* <div ng-message="minlength">Your field is too short</div>
|
||||||
* <div ng-message="maxlength">Your field is too long</div>
|
* <div ng-message="maxlength">Your field is too long</div>
|
||||||
@ -233,92 +341,224 @@ angular.module('ngMessages', [])
|
|||||||
* </file>
|
* </file>
|
||||||
* </example>
|
* </example>
|
||||||
*/
|
*/
|
||||||
.directive('ngMessages', ['$compile', '$animate', '$templateRequest',
|
.directive('ngMessages', ['$animate', function($animate) {
|
||||||
function($compile, $animate, $templateRequest) {
|
|
||||||
var ACTIVE_CLASS = 'ng-active';
|
var ACTIVE_CLASS = 'ng-active';
|
||||||
var INACTIVE_CLASS = 'ng-inactive';
|
var INACTIVE_CLASS = 'ng-inactive';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
restrict: 'AE',
|
|
||||||
controller: function() {
|
|
||||||
this.$renderNgMessageClasses = angular.noop;
|
|
||||||
|
|
||||||
var messages = [];
|
|
||||||
this.registerMessage = function(index, message) {
|
|
||||||
for (var i = 0; i < messages.length; i++) {
|
|
||||||
if (messages[i].type == message.type) {
|
|
||||||
if (index != i) {
|
|
||||||
var temp = messages[index];
|
|
||||||
messages[index] = messages[i];
|
|
||||||
if (index < messages.length) {
|
|
||||||
messages[i] = temp;
|
|
||||||
} else {
|
|
||||||
messages.splice(0, i); //remove the old one (and shift left)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
messages.splice(index, 0, message); //add the new one (and shift right)
|
|
||||||
};
|
|
||||||
|
|
||||||
this.renderMessages = function(values, multiple) {
|
|
||||||
values = values || {};
|
|
||||||
|
|
||||||
var found;
|
|
||||||
angular.forEach(messages, function(message) {
|
|
||||||
if ((!found || multiple) && truthyVal(values[message.type])) {
|
|
||||||
message.attach();
|
|
||||||
found = true;
|
|
||||||
} else {
|
|
||||||
message.detach();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.renderElementClasses(found);
|
|
||||||
|
|
||||||
function truthyVal(value) {
|
|
||||||
return value !== null && value !== false && value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
require: 'ngMessages',
|
require: 'ngMessages',
|
||||||
link: function($scope, element, $attrs, ctrl) {
|
restrict: 'AE',
|
||||||
ctrl.renderElementClasses = function(bool) {
|
controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {
|
||||||
bool ? $animate.setClass(element, ACTIVE_CLASS, INACTIVE_CLASS)
|
var ctrl = this;
|
||||||
: $animate.setClass(element, INACTIVE_CLASS, ACTIVE_CLASS);
|
var latestKey = 0;
|
||||||
};
|
var nextAttachId = 0;
|
||||||
|
|
||||||
//JavaScript treats empty strings as false, but ng-message-multiple by itself is an empty string
|
this.getAttachId = function getAttachId() { return nextAttachId++; };
|
||||||
var multiple = angular.isString($attrs.ngMessagesMultiple) ||
|
|
||||||
angular.isString($attrs.multiple);
|
|
||||||
|
|
||||||
var cachedValues, watchAttr = $attrs.ngMessages || $attrs['for']; //for is a reserved keyword
|
var messages = this.messages = {};
|
||||||
$scope.$watchCollection(watchAttr, function(values) {
|
var renderLater, cachedCollection;
|
||||||
cachedValues = values;
|
|
||||||
ctrl.renderMessages(values, multiple);
|
|
||||||
});
|
|
||||||
|
|
||||||
var tpl = $attrs.ngMessagesInclude || $attrs.include;
|
this.render = function(collection) {
|
||||||
if (tpl) {
|
collection = collection || {};
|
||||||
$templateRequest(tpl)
|
|
||||||
.then(function processTemplate(html) {
|
renderLater = false;
|
||||||
var after, container = angular.element('<div/>').html(html);
|
cachedCollection = collection;
|
||||||
angular.forEach(container.children(), function(elm) {
|
|
||||||
elm = angular.element(elm);
|
// this is true if the attribute is empty or if the attribute value is truthy
|
||||||
after ? after.after(elm)
|
var multiple = isAttrTruthy($scope, $attrs.ngMessagesMultiple) ||
|
||||||
: element.prepend(elm); //start of the container
|
isAttrTruthy($scope, $attrs.multiple);
|
||||||
after = elm;
|
|
||||||
$compile(elm)($scope);
|
var unmatchedMessages = [];
|
||||||
});
|
var matchedKeys = {};
|
||||||
ctrl.renderMessages(cachedValues, multiple);
|
var messageItem = ctrl.head;
|
||||||
|
var messageFound = false;
|
||||||
|
var totalMessages = 0;
|
||||||
|
|
||||||
|
// we use != instead of !== to allow for both undefined and null values
|
||||||
|
while (messageItem != null) {
|
||||||
|
totalMessages++;
|
||||||
|
var messageCtrl = messageItem.message;
|
||||||
|
|
||||||
|
var messageUsed = false;
|
||||||
|
if (!messageFound) {
|
||||||
|
forEach(collection, function(value, key) {
|
||||||
|
if (!messageUsed && truthy(value) && messageCtrl.test(key)) {
|
||||||
|
// this is to prevent the same error name from showing up twice
|
||||||
|
if (matchedKeys[key]) return;
|
||||||
|
matchedKeys[key] = true;
|
||||||
|
|
||||||
|
messageUsed = true;
|
||||||
|
messageCtrl.attach();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (messageUsed) {
|
||||||
|
// unless we want to display multiple messages then we should
|
||||||
|
// set a flag here to avoid displaying the next message in the list
|
||||||
|
messageFound = !multiple;
|
||||||
|
} else {
|
||||||
|
unmatchedMessages.push(messageCtrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
messageItem = messageItem.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
forEach(unmatchedMessages, function(messageCtrl) {
|
||||||
|
messageCtrl.detach();
|
||||||
|
});
|
||||||
|
|
||||||
|
unmatchedMessages.length !== totalMessages
|
||||||
|
? $animate.setClass($element, ACTIVE_CLASS, INACTIVE_CLASS)
|
||||||
|
: $animate.setClass($element, INACTIVE_CLASS, ACTIVE_CLASS);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.$watchCollection($attrs.ngMessages || $attrs['for'], ctrl.render);
|
||||||
|
|
||||||
|
this.reRender = function() {
|
||||||
|
if (!renderLater) {
|
||||||
|
renderLater = true;
|
||||||
|
$scope.$evalAsync(function() {
|
||||||
|
if (renderLater) {
|
||||||
|
cachedCollection && ctrl.render(cachedCollection);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.register = function(comment, messageCtrl) {
|
||||||
|
var nextKey = latestKey.toString();
|
||||||
|
messages[nextKey] = {
|
||||||
|
message: messageCtrl
|
||||||
|
};
|
||||||
|
insertMessageNode($element[0], comment, nextKey);
|
||||||
|
comment.$$ngMessageNode = nextKey;
|
||||||
|
latestKey++;
|
||||||
|
|
||||||
|
ctrl.reRender();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.deregister = function(comment) {
|
||||||
|
var key = comment.$$ngMessageNode;
|
||||||
|
delete comment.$$ngMessageNode;
|
||||||
|
removeMessageNode($element[0], comment, key);
|
||||||
|
delete messages[key];
|
||||||
|
ctrl.reRender();
|
||||||
|
};
|
||||||
|
|
||||||
|
function findPreviousMessage(parent, comment) {
|
||||||
|
var prevNode = comment;
|
||||||
|
var parentLookup = [];
|
||||||
|
while (prevNode && prevNode !== parent) {
|
||||||
|
var prevKey = prevNode.$$ngMessageNode;
|
||||||
|
if (prevKey && prevKey.length) {
|
||||||
|
return messages[prevKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
// dive deeper into the DOM and examine its children for any ngMessage
|
||||||
|
// comments that may be in an element that appears deeper in the list
|
||||||
|
if (prevNode.childNodes.length && parentLookup.indexOf(prevNode) == -1) {
|
||||||
|
parentLookup.push(prevNode);
|
||||||
|
prevNode = prevNode.childNodes[prevNode.childNodes.length - 1];
|
||||||
|
} else {
|
||||||
|
prevNode = prevNode.previousSibling || prevNode.parentNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertMessageNode(parent, comment, key) {
|
||||||
|
var messageNode = messages[key];
|
||||||
|
if (!ctrl.head) {
|
||||||
|
ctrl.head = messageNode;
|
||||||
|
} else {
|
||||||
|
var match = findPreviousMessage(parent, comment);
|
||||||
|
if (match) {
|
||||||
|
messageNode.next = match.next;
|
||||||
|
match.next = messageNode;
|
||||||
|
} else {
|
||||||
|
messageNode.next = ctrl.head;
|
||||||
|
ctrl.head = messageNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeMessageNode(parent, comment, key) {
|
||||||
|
var messageNode = messages[key];
|
||||||
|
|
||||||
|
var match = findPreviousMessage(parent, comment);
|
||||||
|
if (match) {
|
||||||
|
match.next = messageNode.next;
|
||||||
|
} else {
|
||||||
|
ctrl.head = messageNode.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
function isAttrTruthy(scope, attr) {
|
||||||
|
return (isString(attr) && attr.length === 0) || //empty attribute
|
||||||
|
truthy(scope.$eval(attr));
|
||||||
|
}
|
||||||
|
|
||||||
|
function truthy(val) {
|
||||||
|
return isString(val) ? val.length : !!val;
|
||||||
|
}
|
||||||
|
}])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc directive
|
||||||
|
* @name ngMessagesInclude
|
||||||
|
* @restrict AE
|
||||||
|
* @scope
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* `ngMessagesInclude` is a directive with the purpose to import existing ngMessage template
|
||||||
|
* code from a remote template and place the downloaded template code into the exact spot
|
||||||
|
* that the ngMessagesInclude directive is placed within the ngMessages container. This allows
|
||||||
|
* for a series of pre-defined messages to be reused and also allows for the developer to
|
||||||
|
* determine what messages are overridden due to the placement of the ngMessagesInclude directive.
|
||||||
|
*
|
||||||
|
* @usage
|
||||||
|
* ```html
|
||||||
|
* <!-- using attribute directives -->
|
||||||
|
* <ANY ng-messages="expression" role="alert">
|
||||||
|
* <ANY ng-messages-include="remoteTplString">...</ANY>
|
||||||
|
* </ANY>
|
||||||
|
*
|
||||||
|
* <!-- or by using element directives -->
|
||||||
|
* <ng-messages for="expression" role="alert">
|
||||||
|
* <ng-messages-include src="expressionValue1">...</ng-messages-include>
|
||||||
|
* </ng-messages>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
|
||||||
|
*
|
||||||
|
* @param {string} ngMessagesInclude|src a string value corresponding to the remote template.
|
||||||
|
*/
|
||||||
|
.directive('ngMessagesInclude',
|
||||||
|
['$templateRequest', '$document', '$compile', function($templateRequest, $document, $compile) {
|
||||||
|
|
||||||
|
return {
|
||||||
|
restrict: 'AE',
|
||||||
|
require: '^^ngMessages', // we only require this for validation sake
|
||||||
|
link: function($scope, element, attrs) {
|
||||||
|
var src = attrs.ngMessagesInclude || attrs.src;
|
||||||
|
$templateRequest(src).then(function(html) {
|
||||||
|
$compile(html)($scope, function(contents) {
|
||||||
|
element.after(contents);
|
||||||
|
|
||||||
|
// the anchor is placed for debugging purposes
|
||||||
|
var anchor = jqLite($document[0].createComment(' ngMessagesInclude: ' + src + ' '));
|
||||||
|
element.after(anchor);
|
||||||
|
|
||||||
|
// we don't want to pollute the DOM anymore by keeping an empty directive element
|
||||||
|
element.remove();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}])
|
}])
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc directive
|
* @ngdoc directive
|
||||||
* @name ngMessage
|
* @name ngMessage
|
||||||
@ -337,65 +577,130 @@ angular.module('ngMessages', [])
|
|||||||
* @usage
|
* @usage
|
||||||
* ```html
|
* ```html
|
||||||
* <!-- using attribute directives -->
|
* <!-- using attribute directives -->
|
||||||
|
* <ANY ng-messages="expression" role="alert">
|
||||||
|
* <ANY ng-message="stringValue">...</ANY>
|
||||||
|
* <ANY ng-message="stringValue1, stringValue2, ...">...</ANY>
|
||||||
|
* </ANY>
|
||||||
|
*
|
||||||
|
* <!-- or by using element directives -->
|
||||||
|
* <ng-messages for="expression" role="alert">
|
||||||
|
* <ng-message when="stringValue">...</ng-message>
|
||||||
|
* <ng-message when="stringValue1, stringValue2, ...">...</ng-message>
|
||||||
|
* </ng-messages>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param {expression} ngMessage|when a string value corresponding to the message key.
|
||||||
|
*/
|
||||||
|
.directive('ngMessage', ngMessageDirectiveFactory('AE'))
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc directive
|
||||||
|
* @name ngMessageExp
|
||||||
|
* @restrict AE
|
||||||
|
* @scope
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* `ngMessageExp` is a directive with the purpose to show and hide a particular message.
|
||||||
|
* For `ngMessageExp` to operate, a parent `ngMessages` directive on a parent DOM element
|
||||||
|
* must be situated since it determines which messages are visible based on the state
|
||||||
|
* of the provided key/value map that `ngMessages` listens on.
|
||||||
|
*
|
||||||
|
* @usage
|
||||||
|
* ```html
|
||||||
|
* <!-- using attribute directives -->
|
||||||
* <ANY ng-messages="expression">
|
* <ANY ng-messages="expression">
|
||||||
* <ANY ng-message="keyValue1">...</ANY>
|
* <ANY ng-message-exp="expressionValue">...</ANY>
|
||||||
* <ANY ng-message="keyValue2">...</ANY>
|
|
||||||
* <ANY ng-message="keyValue3">...</ANY>
|
|
||||||
* </ANY>
|
* </ANY>
|
||||||
*
|
*
|
||||||
* <!-- or by using element directives -->
|
* <!-- or by using element directives -->
|
||||||
* <ng-messages for="expression">
|
* <ng-messages for="expression">
|
||||||
* <ng-message when="keyValue1">...</ng-message>
|
* <ng-message when-exp="expressionValue">...</ng-message>
|
||||||
* <ng-message when="keyValue2">...</ng-message>
|
|
||||||
* <ng-message when="keyValue3">...</ng-message>
|
|
||||||
* </ng-messages>
|
* </ng-messages>
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param {string} ngMessage a string value corresponding to the message key.
|
* {@link module:ngMessages Click here} to learn more about `ngMessages` and `ngMessage`.
|
||||||
|
*
|
||||||
|
* @param {expression} ngMessageExp|whenExp an expression value corresponding to the message key.
|
||||||
*/
|
*/
|
||||||
.directive('ngMessage', ['$animate', function($animate) {
|
.directive('ngMessageExp', ngMessageDirectiveFactory('A'));
|
||||||
var COMMENT_NODE = 8;
|
|
||||||
|
function ngMessageDirectiveFactory(restrict) {
|
||||||
|
return ['$animate', function($animate) {
|
||||||
return {
|
return {
|
||||||
require: '^ngMessages',
|
restrict: 'AE',
|
||||||
transclude: 'element',
|
transclude: 'element',
|
||||||
terminal: true,
|
terminal: true,
|
||||||
restrict: 'AE',
|
require: '^^ngMessages',
|
||||||
link: function($scope, $element, $attrs, ngMessages, $transclude) {
|
link: function(scope, element, attrs, ngMessagesCtrl, $transclude) {
|
||||||
var index, element;
|
var commentNode = element[0];
|
||||||
|
|
||||||
var commentNode = $element[0];
|
var records;
|
||||||
var parentNode = commentNode.parentNode;
|
var staticExp = attrs.ngMessage || attrs.when;
|
||||||
for (var i = 0, j = 0; i < parentNode.childNodes.length; i++) {
|
var dynamicExp = attrs.ngMessageExp || attrs.whenExp;
|
||||||
var node = parentNode.childNodes[i];
|
var assignRecords = function(items) {
|
||||||
if (node.nodeType == COMMENT_NODE && node.nodeValue.indexOf('ngMessage') >= 0) {
|
records = items
|
||||||
if (node === commentNode) {
|
? (isArray(items)
|
||||||
index = j;
|
? items
|
||||||
break;
|
: items.split(/[\s,]+/))
|
||||||
}
|
: null;
|
||||||
j++;
|
ngMessagesCtrl.reRender();
|
||||||
}
|
};
|
||||||
|
|
||||||
|
if (dynamicExp) {
|
||||||
|
assignRecords(scope.$eval(dynamicExp));
|
||||||
|
scope.$watchCollection(dynamicExp, assignRecords);
|
||||||
|
} else {
|
||||||
|
assignRecords(staticExp);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngMessages.registerMessage(index, {
|
var currentElement, messageCtrl;
|
||||||
type: $attrs.ngMessage || $attrs.when,
|
ngMessagesCtrl.register(commentNode, messageCtrl = {
|
||||||
|
test: function(name) {
|
||||||
|
return contains(records, name);
|
||||||
|
},
|
||||||
attach: function() {
|
attach: function() {
|
||||||
if (!element) {
|
if (!currentElement) {
|
||||||
$transclude($scope, function(clone) {
|
$transclude(scope, function(elm) {
|
||||||
$animate.enter(clone, null, $element);
|
$animate.enter(elm, null, element);
|
||||||
element = clone;
|
currentElement = elm;
|
||||||
|
|
||||||
|
// Each time we attach this node to a message we get a new id that we can match
|
||||||
|
// when we are destroying the node later.
|
||||||
|
var $$attachId = currentElement.$$attachId = ngMessagesCtrl.getAttachId();
|
||||||
|
|
||||||
|
// in the event that the parent element is destroyed
|
||||||
|
// by any other structural directive then it's time
|
||||||
|
// to deregister the message from the controller
|
||||||
|
currentElement.on('$destroy', function() {
|
||||||
|
if (currentElement && currentElement.$$attachId === $$attachId) {
|
||||||
|
ngMessagesCtrl.deregister(commentNode);
|
||||||
|
messageCtrl.detach();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
detach: function(now) {
|
detach: function() {
|
||||||
if (element) {
|
if (currentElement) {
|
||||||
$animate.leave(element);
|
var elm = currentElement;
|
||||||
element = null;
|
currentElement = null;
|
||||||
|
$animate.leave(elm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}]);
|
}];
|
||||||
|
|
||||||
|
function contains(collection, key) {
|
||||||
|
if (collection) {
|
||||||
|
return isArray(collection)
|
||||||
|
? collection.indexOf(key) >= 0
|
||||||
|
: collection.hasOwnProperty(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
})(window, window.angular);
|
})(window, window.angular);
|
||||||
|
379
xstatic/pkg/angular/data/angular-mocks.js
vendored
379
xstatic/pkg/angular/data/angular-mocks.js
vendored
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @license AngularJS v1.3.18
|
* @license AngularJS v1.4.10
|
||||||
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
* (c) 2010-2015 Google, Inc. http://angularjs.org
|
||||||
* License: MIT
|
* License: MIT
|
||||||
*/
|
*/
|
||||||
(function(window, angular, undefined) {
|
(function(window, angular, undefined) {
|
||||||
@ -64,10 +64,9 @@ angular.mock.$Browser = function() {
|
|||||||
return listener;
|
return listener;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.$$applicationDestroyed = angular.noop;
|
||||||
self.$$checkUrlChange = angular.noop;
|
self.$$checkUrlChange = angular.noop;
|
||||||
|
|
||||||
self.cookieHash = {};
|
|
||||||
self.lastCookieHash = {};
|
|
||||||
self.deferredFns = [];
|
self.deferredFns = [];
|
||||||
self.deferredNextId = 0;
|
self.deferredNextId = 0;
|
||||||
|
|
||||||
@ -95,7 +94,7 @@ angular.mock.$Browser = function() {
|
|||||||
if (fn.id === deferId) fnIndex = index;
|
if (fn.id === deferId) fnIndex = index;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (fnIndex !== undefined) {
|
if (angular.isDefined(fnIndex)) {
|
||||||
self.deferredFns.splice(fnIndex, 1);
|
self.deferredFns.splice(fnIndex, 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -147,11 +146,6 @@ angular.mock.$Browser.prototype = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
addPollFn: function(pollFn) {
|
|
||||||
this.pollFns.push(pollFn);
|
|
||||||
return pollFn;
|
|
||||||
},
|
|
||||||
|
|
||||||
url: function(url, replace, state) {
|
url: function(url, replace, state) {
|
||||||
if (angular.isUndefined(state)) {
|
if (angular.isUndefined(state)) {
|
||||||
state = null;
|
state = null;
|
||||||
@ -170,25 +164,6 @@ angular.mock.$Browser.prototype = {
|
|||||||
return this.$$state;
|
return this.$$state;
|
||||||
},
|
},
|
||||||
|
|
||||||
cookies: function(name, value) {
|
|
||||||
if (name) {
|
|
||||||
if (angular.isUndefined(value)) {
|
|
||||||
delete this.cookieHash[name];
|
|
||||||
} else {
|
|
||||||
if (angular.isString(value) && //strings only
|
|
||||||
value.length <= 4096) { //strict cookie storage limits
|
|
||||||
this.cookieHash[name] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!angular.equals(this.cookieHash, this.lastCookieHash)) {
|
|
||||||
this.lastCookieHash = angular.copy(this.cookieHash);
|
|
||||||
this.cookieHash = angular.copy(this.cookieHash);
|
|
||||||
}
|
|
||||||
return this.cookieHash;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
notifyWhenNoOutstandingRequests: function(fn) {
|
notifyWhenNoOutstandingRequests: function(fn) {
|
||||||
fn();
|
fn();
|
||||||
}
|
}
|
||||||
@ -458,6 +433,7 @@ angular.mock.$LogProvider = function() {
|
|||||||
* indefinitely.
|
* indefinitely.
|
||||||
* @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
|
* @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
|
||||||
* will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
|
* will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
|
||||||
|
* @param {...*=} Pass additional parameters to the executed function.
|
||||||
* @returns {promise} A promise which will be notified on each iteration.
|
* @returns {promise} A promise which will be notified on each iteration.
|
||||||
*/
|
*/
|
||||||
angular.mock.$IntervalProvider = function() {
|
angular.mock.$IntervalProvider = function() {
|
||||||
@ -468,13 +444,17 @@ angular.mock.$IntervalProvider = function() {
|
|||||||
now = 0;
|
now = 0;
|
||||||
|
|
||||||
var $interval = function(fn, delay, count, invokeApply) {
|
var $interval = function(fn, delay, count, invokeApply) {
|
||||||
var iteration = 0,
|
var hasParams = arguments.length > 4,
|
||||||
|
args = hasParams ? Array.prototype.slice.call(arguments, 4) : [],
|
||||||
|
iteration = 0,
|
||||||
skipApply = (angular.isDefined(invokeApply) && !invokeApply),
|
skipApply = (angular.isDefined(invokeApply) && !invokeApply),
|
||||||
deferred = (skipApply ? $$q : $q).defer(),
|
deferred = (skipApply ? $$q : $q).defer(),
|
||||||
promise = deferred.promise;
|
promise = deferred.promise;
|
||||||
|
|
||||||
count = (angular.isDefined(count)) ? count : 0;
|
count = (angular.isDefined(count)) ? count : 0;
|
||||||
promise.then(null, null, fn);
|
promise.then(null, null, (!hasParams) ? fn : function() {
|
||||||
|
fn.apply(null, args);
|
||||||
|
});
|
||||||
|
|
||||||
promise.$$intervalId = nextRepeatId;
|
promise.$$intervalId = nextRepeatId;
|
||||||
|
|
||||||
@ -489,7 +469,7 @@ angular.mock.$IntervalProvider = function() {
|
|||||||
if (fn.id === promise.$$intervalId) fnIndex = index;
|
if (fn.id === promise.$$intervalId) fnIndex = index;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (fnIndex !== undefined) {
|
if (angular.isDefined(fnIndex)) {
|
||||||
repeatFns.splice(fnIndex, 1);
|
repeatFns.splice(fnIndex, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -531,7 +511,7 @@ angular.mock.$IntervalProvider = function() {
|
|||||||
if (fn.id === promise.$$intervalId) fnIndex = index;
|
if (fn.id === promise.$$intervalId) fnIndex = index;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (fnIndex !== undefined) {
|
if (angular.isDefined(fnIndex)) {
|
||||||
repeatFns[fnIndex].deferred.reject('canceled');
|
repeatFns[fnIndex].deferred.reject('canceled');
|
||||||
repeatFns.splice(fnIndex, 1);
|
repeatFns.splice(fnIndex, 1);
|
||||||
return true;
|
return true;
|
||||||
@ -581,20 +561,20 @@ function jsonStringToDate(string) {
|
|||||||
tzHour = 0,
|
tzHour = 0,
|
||||||
tzMin = 0;
|
tzMin = 0;
|
||||||
if (match[9]) {
|
if (match[9]) {
|
||||||
tzHour = int(match[9] + match[10]);
|
tzHour = toInt(match[9] + match[10]);
|
||||||
tzMin = int(match[9] + match[11]);
|
tzMin = toInt(match[9] + match[11]);
|
||||||
}
|
}
|
||||||
date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));
|
date.setUTCFullYear(toInt(match[1]), toInt(match[2]) - 1, toInt(match[3]));
|
||||||
date.setUTCHours(int(match[4] || 0) - tzHour,
|
date.setUTCHours(toInt(match[4] || 0) - tzHour,
|
||||||
int(match[5] || 0) - tzMin,
|
toInt(match[5] || 0) - tzMin,
|
||||||
int(match[6] || 0),
|
toInt(match[6] || 0),
|
||||||
int(match[7] || 0));
|
toInt(match[7] || 0));
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function int(str) {
|
function toInt(str) {
|
||||||
return parseInt(str, 10);
|
return parseInt(str, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,8 +586,9 @@ function padNumber(num, digits, trim) {
|
|||||||
}
|
}
|
||||||
num = '' + num;
|
num = '' + num;
|
||||||
while (num.length < digits) num = '0' + num;
|
while (num.length < digits) num = '0' + num;
|
||||||
if (trim)
|
if (trim) {
|
||||||
num = num.substr(num.length - digits);
|
num = num.substr(num.length - digits);
|
||||||
|
}
|
||||||
return neg + num;
|
return neg + num;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -657,11 +638,12 @@ angular.mock.TzDate = function(offset, timestamp) {
|
|||||||
self.origDate = jsonStringToDate(timestamp);
|
self.origDate = jsonStringToDate(timestamp);
|
||||||
|
|
||||||
timestamp = self.origDate.getTime();
|
timestamp = self.origDate.getTime();
|
||||||
if (isNaN(timestamp))
|
if (isNaN(timestamp)) {
|
||||||
throw {
|
throw {
|
||||||
name: "Illegal Argument",
|
name: "Illegal Argument",
|
||||||
message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
|
message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
|
||||||
};
|
};
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.origDate = new Date(timestamp);
|
self.origDate = new Date(timestamp);
|
||||||
}
|
}
|
||||||
@ -776,40 +758,152 @@ angular.mock.TzDate = function(offset, timestamp) {
|
|||||||
angular.mock.TzDate.prototype = Date.prototype;
|
angular.mock.TzDate.prototype = Date.prototype;
|
||||||
/* jshint +W101 */
|
/* jshint +W101 */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc service
|
||||||
|
* @name $animate
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Mock implementation of the {@link ng.$animate `$animate`} service. Exposes two additional methods
|
||||||
|
* for testing animations.
|
||||||
|
*/
|
||||||
angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
|
angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
|
||||||
|
|
||||||
.config(['$provide', function($provide) {
|
.config(['$provide', function($provide) {
|
||||||
|
|
||||||
var reflowQueue = [];
|
$provide.factory('$$forceReflow', function() {
|
||||||
$provide.value('$$animateReflow', function(fn) {
|
function reflowFn() {
|
||||||
var index = reflowQueue.length;
|
reflowFn.totalReflows++;
|
||||||
reflowQueue.push(fn);
|
}
|
||||||
return function cancel() {
|
reflowFn.totalReflows = 0;
|
||||||
reflowQueue.splice(index, 1);
|
return reflowFn;
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$provide.decorator('$animate', ['$delegate', '$$asyncCallback', '$timeout', '$browser',
|
$provide.factory('$$animateAsyncRun', function() {
|
||||||
function($delegate, $$asyncCallback, $timeout, $browser) {
|
var queue = [];
|
||||||
|
var queueFn = function() {
|
||||||
|
return function(fn) {
|
||||||
|
queue.push(fn);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
queueFn.flush = function() {
|
||||||
|
if (queue.length === 0) return false;
|
||||||
|
|
||||||
|
for (var i = 0; i < queue.length; i++) {
|
||||||
|
queue[i]();
|
||||||
|
}
|
||||||
|
queue = [];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
return queueFn;
|
||||||
|
});
|
||||||
|
|
||||||
|
$provide.decorator('$$animateJs', ['$delegate', function($delegate) {
|
||||||
|
var runners = [];
|
||||||
|
|
||||||
|
var animateJsConstructor = function() {
|
||||||
|
var animator = $delegate.apply($delegate, arguments);
|
||||||
|
// If no javascript animation is found, animator is undefined
|
||||||
|
if (animator) {
|
||||||
|
runners.push(animator);
|
||||||
|
}
|
||||||
|
return animator;
|
||||||
|
};
|
||||||
|
|
||||||
|
animateJsConstructor.$closeAndFlush = function() {
|
||||||
|
runners.forEach(function(runner) {
|
||||||
|
runner.end();
|
||||||
|
});
|
||||||
|
runners = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
return animateJsConstructor;
|
||||||
|
}]);
|
||||||
|
|
||||||
|
$provide.decorator('$animateCss', ['$delegate', function($delegate) {
|
||||||
|
var runners = [];
|
||||||
|
|
||||||
|
var animateCssConstructor = function(element, options) {
|
||||||
|
var animator = $delegate(element, options);
|
||||||
|
runners.push(animator);
|
||||||
|
return animator;
|
||||||
|
};
|
||||||
|
|
||||||
|
animateCssConstructor.$closeAndFlush = function() {
|
||||||
|
runners.forEach(function(runner) {
|
||||||
|
runner.end();
|
||||||
|
});
|
||||||
|
runners = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
return animateCssConstructor;
|
||||||
|
}]);
|
||||||
|
|
||||||
|
$provide.decorator('$animate', ['$delegate', '$timeout', '$browser', '$$rAF', '$animateCss', '$$animateJs',
|
||||||
|
'$$forceReflow', '$$animateAsyncRun', '$rootScope',
|
||||||
|
function($delegate, $timeout, $browser, $$rAF, $animateCss, $$animateJs,
|
||||||
|
$$forceReflow, $$animateAsyncRun, $rootScope) {
|
||||||
var animate = {
|
var animate = {
|
||||||
queue: [],
|
queue: [],
|
||||||
cancel: $delegate.cancel,
|
cancel: $delegate.cancel,
|
||||||
|
on: $delegate.on,
|
||||||
|
off: $delegate.off,
|
||||||
|
pin: $delegate.pin,
|
||||||
|
get reflows() {
|
||||||
|
return $$forceReflow.totalReflows;
|
||||||
|
},
|
||||||
enabled: $delegate.enabled,
|
enabled: $delegate.enabled,
|
||||||
triggerCallbackEvents: function() {
|
/**
|
||||||
$$asyncCallback.flush();
|
* @ngdoc method
|
||||||
|
* @name $animate#closeAndFlush
|
||||||
|
* @description
|
||||||
|
*
|
||||||
|
* This method will close all pending animations (both {@link ngAnimate#javascript-based-animations Javascript}
|
||||||
|
* and {@link ngAnimate.$animateCss CSS}) and it will also flush any remaining animation frames and/or callbacks.
|
||||||
|
*/
|
||||||
|
closeAndFlush: function() {
|
||||||
|
// we allow the flush command to swallow the errors
|
||||||
|
// because depending on whether CSS or JS animations are
|
||||||
|
// used, there may not be a RAF flush. The primary flush
|
||||||
|
// at the end of this function must throw an exception
|
||||||
|
// because it will track if there were pending animations
|
||||||
|
this.flush(true);
|
||||||
|
$animateCss.$closeAndFlush();
|
||||||
|
$$animateJs.$closeAndFlush();
|
||||||
|
this.flush();
|
||||||
},
|
},
|
||||||
triggerCallbackPromise: function() {
|
/**
|
||||||
$timeout.flush(0);
|
* @ngdoc method
|
||||||
},
|
* @name $animate#flush
|
||||||
triggerCallbacks: function() {
|
* @description
|
||||||
this.triggerCallbackEvents();
|
*
|
||||||
this.triggerCallbackPromise();
|
* This method is used to flush the pending callbacks and animation frames to either start
|
||||||
},
|
* an animation or conclude an animation. Note that this will not actually close an
|
||||||
triggerReflow: function() {
|
* actively running animation (see {@link ngMock.$animate#closeAndFlush `closeAndFlush()`} for that).
|
||||||
angular.forEach(reflowQueue, function(fn) {
|
*/
|
||||||
fn();
|
flush: function(hideErrors) {
|
||||||
});
|
$rootScope.$digest();
|
||||||
reflowQueue = [];
|
|
||||||
|
var doNextRun, somethingFlushed = false;
|
||||||
|
do {
|
||||||
|
doNextRun = false;
|
||||||
|
|
||||||
|
if ($$rAF.queue.length) {
|
||||||
|
$$rAF.flush();
|
||||||
|
doNextRun = somethingFlushed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($$animateAsyncRun.flush()) {
|
||||||
|
doNextRun = somethingFlushed = true;
|
||||||
|
}
|
||||||
|
} while (doNextRun);
|
||||||
|
|
||||||
|
if (!somethingFlushed && !hideErrors) {
|
||||||
|
throw new Error('No pending animations ready to be closed or flushed');
|
||||||
|
}
|
||||||
|
|
||||||
|
$rootScope.$digest();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1026,7 +1120,7 @@ angular.mock.dump = function(object) {
|
|||||||
$http.post('/add-msg.py', message, { headers: headers } ).success(function(response) {
|
$http.post('/add-msg.py', message, { headers: headers } ).success(function(response) {
|
||||||
$scope.status = '';
|
$scope.status = '';
|
||||||
}).error(function() {
|
}).error(function() {
|
||||||
$scope.status = 'ERROR!';
|
$scope.status = 'Failed...';
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1107,7 +1201,7 @@ angular.mock.dump = function(object) {
|
|||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
|
|
||||||
$httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
|
$httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
|
||||||
// check if the header was send, if it wasn't the expectation won't
|
// check if the header was sent, if it wasn't the expectation won't
|
||||||
// match the request and the test will fail
|
// match the request and the test will fail
|
||||||
return headers['Authorization'] == 'xxx';
|
return headers['Authorization'] == 'xxx';
|
||||||
}).respond(201, '');
|
}).respond(201, '');
|
||||||
@ -1154,7 +1248,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(vojta): change params to: method, url, data, headers, callback
|
// TODO(vojta): change params to: method, url, data, headers, callback
|
||||||
function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) {
|
function $httpBackend(method, url, data, callback, headers, timeout, withCredentials, responseType) {
|
||||||
|
|
||||||
var xhr = new MockXhr(),
|
var xhr = new MockXhr(),
|
||||||
expectation = expectations[0],
|
expectation = expectations[0],
|
||||||
wasExpected = false;
|
wasExpected = false;
|
||||||
@ -1191,14 +1286,16 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (expectation && expectation.match(method, url)) {
|
if (expectation && expectation.match(method, url)) {
|
||||||
if (!expectation.matchData(data))
|
if (!expectation.matchData(data)) {
|
||||||
throw new Error('Expected ' + expectation + ' with different data\n' +
|
throw new Error('Expected ' + expectation + ' with different data\n' +
|
||||||
'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data);
|
'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data);
|
||||||
|
}
|
||||||
|
|
||||||
if (!expectation.matchHeaders(headers))
|
if (!expectation.matchHeaders(headers)) {
|
||||||
throw new Error('Expected ' + expectation + ' with different headers\n' +
|
throw new Error('Expected ' + expectation + ' with different headers\n' +
|
||||||
'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' +
|
'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' +
|
||||||
prettyPrint(headers));
|
prettyPrint(headers));
|
||||||
|
}
|
||||||
|
|
||||||
expectations.shift();
|
expectations.shift();
|
||||||
|
|
||||||
@ -1216,7 +1313,7 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
// if $browser specified, we do auto flush all requests
|
// if $browser specified, we do auto flush all requests
|
||||||
($browser ? $browser.defer : responsesPush)(wrapResponse(definition));
|
($browser ? $browser.defer : responsesPush)(wrapResponse(definition));
|
||||||
} else if (definition.passThrough) {
|
} else if (definition.passThrough) {
|
||||||
$delegate(method, url, data, callback, headers, timeout, withCredentials);
|
$delegate(method, url, data, callback, headers, timeout, withCredentials, responseType);
|
||||||
} else throw new Error('No response defined !');
|
} else throw new Error('No response defined !');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1234,8 +1331,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
* Creates a new backend definition.
|
* Creates a new backend definition.
|
||||||
*
|
*
|
||||||
* @param {string} method HTTP method.
|
* @param {string} method HTTP method.
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
|
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
|
||||||
* data string and returns true if the data is as expected.
|
* data string and returns true if the data is as expected.
|
||||||
* @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
|
* @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
|
||||||
@ -1280,8 +1377,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new backend definition for GET requests. For more info see `when()`.
|
* Creates a new backend definition for GET requests. For more info see `when()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(Object|function(Object))=} headers HTTP headers.
|
* @param {(Object|function(Object))=} headers HTTP headers.
|
||||||
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
||||||
* request is handled. You can save this object for later use and invoke `respond` again in
|
* request is handled. You can save this object for later use and invoke `respond` again in
|
||||||
@ -1294,8 +1391,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new backend definition for HEAD requests. For more info see `when()`.
|
* Creates a new backend definition for HEAD requests. For more info see `when()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(Object|function(Object))=} headers HTTP headers.
|
* @param {(Object|function(Object))=} headers HTTP headers.
|
||||||
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
||||||
* request is handled. You can save this object for later use and invoke `respond` again in
|
* request is handled. You can save this object for later use and invoke `respond` again in
|
||||||
@ -1308,8 +1405,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new backend definition for DELETE requests. For more info see `when()`.
|
* Creates a new backend definition for DELETE requests. For more info see `when()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(Object|function(Object))=} headers HTTP headers.
|
* @param {(Object|function(Object))=} headers HTTP headers.
|
||||||
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
||||||
* request is handled. You can save this object for later use and invoke `respond` again in
|
* request is handled. You can save this object for later use and invoke `respond` again in
|
||||||
@ -1322,8 +1419,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new backend definition for POST requests. For more info see `when()`.
|
* Creates a new backend definition for POST requests. For more info see `when()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
|
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
|
||||||
* data string and returns true if the data is as expected.
|
* data string and returns true if the data is as expected.
|
||||||
* @param {(Object|function(Object))=} headers HTTP headers.
|
* @param {(Object|function(Object))=} headers HTTP headers.
|
||||||
@ -1338,8 +1435,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new backend definition for PUT requests. For more info see `when()`.
|
* Creates a new backend definition for PUT requests. For more info see `when()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
|
* @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
|
||||||
* data string and returns true if the data is as expected.
|
* data string and returns true if the data is as expected.
|
||||||
* @param {(Object|function(Object))=} headers HTTP headers.
|
* @param {(Object|function(Object))=} headers HTTP headers.
|
||||||
@ -1354,8 +1451,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new backend definition for JSONP requests. For more info see `when()`.
|
* Creates a new backend definition for JSONP requests. For more info see `when()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
||||||
* request is handled. You can save this object for later use and invoke `respond` again in
|
* request is handled. You can save this object for later use and invoke `respond` again in
|
||||||
* order to change how a matched request is handled.
|
* order to change how a matched request is handled.
|
||||||
@ -1370,8 +1467,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
* Creates a new request expectation.
|
* Creates a new request expectation.
|
||||||
*
|
*
|
||||||
* @param {string} method HTTP method.
|
* @param {string} method HTTP method.
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
|
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
|
||||||
* receives data string and returns true if the data is as expected, or Object if request body
|
* receives data string and returns true if the data is as expected, or Object if request body
|
||||||
* is in JSON format.
|
* is in JSON format.
|
||||||
@ -1409,8 +1506,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new request expectation for GET requests. For more info see `expect()`.
|
* Creates a new request expectation for GET requests. For more info see `expect()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {Object=} headers HTTP headers.
|
* @param {Object=} headers HTTP headers.
|
||||||
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
||||||
* request is handled. You can save this object for later use and invoke `respond` again in
|
* request is handled. You can save this object for later use and invoke `respond` again in
|
||||||
@ -1423,8 +1520,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new request expectation for HEAD requests. For more info see `expect()`.
|
* Creates a new request expectation for HEAD requests. For more info see `expect()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {Object=} headers HTTP headers.
|
* @param {Object=} headers HTTP headers.
|
||||||
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
||||||
* request is handled. You can save this object for later use and invoke `respond` again in
|
* request is handled. You can save this object for later use and invoke `respond` again in
|
||||||
@ -1437,8 +1534,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new request expectation for DELETE requests. For more info see `expect()`.
|
* Creates a new request expectation for DELETE requests. For more info see `expect()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {Object=} headers HTTP headers.
|
* @param {Object=} headers HTTP headers.
|
||||||
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
||||||
* request is handled. You can save this object for later use and invoke `respond` again in
|
* request is handled. You can save this object for later use and invoke `respond` again in
|
||||||
@ -1451,8 +1548,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new request expectation for POST requests. For more info see `expect()`.
|
* Creates a new request expectation for POST requests. For more info see `expect()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
|
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
|
||||||
* receives data string and returns true if the data is as expected, or Object if request body
|
* receives data string and returns true if the data is as expected, or Object if request body
|
||||||
* is in JSON format.
|
* is in JSON format.
|
||||||
@ -1468,8 +1565,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new request expectation for PUT requests. For more info see `expect()`.
|
* Creates a new request expectation for PUT requests. For more info see `expect()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
|
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
|
||||||
* receives data string and returns true if the data is as expected, or Object if request body
|
* receives data string and returns true if the data is as expected, or Object if request body
|
||||||
* is in JSON format.
|
* is in JSON format.
|
||||||
@ -1485,8 +1582,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new request expectation for PATCH requests. For more info see `expect()`.
|
* Creates a new request expectation for PATCH requests. For more info see `expect()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
|
* @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
|
||||||
* receives data string and returns true if the data is as expected, or Object if request body
|
* receives data string and returns true if the data is as expected, or Object if request body
|
||||||
* is in JSON format.
|
* is in JSON format.
|
||||||
@ -1502,8 +1599,8 @@ function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new request expectation for JSONP requests. For more info see `expect()`.
|
* Creates a new request expectation for JSONP requests. For more info see `expect()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives an url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
* @returns {requestHandler} Returns an object with `respond` method that controls how a matched
|
||||||
* request is handled. You can save this object for later use and invoke `respond` again in
|
* request is handled. You can save this object for later use and invoke `respond` again in
|
||||||
* order to change how a matched request is handled.
|
* order to change how a matched request is handled.
|
||||||
@ -1759,47 +1856,33 @@ angular.mock.$TimeoutDecorator = ['$delegate', '$browser', function($delegate, $
|
|||||||
}];
|
}];
|
||||||
|
|
||||||
angular.mock.$RAFDecorator = ['$delegate', function($delegate) {
|
angular.mock.$RAFDecorator = ['$delegate', function($delegate) {
|
||||||
var queue = [];
|
|
||||||
var rafFn = function(fn) {
|
var rafFn = function(fn) {
|
||||||
var index = queue.length;
|
var index = rafFn.queue.length;
|
||||||
queue.push(fn);
|
rafFn.queue.push(fn);
|
||||||
return function() {
|
return function() {
|
||||||
queue.splice(index, 1);
|
rafFn.queue.splice(index, 1);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
rafFn.queue = [];
|
||||||
rafFn.supported = $delegate.supported;
|
rafFn.supported = $delegate.supported;
|
||||||
|
|
||||||
rafFn.flush = function() {
|
rafFn.flush = function() {
|
||||||
if (queue.length === 0) {
|
if (rafFn.queue.length === 0) {
|
||||||
throw new Error('No rAF callbacks present');
|
throw new Error('No rAF callbacks present');
|
||||||
}
|
}
|
||||||
|
|
||||||
var length = queue.length;
|
var length = rafFn.queue.length;
|
||||||
for (var i = 0; i < length; i++) {
|
for (var i = 0; i < length; i++) {
|
||||||
queue[i]();
|
rafFn.queue[i]();
|
||||||
}
|
}
|
||||||
|
|
||||||
queue = [];
|
rafFn.queue = rafFn.queue.slice(i);
|
||||||
};
|
};
|
||||||
|
|
||||||
return rafFn;
|
return rafFn;
|
||||||
}];
|
}];
|
||||||
|
|
||||||
angular.mock.$AsyncCallbackDecorator = ['$delegate', function($delegate) {
|
|
||||||
var callbacks = [];
|
|
||||||
var addFn = function(fn) {
|
|
||||||
callbacks.push(fn);
|
|
||||||
};
|
|
||||||
addFn.flush = function() {
|
|
||||||
angular.forEach(callbacks, function(fn) {
|
|
||||||
fn();
|
|
||||||
});
|
|
||||||
callbacks = [];
|
|
||||||
};
|
|
||||||
return addFn;
|
|
||||||
}];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -1833,19 +1916,19 @@ angular.mock.$RootElementProvider = function() {
|
|||||||
*
|
*
|
||||||
* // Controller definition ...
|
* // Controller definition ...
|
||||||
*
|
*
|
||||||
* myMod.controller('MyDirectiveController', ['log', function($log) {
|
* myMod.controller('MyDirectiveController', ['$log', function($log) {
|
||||||
* $log.info(this.name);
|
* $log.info(this.name);
|
||||||
* })];
|
* }]);
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* // In a test ...
|
* // In a test ...
|
||||||
*
|
*
|
||||||
* describe('myDirectiveController', function() {
|
* describe('myDirectiveController', function() {
|
||||||
* it('should write the bound name to the log', inject(function($controller, $log) {
|
* it('should write the bound name to the log', inject(function($controller, $log) {
|
||||||
* var ctrl = $controller('MyDirective', { /* no locals */ }, { name: 'Clark Kent' });
|
* var ctrl = $controller('MyDirectiveController', { /* no locals */ }, { name: 'Clark Kent' });
|
||||||
* expect(ctrl.name).toEqual('Clark Kent');
|
* expect(ctrl.name).toEqual('Clark Kent');
|
||||||
* expect($log.info.logs).toEqual(['Clark Kent']);
|
* expect($log.info.logs).toEqual(['Clark Kent']);
|
||||||
* });
|
* }));
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
@ -1906,7 +1989,6 @@ angular.module('ngMock', ['ng']).provider({
|
|||||||
}).config(['$provide', function($provide) {
|
}).config(['$provide', function($provide) {
|
||||||
$provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
|
$provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
|
||||||
$provide.decorator('$$rAF', angular.mock.$RAFDecorator);
|
$provide.decorator('$$rAF', angular.mock.$RAFDecorator);
|
||||||
$provide.decorator('$$asyncCallback', angular.mock.$AsyncCallbackDecorator);
|
|
||||||
$provide.decorator('$rootScope', angular.mock.$RootScopeDecorator);
|
$provide.decorator('$rootScope', angular.mock.$RootScopeDecorator);
|
||||||
$provide.decorator('$controller', angular.mock.$ControllerDecorator);
|
$provide.decorator('$controller', angular.mock.$ControllerDecorator);
|
||||||
}]);
|
}]);
|
||||||
@ -1985,8 +2067,8 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
|
|||||||
* Creates a new backend definition.
|
* Creates a new backend definition.
|
||||||
*
|
*
|
||||||
* @param {string} method HTTP method.
|
* @param {string} method HTTP method.
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(string|RegExp)=} data HTTP request body.
|
* @param {(string|RegExp)=} data HTTP request body.
|
||||||
* @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
|
* @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
|
||||||
* object and returns true if the headers match the current definition.
|
* object and returns true if the headers match the current definition.
|
||||||
@ -2013,8 +2095,8 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new backend definition for GET requests. For more info see `when()`.
|
* Creates a new backend definition for GET requests. For more info see `when()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(Object|function(Object))=} headers HTTP headers.
|
* @param {(Object|function(Object))=} headers HTTP headers.
|
||||||
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
|
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
|
||||||
* control how a matched request is handled. You can save this object for later use and invoke
|
* control how a matched request is handled. You can save this object for later use and invoke
|
||||||
@ -2028,8 +2110,8 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new backend definition for HEAD requests. For more info see `when()`.
|
* Creates a new backend definition for HEAD requests. For more info see `when()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(Object|function(Object))=} headers HTTP headers.
|
* @param {(Object|function(Object))=} headers HTTP headers.
|
||||||
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
|
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
|
||||||
* control how a matched request is handled. You can save this object for later use and invoke
|
* control how a matched request is handled. You can save this object for later use and invoke
|
||||||
@ -2043,8 +2125,8 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new backend definition for DELETE requests. For more info see `when()`.
|
* Creates a new backend definition for DELETE requests. For more info see `when()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(Object|function(Object))=} headers HTTP headers.
|
* @param {(Object|function(Object))=} headers HTTP headers.
|
||||||
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
|
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
|
||||||
* control how a matched request is handled. You can save this object for later use and invoke
|
* control how a matched request is handled. You can save this object for later use and invoke
|
||||||
@ -2058,8 +2140,8 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new backend definition for POST requests. For more info see `when()`.
|
* Creates a new backend definition for POST requests. For more info see `when()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(string|RegExp)=} data HTTP request body.
|
* @param {(string|RegExp)=} data HTTP request body.
|
||||||
* @param {(Object|function(Object))=} headers HTTP headers.
|
* @param {(Object|function(Object))=} headers HTTP headers.
|
||||||
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
|
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
|
||||||
@ -2074,8 +2156,8 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new backend definition for PUT requests. For more info see `when()`.
|
* Creates a new backend definition for PUT requests. For more info see `when()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(string|RegExp)=} data HTTP request body.
|
* @param {(string|RegExp)=} data HTTP request body.
|
||||||
* @param {(Object|function(Object))=} headers HTTP headers.
|
* @param {(Object|function(Object))=} headers HTTP headers.
|
||||||
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
|
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
|
||||||
@ -2090,8 +2172,8 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new backend definition for PATCH requests. For more info see `when()`.
|
* Creates a new backend definition for PATCH requests. For more info see `when()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @param {(string|RegExp)=} data HTTP request body.
|
* @param {(string|RegExp)=} data HTTP request body.
|
||||||
* @param {(Object|function(Object))=} headers HTTP headers.
|
* @param {(Object|function(Object))=} headers HTTP headers.
|
||||||
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
|
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
|
||||||
@ -2106,8 +2188,8 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
|
|||||||
* @description
|
* @description
|
||||||
* Creates a new backend definition for JSONP requests. For more info see `when()`.
|
* Creates a new backend definition for JSONP requests. For more info see `when()`.
|
||||||
*
|
*
|
||||||
* @param {string|RegExp|function(string)} url HTTP url or function that receives the url
|
* @param {string|RegExp|function(string)} url HTTP url or function that receives a url
|
||||||
* and returns true if the url match the current definition.
|
* and returns true if the url matches the current definition.
|
||||||
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
|
* @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
|
||||||
* control how a matched request is handled. You can save this object for later use and invoke
|
* control how a matched request is handled. You can save this object for later use and invoke
|
||||||
* `respond` or `passThrough` again in order to change how a matched request is handled.
|
* `respond` or `passThrough` again in order to change how a matched request is handled.
|
||||||
@ -2244,8 +2326,6 @@ if (window.jasmine || window.mocha) {
|
|||||||
|
|
||||||
if (injector) {
|
if (injector) {
|
||||||
injector.get('$rootElement').off();
|
injector.get('$rootElement').off();
|
||||||
var $browser = injector.get('$browser');
|
|
||||||
if ($browser.pollFns) $browser.pollFns.length = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up jquery's fragment cache
|
// clean up jquery's fragment cache
|
||||||
@ -2277,8 +2357,9 @@ if (window.jasmine || window.mocha) {
|
|||||||
* @param {...(string|Function|Object)} fns any number of modules which are represented as string
|
* @param {...(string|Function|Object)} fns any number of modules which are represented as string
|
||||||
* aliases or as anonymous module initialization functions. The modules are used to
|
* aliases or as anonymous module initialization functions. The modules are used to
|
||||||
* configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an
|
* configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an
|
||||||
* object literal is passed they will be registered as values in the module, the key being
|
* object literal is passed each key-value pair will be registered on the module via
|
||||||
* the module name and the value being what is returned.
|
* {@link auto.$provide $provide}.value, the key being the string name (or token) to associate
|
||||||
|
* with the value on the injector.
|
||||||
*/
|
*/
|
||||||
window.module = angular.mock.module = function() {
|
window.module = angular.mock.module = function() {
|
||||||
var moduleFns = Array.prototype.slice.call(arguments, 0);
|
var moduleFns = Array.prototype.slice.call(arguments, 0);
|
||||||
|
31
xstatic/pkg/angular/data/angular-route.js
vendored
31
xstatic/pkg/angular/data/angular-route.js
vendored
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @license AngularJS v1.3.18
|
* @license AngularJS v1.4.10
|
||||||
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
* (c) 2010-2015 Google, Inc. http://angularjs.org
|
||||||
* License: MIT
|
* License: MIT
|
||||||
*/
|
*/
|
||||||
(function(window, angular, undefined) {'use strict';
|
(function(window, angular, undefined) {'use strict';
|
||||||
@ -78,8 +78,8 @@ function $RouteProvider() {
|
|||||||
* - `controller` – `{(string|function()=}` – Controller fn that should be associated with
|
* - `controller` – `{(string|function()=}` – Controller fn that should be associated with
|
||||||
* newly created scope or the name of a {@link angular.Module#controller registered
|
* newly created scope or the name of a {@link angular.Module#controller registered
|
||||||
* controller} if passed as a string.
|
* controller} if passed as a string.
|
||||||
* - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be
|
* - `controllerAs` – `{string=}` – An identifier name for a reference to the controller.
|
||||||
* published to scope under the `controllerAs` 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
|
* - `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
|
* returns an html template as a string which should be used by {@link
|
||||||
* ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
|
* ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
|
||||||
@ -206,9 +206,9 @@ function $RouteProvider() {
|
|||||||
|
|
||||||
path = path
|
path = path
|
||||||
.replace(/([().])/g, '\\$1')
|
.replace(/([().])/g, '\\$1')
|
||||||
.replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option) {
|
.replace(/(\/)?:(\w+)(\*\?|[\?\*])?/g, function(_, slash, key, option) {
|
||||||
var optional = option === '?' ? option : null;
|
var optional = (option === '?' || option === '*?') ? '?' : null;
|
||||||
var star = option === '*' ? option : null;
|
var star = (option === '*' || option === '*?') ? '*' : null;
|
||||||
keys.push({ name: key, optional: !!optional });
|
keys.push({ name: key, optional: !!optional });
|
||||||
slash = slash || '';
|
slash = slash || '';
|
||||||
return ''
|
return ''
|
||||||
@ -468,10 +468,18 @@ function $RouteProvider() {
|
|||||||
*/
|
*/
|
||||||
reload: function() {
|
reload: function() {
|
||||||
forceReload = true;
|
forceReload = true;
|
||||||
|
|
||||||
|
var fakeLocationEvent = {
|
||||||
|
defaultPrevented: false,
|
||||||
|
preventDefault: function fakePreventDefault() {
|
||||||
|
this.defaultPrevented = true;
|
||||||
|
forceReload = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
$rootScope.$evalAsync(function() {
|
$rootScope.$evalAsync(function() {
|
||||||
// Don't support cancellation of a reload for now...
|
prepareRoute(fakeLocationEvent);
|
||||||
prepareRoute();
|
if (!fakeLocationEvent.defaultPrevented) commitRoute();
|
||||||
commitRoute();
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -609,8 +617,8 @@ function $RouteProvider() {
|
|||||||
return $q.all(locals);
|
return $q.all(locals);
|
||||||
}
|
}
|
||||||
}).
|
}).
|
||||||
// after route change
|
|
||||||
then(function(locals) {
|
then(function(locals) {
|
||||||
|
// after route change
|
||||||
if (nextRoute == $route.current) {
|
if (nextRoute == $route.current) {
|
||||||
if (nextRoute) {
|
if (nextRoute) {
|
||||||
nextRoute.locals = locals;
|
nextRoute.locals = locals;
|
||||||
@ -796,7 +804,6 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory);
|
|||||||
}
|
}
|
||||||
|
|
||||||
.view-animate.ng-enter, .view-animate.ng-leave {
|
.view-animate.ng-enter, .view-animate.ng-leave {
|
||||||
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
|
|
||||||
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
|
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
|
||||||
|
|
||||||
display:block;
|
display:block;
|
||||||
|
64
xstatic/pkg/angular/data/angular-sanitize.js
vendored
64
xstatic/pkg/angular/data/angular-sanitize.js
vendored
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @license AngularJS v1.3.18
|
* @license AngularJS v1.4.10
|
||||||
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
* (c) 2010-2015 Google, Inc. http://angularjs.org
|
||||||
* License: MIT
|
* License: MIT
|
||||||
*/
|
*/
|
||||||
(function(window, angular, undefined) {'use strict';
|
(function(window, angular, undefined) {'use strict';
|
||||||
@ -211,10 +211,11 @@ var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a
|
|||||||
|
|
||||||
// SVG Elements
|
// SVG Elements
|
||||||
// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements
|
// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements
|
||||||
var svgElements = makeMap("animate,animateColor,animateMotion,animateTransform,circle,defs," +
|
// Note: the elements animate,animateColor,animateMotion,animateTransform,set are intentionally omitted.
|
||||||
"desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient," +
|
// They can potentially allow for arbitrary javascript to be executed. See #11290
|
||||||
"line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set," +
|
var svgElements = makeMap("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph," +
|
||||||
"stop,svg,switch,text,title,tspan,use");
|
"hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline," +
|
||||||
|
"radialGradient,rect,stop,svg,switch,text,title,tspan,use");
|
||||||
|
|
||||||
// Special Elements (can contain anything)
|
// Special Elements (can contain anything)
|
||||||
var specialElements = makeMap("script,style");
|
var specialElements = makeMap("script,style");
|
||||||
@ -232,36 +233,37 @@ var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap,xlink:href");
|
|||||||
var htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' +
|
var htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' +
|
||||||
'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' +
|
'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' +
|
||||||
'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' +
|
'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' +
|
||||||
'scope,scrolling,shape,size,span,start,summary,target,title,type,' +
|
'scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,' +
|
||||||
'valign,value,vspace,width');
|
'valign,value,vspace,width');
|
||||||
|
|
||||||
// SVG attributes (without "id" and "name" attributes)
|
// SVG attributes (without "id" and "name" attributes)
|
||||||
// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes
|
// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes
|
||||||
var svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +
|
var svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +
|
||||||
'attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,' +
|
'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' +
|
||||||
'color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,' +
|
'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' +
|
||||||
'font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,' +
|
'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' +
|
||||||
'gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,' +
|
'height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,' +
|
||||||
'keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,' +
|
'marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,' +
|
||||||
'markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,' +
|
'max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,' +
|
||||||
'overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,' +
|
'path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,' +
|
||||||
'repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,' +
|
'requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,' +
|
||||||
'stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,' +
|
'stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,' +
|
||||||
'stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,' +
|
'stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,' +
|
||||||
'stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,' +
|
'stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,' +
|
||||||
'underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,' +
|
'underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,' +
|
||||||
'viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,' +
|
'width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,' +
|
||||||
'xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,' +
|
'xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan', true);
|
||||||
'zoomAndPan');
|
|
||||||
|
|
||||||
var validAttrs = angular.extend({},
|
var validAttrs = angular.extend({},
|
||||||
uriAttrs,
|
uriAttrs,
|
||||||
svgAttrs,
|
svgAttrs,
|
||||||
htmlAttrs);
|
htmlAttrs);
|
||||||
|
|
||||||
function makeMap(str) {
|
function makeMap(str, lowercaseKeys) {
|
||||||
var obj = {}, items = str.split(','), i;
|
var obj = {}, items = str.split(','), i;
|
||||||
for (i = 0; i < items.length; i++) obj[items[i]] = true;
|
for (i = 0; i < items.length; i++) {
|
||||||
|
obj[lowercaseKeys ? angular.lowercase(items[i]) : items[i]] = true;
|
||||||
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,8 +391,9 @@ function htmlParser(html, handler) {
|
|||||||
|
|
||||||
unary = voidElements[tagName] || !!unary;
|
unary = voidElements[tagName] || !!unary;
|
||||||
|
|
||||||
if (!unary)
|
if (!unary) {
|
||||||
stack.push(tagName);
|
stack.push(tagName);
|
||||||
|
}
|
||||||
|
|
||||||
var attrs = {};
|
var attrs = {};
|
||||||
|
|
||||||
@ -409,11 +412,12 @@ function htmlParser(html, handler) {
|
|||||||
function parseEndTag(tag, tagName) {
|
function parseEndTag(tag, tagName) {
|
||||||
var pos = 0, i;
|
var pos = 0, i;
|
||||||
tagName = angular.lowercase(tagName);
|
tagName = angular.lowercase(tagName);
|
||||||
if (tagName)
|
if (tagName) {
|
||||||
// Find the closest opened tag of the same type
|
// Find the closest opened tag of the same type
|
||||||
for (pos = stack.length - 1; pos >= 0; pos--)
|
for (pos = stack.length - 1; pos >= 0; pos--) {
|
||||||
if (stack[pos] == tagName)
|
if (stack[pos] == tagName) break;
|
||||||
break;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pos >= 0) {
|
if (pos >= 0) {
|
||||||
// Close all the open elements, up the stack
|
// Close all the open elements, up the stack
|
||||||
@ -627,7 +631,7 @@ angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
|
|||||||
*/
|
*/
|
||||||
angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
|
angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
|
||||||
var LINKY_URL_REGEXP =
|
var LINKY_URL_REGEXP =
|
||||||
/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"”’]/i,
|
/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,
|
||||||
MAILTO_REGEXP = /^mailto:/i;
|
MAILTO_REGEXP = /^mailto:/i;
|
||||||
|
|
||||||
return function(text, target) {
|
return function(text, target) {
|
||||||
|
18
xstatic/pkg/angular/data/angular-touch.js
vendored
18
xstatic/pkg/angular/data/angular-touch.js
vendored
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @license AngularJS v1.3.18
|
* @license AngularJS v1.4.10
|
||||||
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
* (c) 2010-2015 Google, Inc. http://angularjs.org
|
||||||
* License: MIT
|
* License: MIT
|
||||||
*/
|
*/
|
||||||
(function(window, angular, undefined) {'use strict';
|
(function(window, angular, undefined) {'use strict';
|
||||||
@ -43,8 +43,7 @@ function nodeName_(element) {
|
|||||||
*
|
*
|
||||||
* Requires the {@link ngTouch `ngTouch`} module to be installed.
|
* Requires the {@link ngTouch `ngTouch`} module to be installed.
|
||||||
*
|
*
|
||||||
* `$swipe` is used by the `ngSwipeLeft` and `ngSwipeRight` directives in `ngTouch`, and by
|
* `$swipe` is used by the `ngSwipeLeft` and `ngSwipeRight` directives in `ngTouch`.
|
||||||
* `ngCarousel` in a separate component.
|
|
||||||
*
|
*
|
||||||
* # Usage
|
* # Usage
|
||||||
* The `$swipe` service is an object with a single method: `bind`. `bind` takes an element
|
* The `$swipe` service is an object with a single method: `bind`. `bind` takes an element
|
||||||
@ -105,7 +104,8 @@ ngTouch.factory('$swipe', [function() {
|
|||||||
* `$swipe` will listen for `mouse` and `touch` events.
|
* `$swipe` will listen for `mouse` and `touch` events.
|
||||||
*
|
*
|
||||||
* The four events are `start`, `move`, `end`, and `cancel`. `start`, `move`, and `end`
|
* The four events are `start`, `move`, `end`, and `cancel`. `start`, `move`, and `end`
|
||||||
* receive as a parameter a coordinates object of the form `{ x: 150, y: 310 }`.
|
* receive as a parameter a coordinates object of the form `{ x: 150, y: 310 }` and the raw
|
||||||
|
* `event`. `cancel` receives the raw `event` as its single parameter.
|
||||||
*
|
*
|
||||||
* `start` is called on either `mousedown` or `touchstart`. After this event, `$swipe` is
|
* `start` is called on either `mousedown` or `touchstart`. After this event, `$swipe` is
|
||||||
* watching for `touchmove` or `mousemove` events. These events are ignored until the total
|
* watching for `touchmove` or `mousemove` events. These events are ignored until the total
|
||||||
@ -263,7 +263,7 @@ ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement',
|
|||||||
// double-tapping, and then fire a click event.
|
// double-tapping, and then fire a click event.
|
||||||
//
|
//
|
||||||
// This delay sucks and makes mobile apps feel unresponsive.
|
// This delay sucks and makes mobile apps feel unresponsive.
|
||||||
// So we detect touchstart, touchmove, touchcancel and touchend ourselves and determine when
|
// So we detect touchstart, touchcancel and touchend ourselves and determine when
|
||||||
// the user has tapped on something.
|
// the user has tapped on something.
|
||||||
//
|
//
|
||||||
// What happens when the browser then generates a click event?
|
// What happens when the browser then generates a click event?
|
||||||
@ -275,7 +275,7 @@ ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement',
|
|||||||
// So the sequence for a tap is:
|
// So the sequence for a tap is:
|
||||||
// - global touchstart: Sets an "allowable region" at the point touched.
|
// - global touchstart: Sets an "allowable region" at the point touched.
|
||||||
// - element's touchstart: Starts a touch
|
// - element's touchstart: Starts a touch
|
||||||
// (- touchmove or touchcancel ends the touch, no click follows)
|
// (- touchcancel ends the touch, no click follows)
|
||||||
// - element's touchend: Determines if the tap is valid (didn't move too far away, didn't hold
|
// - element's touchend: Determines if the tap is valid (didn't move too far away, didn't hold
|
||||||
// too long) and fires the user's tap handler. The touchend also calls preventGhostClick().
|
// too long) and fires the user's tap handler. The touchend also calls preventGhostClick().
|
||||||
// - preventGhostClick() removes the allowable region the global touchstart created.
|
// - preventGhostClick() removes the allowable region the global touchstart created.
|
||||||
@ -426,10 +426,6 @@ ngTouch.directive('ngClick', ['$parse', '$timeout', '$rootElement',
|
|||||||
touchStartY = e.clientY;
|
touchStartY = e.clientY;
|
||||||
});
|
});
|
||||||
|
|
||||||
element.on('touchmove', function(event) {
|
|
||||||
resetState();
|
|
||||||
});
|
|
||||||
|
|
||||||
element.on('touchcancel', function(event) {
|
element.on('touchcancel', function(event) {
|
||||||
resetState();
|
resetState();
|
||||||
});
|
});
|
||||||
|
9733
xstatic/pkg/angular/data/angular.js
vendored
9733
xstatic/pkg/angular/data/angular.js
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
{"raw":"v1.3.18","major":1,"minor":3,"patch":18,"prerelease":[],"build":[],"version":"1.3.18","codeName":"collective-penmanship","full":"1.3.18","branch":"v1.3.x","cdn":{"raw":"v1.3.17","major":1,"minor":3,"patch":17,"prerelease":[],"build":[],"version":"1.3.17","docsUrl":"http://code.angularjs.org/1.3.17/docs"}}
|
{"raw":"v1.4.10","major":1,"minor":4,"patch":10,"prerelease":[],"build":[],"version":"1.4.10","codeName":"benignant-oscillation","full":"1.4.10","branch":"v1.4.x","cdn":{"raw":"v1.4.9","major":1,"minor":4,"patch":9,"prerelease":[],"build":[],"version":"1.4.9","docsUrl":"http://code.angularjs.org/1.4.9/docs"}}
|
@ -1 +1 @@
|
|||||||
1.3.18
|
1.4.10
|
Loading…
Reference in New Issue
Block a user