Commit 0a50f32a authored by Pascal Hartig's avatar Pascal Hartig

AngularJS: Upgrade to 1.2.16

parent e430314e
......@@ -2,11 +2,11 @@
"name": "todomvc-angular",
"version": "0.0.0",
"dependencies": {
"angular": "1.2.14",
"angular": "1.2.16",
"todomvc-common": "~0.1.4"
},
"devDependencies": {
"angular-mocks": "1.2.14",
"angular-route": "1.2.14"
"angular-mocks": "1.2.16",
"angular-route": "1.2.16"
}
}
/**
* @license AngularJS v1.2.14
* @license AngularJS v1.2.16
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
......@@ -87,7 +87,7 @@ function $RouteProvider(){
*
* If `template` is a function, it will be called with the following parameters:
*
* - `{Array.<Object>}` - route parameters extracted from the current
* - `{Array.<Object>}` - route parameters extracted from the current
* `$location.path()` by applying the current route
*
* - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
......@@ -95,7 +95,7 @@ function $RouteProvider(){
*
* If `templateUrl` is a function, it will be called with the following parameters:
*
* - `{Array.&lt;Object&gt;}` - route parameters extracted from the current
* - `{Array.<Object>}` - route parameters extracted from the current
* `$location.path()` by applying the current route
*
* - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
......@@ -252,7 +252,7 @@ function $RouteProvider(){
* - `$scope` - The current route scope.
* - `$template` - The current route template HTML.
*
* @property {Array.&lt;Object&gt;} routes Array of all configured routes.
* @property {Object} routes Object with all route configuration Objects as its properties.
*
* @description
* `$route` is used for deep-linking URLs to controllers and views (HTML partials).
......@@ -267,102 +267,106 @@ function $RouteProvider(){
* {@link ngRoute.$routeParams `$routeParams`} service.
*
* @example
This example shows how changing the URL hash causes the `$route` to match a route against the
URL, and the `ngView` pulls in the partial.
Note that this example is using {@link ng.directive:script inlined templates}
to get it working on jsfiddle as well.
<example name="$route-service" module="ngRouteExample" deps="angular-route.js" fixBase="true">
<file name="index.html">
<div ng-controller="MainCntl">
Choose:
<a href="Book/Moby">Moby</a> |
<a href="Book/Moby/ch/1">Moby: Ch1</a> |
<a href="Book/Gatsby">Gatsby</a> |
<a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
<a href="Book/Scarlet">Scarlet Letter</a><br/>
<div ng-view></div>
<hr />
<pre>$location.path() = {{$location.path()}}</pre>
<pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
<pre>$route.current.params = {{$route.current.params}}</pre>
<pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
<pre>$routeParams = {{$routeParams}}</pre>
</div>
</file>
<file name="book.html">
controller: {{name}}<br />
Book Id: {{params.bookId}}<br />
</file>
<file name="chapter.html">
controller: {{name}}<br />
Book Id: {{params.bookId}}<br />
Chapter Id: {{params.chapterId}}
</file>
<file name="script.js">
angular.module('ngRouteExample', ['ngRoute'])
.config(function($routeProvider, $locationProvider) {
$routeProvider.when('/Book/:bookId', {
templateUrl: 'book.html',
controller: BookCntl,
resolve: {
// I will cause a 1 second delay
delay: function($q, $timeout) {
var delay = $q.defer();
$timeout(delay.resolve, 1000);
return delay.promise;
}
}
});
$routeProvider.when('/Book/:bookId/ch/:chapterId', {
templateUrl: 'chapter.html',
controller: ChapterCntl
});
// configure html5 to get links working on jsfiddle
$locationProvider.html5Mode(true);
});
function MainCntl($scope, $route, $routeParams, $location) {
$scope.$route = $route;
$scope.$location = $location;
$scope.$routeParams = $routeParams;
}
function BookCntl($scope, $routeParams) {
$scope.name = "BookCntl";
$scope.params = $routeParams;
}
function ChapterCntl($scope, $routeParams) {
$scope.name = "ChapterCntl";
$scope.params = $routeParams;
}
</file>
<file name="protractor.js" type="protractor">
it('should load and compile correct template', function() {
element(by.linkText('Moby: Ch1')).click();
var content = element(by.css('[ng-view]')).getText();
expect(content).toMatch(/controller\: ChapterCntl/);
expect(content).toMatch(/Book Id\: Moby/);
expect(content).toMatch(/Chapter Id\: 1/);
element(by.partialLinkText('Scarlet')).click();
content = element(by.css('[ng-view]')).getText();
expect(content).toMatch(/controller\: BookCntl/);
expect(content).toMatch(/Book Id\: Scarlet/);
});
</file>
</example>
* This example shows how changing the URL hash causes the `$route` to match a route against the
* URL, and the `ngView` pulls in the partial.
*
* Note that this example is using {@link ng.directive:script inlined templates}
* to get it working on jsfiddle as well.
*
* <example name="$route-service" module="ngRouteExample"
* deps="angular-route.js" fixBase="true">
* <file name="index.html">
* <div ng-controller="MainController">
* Choose:
* <a href="Book/Moby">Moby</a> |
* <a href="Book/Moby/ch/1">Moby: Ch1</a> |
* <a href="Book/Gatsby">Gatsby</a> |
* <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
* <a href="Book/Scarlet">Scarlet Letter</a><br/>
*
* <div ng-view></div>
*
* <hr />
*
* <pre>$location.path() = {{$location.path()}}</pre>
* <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
* <pre>$route.current.params = {{$route.current.params}}</pre>
* <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
* <pre>$routeParams = {{$routeParams}}</pre>
* </div>
* </file>
*
* <file name="book.html">
* controller: {{name}}<br />
* Book Id: {{params.bookId}}<br />
* </file>
*
* <file name="chapter.html">
* controller: {{name}}<br />
* Book Id: {{params.bookId}}<br />
* Chapter Id: {{params.chapterId}}
* </file>
*
* <file name="script.js">
* angular.module('ngRouteExample', ['ngRoute'])
*
* .controller('MainController', function($scope, $route, $routeParams, $location) {
* $scope.$route = $route;
* $scope.$location = $location;
* $scope.$routeParams = $routeParams;
* })
*
* .controller('BookController', function($scope, $routeParams) {
* $scope.name = "BookController";
* $scope.params = $routeParams;
* })
*
* .controller('ChapterController', function($scope, $routeParams) {
* $scope.name = "ChapterController";
* $scope.params = $routeParams;
* })
*
* .config(function($routeProvider, $locationProvider) {
* $routeProvider
* .when('/Book/:bookId', {
* templateUrl: 'book.html',
* controller: 'BookController',
* resolve: {
* // I will cause a 1 second delay
* delay: function($q, $timeout) {
* var delay = $q.defer();
* $timeout(delay.resolve, 1000);
* return delay.promise;
* }
* }
* })
* .when('/Book/:bookId/ch/:chapterId', {
* templateUrl: 'chapter.html',
* controller: 'ChapterController'
* });
*
* // configure html5 to get links working on jsfiddle
* $locationProvider.html5Mode(true);
* });
*
* </file>
*
* <file name="protractor.js" type="protractor">
* it('should load and compile correct template', function() {
* element(by.linkText('Moby: Ch1')).click();
* var content = element(by.css('[ng-view]')).getText();
* expect(content).toMatch(/controller\: ChapterController/);
* expect(content).toMatch(/Book Id\: Moby/);
* expect(content).toMatch(/Chapter Id\: 1/);
*
* element(by.partialLinkText('Scarlet')).click();
*
* content = element(by.css('[ng-view]')).getText();
* expect(content).toMatch(/controller\: BookController/);
* expect(content).toMatch(/Book Id\: Scarlet/);
* });
* </file>
* </example>
*/
/**
......@@ -675,7 +679,7 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory);
deps="angular-route.js;angular-animate.js"
animations="true" fixBase="true">
<file name="index.html">
<div ng-controller="MainCntl as main">
<div ng-controller="MainCtrl as main">
Choose:
<a href="Book/Moby">Moby</a> |
<a href="Book/Moby/ch/1">Moby: Ch1</a> |
......@@ -754,52 +758,53 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory);
</file>
<file name="script.js">
angular.module('ngViewExample', ['ngRoute', 'ngAnimate'],
angular.module('ngViewExample', ['ngRoute', 'ngAnimate'])
.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider.when('/Book/:bookId', {
$routeProvider
.when('/Book/:bookId', {
templateUrl: 'book.html',
controller: BookCntl,
controller: 'BookCtrl',
controllerAs: 'book'
});
$routeProvider.when('/Book/:bookId/ch/:chapterId', {
})
.when('/Book/:bookId/ch/:chapterId', {
templateUrl: 'chapter.html',
controller: ChapterCntl,
controller: 'ChapterCtrl',
controllerAs: 'chapter'
});
// configure html5 to get links working on jsfiddle
$locationProvider.html5Mode(true);
});
function MainCntl($route, $routeParams, $location) {
}])
.controller('MainCtrl', ['$route', '$routeParams', '$location',
function($route, $routeParams, $location) {
this.$route = $route;
this.$location = $location;
this.$routeParams = $routeParams;
}
function BookCntl($routeParams) {
this.name = "BookCntl";
}])
.controller('BookCtrl', ['$routeParams', function($routeParams) {
this.name = "BookCtrl";
this.params = $routeParams;
}
function ChapterCntl($routeParams) {
this.name = "ChapterCntl";
}])
.controller('ChapterCtrl', ['$routeParams', function($routeParams) {
this.name = "ChapterCtrl";
this.params = $routeParams;
}
}]);
</file>
<file name="protractor.js" type="protractor">
it('should load and compile correct template', function() {
element(by.linkText('Moby: Ch1')).click();
var content = element(by.css('[ng-view]')).getText();
expect(content).toMatch(/controller\: ChapterCntl/);
expect(content).toMatch(/controller\: ChapterCtrl/);
expect(content).toMatch(/Book Id\: Moby/);
expect(content).toMatch(/Chapter Id\: 1/);
element(by.partialLinkText('Scarlet')).click();
content = element(by.css('[ng-view]')).getText();
expect(content).toMatch(/controller\: BookCntl/);
expect(content).toMatch(/controller\: BookCtrl/);
expect(content).toMatch(/Book Id\: Scarlet/);
});
</file>
......
/**
* @license AngularJS v1.2.14
* @license AngularJS v1.2.16
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
......@@ -68,7 +68,7 @@ function minErr(module) {
return match;
});
message = message + '\nhttp://errors.angularjs.org/1.2.14/' +
message = message + '\nhttp://errors.angularjs.org/1.2.16/' +
(module ? module + '/' : '') + code;
for (i = 2; i < arguments.length; i++) {
message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
......@@ -124,6 +124,7 @@ function minErr(module) {
-isWindow,
-isScope,
-isFile,
-isBlob,
-isBoolean,
-trim,
-isElement,
......@@ -645,6 +646,11 @@ function isFile(obj) {
}
function isBlob(obj) {
return toString.call(obj) === '[object Blob]';
}
function isBoolean(value) {
return typeof value === 'boolean';
}
......@@ -1314,7 +1320,42 @@ function angularInit(element, bootstrap) {
* Note that ngScenario-based end-to-end tests cannot use this function to bootstrap manually.
* They must use {@link ng.directive:ngApp ngApp}.
*
* @param {Element} element DOM element which is the root of angular application.
* Angular will detect if it has been loaded into the browser more than once and only allow the
* first loaded script to be bootstrapped and will report a warning to the browser console for
* each of the subsequent scripts. This prevents strange results in applications, where otherwise
* multiple instances of Angular try to work on the DOM.
*
* <example name="multi-bootstrap" module="multi-bootstrap">
* <file name="index.html">
* <script src="../../../angular.js"></script>
* <div ng-controller="BrokenTable">
* <table>
* <tr>
* <th ng-repeat="heading in headings">{{heading}}</th>
* </tr>
* <tr ng-repeat="filling in fillings">
* <td ng-repeat="fill in filling">{{fill}}</td>
* </tr>
* </table>
* </div>
* </file>
* <file name="controller.js">
* var app = angular.module('multi-bootstrap', [])
*
* .controller('BrokenTable', function($scope) {
* $scope.headings = ['One', 'Two', 'Three'];
* $scope.fillings = [[1, 2, 3], ['A', 'B', 'C'], [7, 8, 9]];
* });
* </file>
* <file name="protractor.js" type="protractor">
* it('should only insert one table cell for each item in $scope.fillings', function() {
* expect(element.all(by.css('td')).count())
* .toBe(9);
* });
* </file>
* </example>
*
* @param {DOMElement} element DOM element which is the root of angular application.
* @param {Array<String|Function|Array>=} modules an array of modules to load into the application.
* Each item in the array should be the name of a predefined module or a (DI annotated)
* function that will be invoked by the injector as a run block.
......@@ -1531,16 +1572,16 @@ function setupModuleLoader(window) {
* myModule.value('appName', 'MyCoolApp');
*
* // configure existing services inside initialization blocks.
* myModule.config(function($locationProvider) {
* myModule.config(['$locationProvider', function($locationProvider) {
* // Configure existing providers
* $locationProvider.hashPrefix('!');
* });
* }]);
* ```
*
* Then you can create an injector and load your modules like this:
*
* ```js
* var injector = angular.injector(['ng', 'MyModule'])
* var injector = angular.injector(['ng', 'myModule'])
* ```
*
* However it's more likely that you'll just use
......@@ -1548,8 +1589,8 @@ function setupModuleLoader(window) {
* {@link angular.bootstrap} to simplify this process for you.
*
* @param {!string} name The name of the module to create or retrieve.
* @param {Array.<string>=} requires If specified then new module is being created. If
* unspecified then the the module is being retrieved for further configuration.
<<<<<* @param {!Array.<string>=} requires If specified then new module is being created. If
>>>>>* unspecified then the module is being retrieved for further configuration.
* @param {Function} configFn Optional configuration function for the module. Same as
* {@link angular.Module#config Module#config()}.
* @returns {module} new module with the {@link angular.Module} api.
......@@ -1590,7 +1631,6 @@ function setupModuleLoader(window) {
* @ngdoc property
* @name angular.Module#requires
* @module ng
* @propertyOf angular.Module
* @returns {Array.<string>} List of module names which must be loaded before this module.
* @description
* Holds the list of modules which the injector will load before the current module is
......@@ -1602,7 +1642,6 @@ function setupModuleLoader(window) {
* @ngdoc property
* @name angular.Module#name
* @module ng
* @propertyOf angular.Module
* @returns {string} Name of the module.
* @description
*/
......@@ -1880,11 +1919,11 @@ function setupModuleLoader(window) {
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
*/
var version = {
full: '1.2.14', // all of these placeholder strings will be replaced by grunt's
full: '1.2.16', // all of these placeholder strings will be replaced by grunt's
major: 1, // package task
minor: 2,
dot: 14,
codeName: 'feisty-cryokinesis'
dot: 16,
codeName: 'badger-enumeration'
};
......@@ -2187,6 +2226,75 @@ function jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArgu
}
}
var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
var HTML_REGEXP = /<|&#?\w+;/;
var TAG_NAME_REGEXP = /<([\w:]+)/;
var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;
var wrapMap = {
'option': [1, '<select multiple="multiple">', '</select>'],
'thead': [1, '<table>', '</table>'],
'col': [2, '<table><colgroup>', '</colgroup></table>'],
'tr': [2, '<table><tbody>', '</tbody></table>'],
'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],
'_default': [0, "", ""]
};
wrapMap.optgroup = wrapMap.option;
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;
function jqLiteIsTextNode(html) {
return !HTML_REGEXP.test(html);
}
function jqLiteBuildFragment(html, context) {
var elem, tmp, tag, wrap,
fragment = context.createDocumentFragment(),
nodes = [], i, j, jj;
if (jqLiteIsTextNode(html)) {
// Convert non-html into a text node
nodes.push(context.createTextNode(html));
} else {
tmp = fragment.appendChild(context.createElement('div'));
// Convert html into DOM nodes
tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
wrap = wrapMap[tag] || wrapMap._default;
tmp.innerHTML = '<div>&#160;</div>' +
wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2];
tmp.removeChild(tmp.firstChild);
// Descend through wrappers to the right content
i = wrap[0];
while (i--) {
tmp = tmp.lastChild;
}
for (j=0, jj=tmp.childNodes.length; j<jj; ++j) nodes.push(tmp.childNodes[j]);
tmp = fragment.firstChild;
tmp.textContent = "";
}
// Remove wrapper from fragment
fragment.textContent = "";
fragment.innerHTML = ""; // Clear inner HTML
return nodes;
}
function jqLiteParseHTML(html, context) {
context = context || document;
var parsed;
if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {
return [context.createElement(parsed[1])];
}
return jqLiteBuildFragment(html, context);
}
/////////////////////////////////////////////
function JQLite(element) {
if (element instanceof JQLite) {
......@@ -2203,14 +2311,9 @@ function JQLite(element) {
}
if (isString(element)) {
var div = document.createElement('div');
// Read about the NoScope elements here:
// http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx
div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!
div.removeChild(div.firstChild); // remove the superfluous div
jqLiteAddNodes(this, div.childNodes);
jqLiteAddNodes(this, jqLiteParseHTML(element));
var fragment = jqLite(document.createDocumentFragment());
fragment.append(this); // detach the elements from the temporary DOM div.
fragment.append(this);
} else {
jqLiteAddNodes(this, element);
}
......@@ -2372,11 +2475,15 @@ function jqLiteInheritedData(element, name, value) {
var names = isArray(name) ? name : [name];
while (element.length) {
var node = element[0];
for (var i = 0, ii = names.length; i < ii; i++) {
if ((value = element.data(names[i])) !== undefined) return value;
}
element = element.parent();
// If dealing with a document fragment node with a host element, and no parent, use the host
// element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
// to lookup parent controllers.
element = jqLite(node.parentNode || (node.nodeType === 11 && node.host));
}
}
......@@ -2465,7 +2572,7 @@ forEach({
return jqLite(element).data('$isolateScope') || jqLite(element).data('$isolateScopeNoTemplate');
},
controller: jqLiteController ,
controller: jqLiteController,
injector: function(element) {
return jqLiteInheritedData(element, '$injector');
......@@ -4338,7 +4445,6 @@ function Browser(window, document, $log, $sniffer) {
/**
* @name $browser#onUrlChange
* @TODO(vojta): refactor to use node's syntax for events
*
* @description
* Register callback function that will be called, when url changes.
......@@ -4359,6 +4465,7 @@ function Browser(window, document, $log, $sniffer) {
* @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.
*/
self.onUrlChange = function(callback) {
// TODO(vojta): refactor to use node's syntax for events
if (!urlChangeInit) {
// We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)
// don't fire popstate when user change the address bar and don't fire hashchange when url
......@@ -4532,7 +4639,8 @@ function $BrowserProvider(){
* @name $cacheFactory
*
* @description
* Factory that constructs cache objects and gives access to them.
* Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to
* them.
*
* ```js
*
......@@ -4564,6 +4672,46 @@ function $BrowserProvider(){
* - `{void}` `removeAll()` — Removes all cached values.
* - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
*
* @example
<example module="cacheExampleApp">
<file name="index.html">
<div ng-controller="CacheController">
<input ng-model="newCacheKey" placeholder="Key">
<input ng-model="newCacheValue" placeholder="Value">
<button ng-click="put(newCacheKey, newCacheValue)">Cache</button>
<p ng-if="keys.length">Cached Values</p>
<div ng-repeat="key in keys">
<span ng-bind="key"></span>
<span>: </span>
<b ng-bind="cache.get(key)"></b>
</div>
<p>Cache Info</p>
<div ng-repeat="(key, value) in cache.info()">
<span ng-bind="key"></span>
<span>: </span>
<b ng-bind="value"></b>
</div>
</div>
</file>
<file name="script.js">
angular.module('cacheExampleApp', []).
controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {
$scope.keys = [];
$scope.cache = $cacheFactory('cacheId');
$scope.put = function(key, value) {
$scope.cache.put(key, value);
$scope.keys.push(key);
};
}]);
</file>
<file name="style.css">
p {
margin: 10px 0 3px;
}
</file>
</example>
*/
function $CacheFactoryProvider() {
......@@ -4583,8 +4731,65 @@ function $CacheFactoryProvider() {
freshEnd = null,
staleEnd = null;
/**
* @ngdoc type
* @name $cacheFactory.Cache
*
* @description
* A cache object used to store and retrieve data, primarily used by
* {@link $http $http} and the {@link ng.directive:script script} directive to cache
* templates and other data.
*
* ```js
* angular.module('superCache')
* .factory('superCache', ['$cacheFactory', function($cacheFactory) {
* return $cacheFactory('super-cache');
* }]);
* ```
*
* Example test:
*
* ```js
* it('should behave like a cache', inject(function(superCache) {
* superCache.put('key', 'value');
* superCache.put('another key', 'another value');
*
* expect(superCache.info()).toEqual({
* id: 'super-cache',
* size: 2
* });
*
* superCache.remove('another key');
* expect(superCache.get('another key')).toBeUndefined();
*
* superCache.removeAll();
* expect(superCache.info()).toEqual({
* id: 'super-cache',
* size: 0
* });
* }));
* ```
*/
return caches[cacheId] = {
/**
* @ngdoc method
* @name $cacheFactory.Cache#put
* @function
*
* @description
* Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be
* retrieved later, and incrementing the size of the cache if the key was not already
* present in the cache. If behaving like an LRU cache, it will also remove stale
* entries from the set.
*
* It will not insert undefined values into the cache.
*
* @param {string} key the key under which the cached data is stored.
* @param {*} value the value to store alongside the key. If it is undefined, the key
* will not be stored.
* @returns {*} the value stored.
*/
put: function(key, value) {
if (capacity < Number.MAX_VALUE) {
var lruEntry = lruHash[key] || (lruHash[key] = {key: key});
......@@ -4603,7 +4808,17 @@ function $CacheFactoryProvider() {
return value;
},
/**
* @ngdoc method
* @name $cacheFactory.Cache#get
* @function
*
* @description
* Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.
*
* @param {string} key the key of the data to be retrieved
* @returns {*} the value stored.
*/
get: function(key) {
if (capacity < Number.MAX_VALUE) {
var lruEntry = lruHash[key];
......@@ -4617,6 +4832,16 @@ function $CacheFactoryProvider() {
},
/**
* @ngdoc method
* @name $cacheFactory.Cache#remove
* @function
*
* @description
* Removes an entry from the {@link $cacheFactory.Cache Cache} object.
*
* @param {string} key the key of the entry to be removed
*/
remove: function(key) {
if (capacity < Number.MAX_VALUE) {
var lruEntry = lruHash[key];
......@@ -4635,6 +4860,14 @@ function $CacheFactoryProvider() {
},
/**
* @ngdoc method
* @name $cacheFactory.Cache#removeAll
* @function
*
* @description
* Clears the cache object of any entries.
*/
removeAll: function() {
data = {};
size = 0;
......@@ -4643,6 +4876,15 @@ function $CacheFactoryProvider() {
},
/**
* @ngdoc method
* @name $cacheFactory.Cache#destroy
* @function
*
* @description
* Destroys the {@link $cacheFactory.Cache Cache} object entirely,
* removing it from the {@link $cacheFactory $cacheFactory} set.
*/
destroy: function() {
data = null;
stats = null;
......@@ -4651,6 +4893,22 @@ function $CacheFactoryProvider() {
},
/**
* @ngdoc method
* @name $cacheFactory.Cache#info
* @function
*
* @description
* Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.
*
* @returns {object} an object with the following properties:
* <ul>
* <li>**id**: the id of the cache instance</li>
* <li>**size**: the number of entries kept in the cache instance</li>
* <li>**...**: any additional properties from the options object when creating the
* cache.</li>
* </ul>
*/
info: function() {
return extend({}, stats, {size: size});
}
......@@ -4735,15 +4993,11 @@ function $CacheFactoryProvider() {
* `$templateCache` service directly.
*
* Adding via the `script` tag:
*
* ```html
* <html ng-app>
* <head>
* <script type="text/ng-template" id="templateId.html">
* This is the content of the template
* <p>This is the content of the template</p>
* </script>
* </head>
* ...
* </html>
* ```
*
* **Note:** the `script` tag containing the template does not need to be included in the `head` of
......@@ -4841,6 +5095,7 @@ function $TemplateCacheProvider() {
* restrict: 'A',
* scope: false,
* controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
* controllerAs: 'stringAlias',
* require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
* compile: function compile(tElement, tAttrs, transclude) {
* return {
......@@ -5058,6 +5313,16 @@ function $TemplateCacheProvider() {
* apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration
* should be done in a linking function rather than in a compile function.
* </div>
* <div class="alert alert-warning">
* **Note:** The compile function cannot handle directives that recursively use themselves in their
* own templates or compile functions. Compiling these directives results in an infinite loop and a
* stack overflow errors.
*
* This can be avoided by manually using $compile in the postLink function to imperatively compile
* a directive's template instead of relying on automatic template compilation via `template` or
* `templateUrl` declaration or manual compilation inside the compile function.
* </div>
*
* <div class="alert alert-error">
* **Note:** The `transclude` function that is passed to the compile function is deprecated, as it
......@@ -5279,8 +5544,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var hasDirectives = {},
Suffix = 'Directive',
COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,
CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/,
TABLE_CONTENT_REGEXP = /^<\s*(tr|th|td|tbody)(\s+[^>]*)?>/i;
CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/;
// Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
// The assumption is that future DOM event attribute names will begin with
......@@ -6022,7 +6286,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (directive.replace) {
replaceDirective = directive;
$template = directiveTemplateContents(directiveValue);
if (jqLiteIsTextNode(directiveValue)) {
$template = [];
} else {
$template = jqLite(directiveValue);
}
compileNode = $template[0];
if ($template.length != 1 || compileNode.nodeType !== 1) {
......@@ -6421,28 +6689,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
function directiveTemplateContents(template) {
var type;
template = trim(template);
if ((type = TABLE_CONTENT_REGEXP.exec(template))) {
type = type[1].toLowerCase();
var table = jqLite('<table>' + template + '</table>'),
tbody = table.children('tbody'),
leaf = /(td|th)/.test(type) && table.find('tr');
if (tbody.length && type !== 'tbody') {
table = tbody;
}
if (leaf && leaf.length) {
table = leaf;
}
return table.contents();
}
return jqLite('<div>' +
template +
'</div>').contents();
}
function compileTemplateUrl(directives, $compileNode, tAttrs,
$rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {
var linkQueue = [],
......@@ -6467,7 +6713,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
content = denormalizeTemplate(content);
if (origAsyncDirective.replace) {
$template = directiveTemplateContents(content);
if (jqLiteIsTextNode(content)) {
$template = [];
} else {
$template = jqLite(content);
}
compileNode = $template[0];
if ($template.length != 1 || compileNode.nodeType !== 1) {
......@@ -6905,6 +7155,22 @@ function $ControllerProvider() {
*
* @description
* A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.
*
* @example
<example>
<file name="index.html">
<div ng-controller="MainCtrl">
<p>$document title: <b ng-bind="title"></b></p>
<p>window.document title: <b ng-bind="windowTitle"></b></p>
</div>
</file>
<file name="script.js">
function MainCtrl($scope, $document) {
$scope.title = $document[0].title;
$scope.windowTitle = angular.element(window.document)[0].title;
}
</file>
</example>
*/
function $DocumentProvider(){
this.$get = ['$window', function(window){
......@@ -7055,7 +7321,7 @@ function $HttpProvider() {
// transform outgoing request data
transformRequest: [function(d) {
return isObject(d) && !isFile(d) ? toJson(d) : d;
return isObject(d) && !isFile(d) && !isBlob(d) ? toJson(d) : d;
}],
// default headers
......@@ -7188,9 +7454,8 @@ function $HttpProvider() {
*
* # Shortcut methods
*
* Since all invocations of the $http service require passing in an HTTP method and URL, and
* POST/PUT requests require request data to be provided as well, shortcut methods
* were created:
* Shortcut methods are also available. All shortcut methods require passing in the URL, and
* request data must be passed in for POST/PUT requests.
*
* ```js
* $http.get('/someUrl').success(successCallback);
......@@ -7230,7 +7495,7 @@ function $HttpProvider() {
*
* ```
* module.run(function($http) {
* $http.defaults.headers.common.Authentication = 'Basic YmVlcDpib29w'
* $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'
* });
* ```
*
......@@ -7524,8 +7789,9 @@ function $HttpProvider() {
* - **status** – `{number}` – HTTP status code of the response.
* - **headers** – `{function([headerName])}` – Header getter function.
* - **config** – `{Object}` – The configuration object that was used to generate the request.
* - **statusText** – `{string}` – HTTP status text of the response.
*
* @property {Array.&ltObject&gt;} pendingRequests Array of config objects for currently pending
* @property {Array.<Object>} pendingRequests Array of config objects for currently pending
* requests. This is primarily meant to be used for debugging purposes.
*
*
......@@ -7827,7 +8093,6 @@ function $HttpProvider() {
/**
* @ngdoc property
* @name $http#defaults
* @propertyOf ng.$http
*
* @description
* Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of
......@@ -7899,9 +8164,9 @@ function $HttpProvider() {
} else {
// serving from cache
if (isArray(cachedResp)) {
resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));
resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]), cachedResp[3]);
} else {
resolvePromise(cachedResp, 200, {});
resolvePromise(cachedResp, 200, {}, 'OK');
}
}
} else {
......@@ -7925,17 +8190,17 @@ function $HttpProvider() {
* - resolves the raw $http promise
* - calls $apply
*/
function done(status, response, headersString) {
function done(status, response, headersString, statusText) {
if (cache) {
if (isSuccess(status)) {
cache.put(url, [status, response, parseHeaders(headersString)]);
cache.put(url, [status, response, parseHeaders(headersString), statusText]);
} else {
// remove promise from the cache
cache.remove(url);
}
}
resolvePromise(response, status, headersString);
resolvePromise(response, status, headersString, statusText);
if (!$rootScope.$$phase) $rootScope.$apply();
}
......@@ -7943,7 +8208,7 @@ function $HttpProvider() {
/**
* Resolves the raw $http promise.
*/
function resolvePromise(response, status, headers) {
function resolvePromise(response, status, headers, statusText) {
// normalize internal statuses to 0
status = Math.max(status, 0);
......@@ -7951,7 +8216,8 @@ function $HttpProvider() {
data: response,
status: status,
headers: headersGetter(headers),
config: config
config: config,
statusText : statusText
});
}
......@@ -8085,7 +8351,8 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
completeRequest(callback,
status || xhr.status,
response,
responseHeaders);
responseHeaders,
xhr.statusText || '');
}
};
......@@ -8126,20 +8393,23 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
xhr && xhr.abort();
}
function completeRequest(callback, status, response, headersString) {
function completeRequest(callback, status, response, headersString, statusText) {
// cancel timeout and subsequent timeout promise resolution
timeoutId && $browserDefer.cancel(timeoutId);
jsonpDone = xhr = null;
// fix status code when it is 0 (0 status is undocumented).
// Occurs when accessing file resources.
// On Android 4.1 stock browser it occurs while retrieving files from application cache.
status = (status === 0) ? (response ? 200 : 404) : status;
// Occurs when accessing file resources or on Android 4.1 stock browser
// while retrieving files from application cache.
if (status === 0) {
status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;
}
// normalize IE bug (http://bugs.jquery.com/ticket/1450)
status = status == 1223 ? 204 : status;
status = status === 1223 ? 204 : status;
statusText = statusText || '';
callback(status, response, headersString);
callback(status, response, headersString, statusText);
$browser.$$completeOutstandingRequest(noop);
}
};
......@@ -8578,7 +8848,7 @@ function $IntervalProvider() {
* @description
* Cancels a task associated with the `promise`.
*
* @param {number} promise Promise returned by the `$interval` function.
* @param {promise} promise returned by the `$interval` function.
* @returns {boolean} Returns `true` if the task was successfully canceled.
*/
interval.cancel = function(promise) {
......@@ -9175,8 +9445,7 @@ function locationGetterSetter(property, preprocess) {
* - Clicks on a link.
* - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).
*
* For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular
* Services: Using $location}
* For more information see {@link guide/$location Developer Guide: Using $location}
*/
/**
......@@ -9912,7 +10181,11 @@ var Parser = function (lexer, $filter, options) {
this.options = options;
};
Parser.ZERO = function () { return 0; };
Parser.ZERO = extend(function () {
return 0;
}, {
constant: true
});
Parser.prototype = {
constructor: Parser,
......@@ -10904,7 +11177,7 @@ function $ParseProvider() {
*
* Because `finally` is a reserved word in JavaScript and reserved keywords are not supported as
* property names by ES3, you'll need to invoke the method like `promise['finally'](callback)` to
* make your code IE8 compatible.
* make your code IE8 and Android 2.x compatible.
*
* # Chaining promises
*
......@@ -11317,21 +11590,32 @@ function qFactory(nextTick, exceptionHandler) {
}
function $$RAFProvider(){ //rAF
this.$get = ['$window', function($window) {
this.$get = ['$window', '$timeout', function($window, $timeout) {
var requestAnimationFrame = $window.requestAnimationFrame ||
$window.webkitRequestAnimationFrame;
$window.webkitRequestAnimationFrame ||
$window.mozRequestAnimationFrame;
var cancelAnimationFrame = $window.cancelAnimationFrame ||
$window.webkitCancelAnimationFrame;
$window.webkitCancelAnimationFrame ||
$window.mozCancelAnimationFrame ||
$window.webkitCancelRequestAnimationFrame;
var raf = function(fn) {
var rafSupported = !!requestAnimationFrame;
var raf = rafSupported
? function(fn) {
var id = requestAnimationFrame(fn);
return function() {
cancelAnimationFrame(id);
};
}
: function(fn) {
var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666
return function() {
$timeout.cancel(timer);
};
};
raf.supported = !!requestAnimationFrame;
raf.supported = rafSupported;
return raf;
}];
......@@ -11476,7 +11760,6 @@ function $RootScopeProvider(){
/**
* @ngdoc property
* @name $rootScope.Scope#$id
* @propertyOf ng.$rootScope.Scope
* @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for
* debugging.
*/
......@@ -11647,7 +11930,8 @@ function $RootScopeProvider(){
* - `function(newValue, oldValue, scope)`: called with current and previous values as
* parameters.
*
* @param {boolean=} objectEquality Compare object for equality rather than for reference.
* @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of
* comparing for reference equality.
* @returns {function()} Returns a deregistration function for this listener.
*/
$watch: function(watchExp, listener, objectEquality) {
......@@ -11736,30 +12020,40 @@ function $RootScopeProvider(){
* {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the
* collection will trigger a call to the `listener`.
*
* @param {function(newCollection, oldCollection, scope)} listener a callback function that is
* fired with both the `newCollection` and `oldCollection` as parameters.
* The `newCollection` object is the newly modified data obtained from the `obj` expression
* and the `oldCollection` object is a copy of the former collection data.
* The `scope` refers to the current scope.
* @param {function(newCollection, oldCollection, scope)} listener a callback function called
* when a change is detected.
* - The `newCollection` object is the newly modified data obtained from the `obj` expression
* - The `oldCollection` object is a copy of the former collection data.
* Due to performance considerations, the`oldCollection` value is computed only if the
* `listener` function declares two or more arguments.
* - The `scope` argument refers to the current scope.
*
* @returns {function()} Returns a de-registration function for this listener. When the
* de-registration function is executed, the internal watch operation is terminated.
*/
$watchCollection: function(obj, listener) {
var self = this;
var oldValue;
// the current value, updated on each dirty-check run
var newValue;
// a shallow copy of the newValue from the last dirty-check run,
// updated to match newValue during dirty-check run
var oldValue;
// a shallow copy of the newValue from when the last change happened
var veryOldValue;
// only track veryOldValue if the listener is asking for it
var trackVeryOldValue = (listener.length > 1);
var changeDetected = 0;
var objGetter = $parse(obj);
var internalArray = [];
var internalObject = {};
var initRun = true;
var oldLength = 0;
function $watchCollectionWatch() {
newValue = objGetter(self);
var newLength, key;
if (!isObject(newValue)) {
if (!isObject(newValue)) { // if primitive
if (oldValue !== newValue) {
oldValue = newValue;
changeDetected++;
......@@ -11781,7 +12075,9 @@ function $RootScopeProvider(){
}
// copy the items to oldValue and look for changes.
for (var i = 0; i < newLength; i++) {
if (oldValue[i] !== newValue[i]) {
var bothNaN = (oldValue[i] !== oldValue[i]) &&
(newValue[i] !== newValue[i]);
if (!bothNaN && (oldValue[i] !== newValue[i])) {
changeDetected++;
oldValue[i] = newValue[i];
}
......@@ -11825,7 +12121,32 @@ function $RootScopeProvider(){
}
function $watchCollectionAction() {
listener(newValue, oldValue, self);
if (initRun) {
initRun = false;
listener(newValue, newValue, self);
} else {
listener(newValue, veryOldValue, self);
}
// make a copy for the next time a collection is changed
if (trackVeryOldValue) {
if (!isObject(newValue)) {
//primitive
veryOldValue = newValue;
} else if (isArrayLike(newValue)) {
veryOldValue = new Array(newValue.length);
for (var i = 0; i < newValue.length; i++) {
veryOldValue[i] = newValue[i];
}
} else { // if object
veryOldValue = {};
for (var key in newValue) {
if (hasOwnProperty.call(newValue, key)) {
veryOldValue[key] = newValue[key];
}
}
}
}
}
return this.$watch($watchCollectionWatch, $watchCollectionAction);
......@@ -11989,7 +12310,6 @@ function $RootScopeProvider(){
/**
* @ngdoc event
* @name $rootScope.Scope#$destroy
* @eventOf ng.$rootScope.Scope
* @eventType broadcast on scope being destroyed
*
* @description
......@@ -12032,15 +12352,32 @@ function $RootScopeProvider(){
forEach(this.$$listenerCount, bind(null, decrementListenerCount, this));
// sever all the references to parent scopes (after this cleanup, the current scope should
// not be retained by any of our references and should be eligible for garbage collection)
if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;
// This is bogus code that works around Chrome's GC leak
// see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
// All of the code below is bogus code that works around V8's memory leak via optimized code
// and inline caches.
//
// see:
// - https://code.google.com/p/v8/issues/detail?id=2073#c26
// - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909
// - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =
this.$$childTail = null;
this.$$childTail = this.$root = null;
// don't reset these to null in case some async task tries to register a listener/watch/task
this.$$listeners = {};
this.$$watchers = this.$$asyncQueue = this.$$postDigestQueue = [];
// prevent NPEs since these methods have references to properties we nulled out
this.$destroy = this.$digest = this.$apply = noop;
this.$on = this.$watch = function() { return noop; };
},
/**
......@@ -12207,7 +12544,7 @@ function $RootScopeProvider(){
* - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
*
* @param {string} name Event name to listen on.
* @param {function(event, args...)} listener Function to call when the event is emitted.
* @param {function(event, ...args)} listener Function to call when the event is emitted.
* @returns {function()} Returns a deregistration function for this listener.
*/
$on: function(name, listener) {
......@@ -13008,8 +13345,8 @@ function $SceDelegateProvider() {
* |---------------------|----------------|
* | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. |
* | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. |
* | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`<a href=` and `<img src=` sanitize their urls and don't consititute an SCE context. |
* | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contens are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
* | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |
* | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
* | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. |
*
* ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name="resourceUrlPatternItem"></a>
......@@ -14655,7 +14992,7 @@ function dateFilter($locale) {
* @returns {string} JSON string.
*
*
* @example:
* @example
<example>
<file name="index.html">
<pre>{{ {'name':'value'} | json }}</pre>
......@@ -14827,7 +15164,7 @@ function limitToFilter(){
* - `Array`: An array of function or string predicates. The first predicate in the array
* is used for sorting, but when two items are equivalent, the next predicate is used.
*
* @param {boolean=} reverse Reverse the order the array.
* @param {boolean=} reverse Reverse the order of the array.
* @returns {Array} Sorted copy of the source array.
*
* @example
......@@ -14879,6 +15216,12 @@ function orderByFilter($parse){
predicate = predicate.substring(1);
}
get = $parse(predicate);
if (get.constant) {
var key = get();
return reverseComparator(function(a,b) {
return compare(a[key], b[key]);
}, descending);
}
}
return reverseComparator(function(a,b){
return compare(get(a),get(b));
......@@ -15252,7 +15595,7 @@ var htmlAnchorDirective = valueFn({
* such as selected. (Their presence means true and their absence means false.)
* If we put an Angular interpolation expression into such an attribute then the
* binding information would be lost when the browser removes the attribute.
* The `ngSelected` directive solves this problem for the `selected` atttribute.
* The `ngSelected` directive solves this problem for the `selected` attribute.
* This complementary directive is not removed by the browser and so provides
* a permanent reliable place to store the binding information.
*
......@@ -15586,6 +15929,10 @@ function FormController(element, attrs, $scope, $animate) {
* does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
* sub-group of controls needs to be determined.
*
* Note: the purpose of `ngForm` is to group controls,
* but not to be a replacement for the `<form>` tag with all of its capabilities
* (e.g. posting to the server, ...).
*
* @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into
* related scope, under this name.
*
......@@ -15731,8 +16078,6 @@ function FormController(element, attrs, $scope, $animate) {
</file>
</example>
*
* @param {string=} name Name of the form. If specified, the form controller will be published into
* related scope, under this name.
*/
var formDirectiveFactory = function(isNgForm) {
return ['$timeout', function($timeout) {
......@@ -16244,7 +16589,6 @@ function addNativeHtml5Validators(ctrl, validatorName, element) {
return value;
};
ctrl.$parsers.push(validator);
ctrl.$formatters.push(validator);
}
}
......@@ -17400,7 +17744,7 @@ var ngValueDirective = function() {
* Typically, you don't use `ngBind` directly, but instead you use the double curly markup like
* `{{ expression }}` which is similar but less verbose.
*
* It is preferrable to use `ngBind` instead of `{{ expression }}` when a template is momentarily
* It is preferable to use `ngBind` instead of `{{ expression }}` when a template is momentarily
* displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an
* element attribute, it makes the bindings invisible to the user while the page is loading.
*
......@@ -17571,7 +17915,7 @@ var ngBindHtmlDirective = ['$sce', '$parse', function($sce, $parse) {
function classDirective(name, selector) {
name = 'ngClass' + name;
return function() {
return ['$animate', function($animate) {
return {
restrict: 'AC',
link: function(scope, element, attr) {
......@@ -17589,31 +17933,88 @@ function classDirective(name, selector) {
// jshint bitwise: false
var mod = $index & 1;
if (mod !== old$index & 1) {
var classes = flattenClasses(scope.$eval(attr[name]));
var classes = arrayClasses(scope.$eval(attr[name]));
mod === selector ?
attr.$addClass(classes) :
attr.$removeClass(classes);
addClasses(classes) :
removeClasses(classes);
}
});
}
function addClasses(classes) {
var newClasses = digestClassCounts(classes, 1);
attr.$addClass(newClasses);
}
function removeClasses(classes) {
var newClasses = digestClassCounts(classes, -1);
attr.$removeClass(newClasses);
}
function digestClassCounts (classes, count) {
var classCounts = element.data('$classCounts') || {};
var classesToUpdate = [];
forEach(classes, function (className) {
if (count > 0 || classCounts[className]) {
classCounts[className] = (classCounts[className] || 0) + count;
if (classCounts[className] === +(count > 0)) {
classesToUpdate.push(className);
}
}
});
element.data('$classCounts', classCounts);
return classesToUpdate.join(' ');
}
function updateClasses (oldClasses, newClasses) {
var toAdd = arrayDifference(newClasses, oldClasses);
var toRemove = arrayDifference(oldClasses, newClasses);
toRemove = digestClassCounts(toRemove, -1);
toAdd = digestClassCounts(toAdd, 1);
if (toAdd.length === 0) {
$animate.removeClass(element, toRemove);
} else if (toRemove.length === 0) {
$animate.addClass(element, toAdd);
} else {
$animate.setClass(element, toAdd, toRemove);
}
}
function ngClassWatchAction(newVal) {
if (selector === true || scope.$index % 2 === selector) {
var newClasses = flattenClasses(newVal || '');
if(!oldVal) {
attr.$addClass(newClasses);
} else if(!equals(newVal,oldVal)) {
attr.$updateClass(newClasses, flattenClasses(oldVal));
var newClasses = arrayClasses(newVal || []);
if (!oldVal) {
addClasses(newClasses);
} else if (!equals(newVal,oldVal)) {
var oldClasses = arrayClasses(oldVal);
updateClasses(oldClasses, newClasses);
}
}
oldVal = copy(newVal);
}
}
};
function arrayDifference(tokens1, tokens2) {
var values = [];
outer:
for(var i = 0; i < tokens1.length; i++) {
var token = tokens1[i];
for(var j = 0; j < tokens2.length; j++) {
if(token == tokens2[j]) continue outer;
}
values.push(token);
}
return values;
}
function flattenClasses(classVal) {
if(isArray(classVal)) {
return classVal.join(' ');
function arrayClasses (classVal) {
if (isArray(classVal)) {
return classVal;
} else if (isString(classVal)) {
return classVal.split(' ');
} else if (isObject(classVal)) {
var classes = [], i = 0;
forEach(classVal, function(v, k) {
......@@ -17621,14 +18022,11 @@ function classDirective(name, selector) {
classes.push(k);
}
});
return classes.join(' ');
return classes;
}
return classVal;
}
}
};
};
}];
}
/**
......@@ -18189,7 +18587,7 @@ var ngControllerDirective = [function() {
* @element ANY
* @priority 0
* @param {expression} ngClick {@link guide/expression Expression} to evaluate upon
* click. (Event object is available as `$event`)
* click. ({@link guide/expression#-event- Event object is available as `$event`})
*
* @example
<example>
......@@ -18270,7 +18668,7 @@ forEach(
* @element ANY
* @priority 0
* @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon
* mousedown. (Event object is available as `$event`)
* mousedown. ({@link guide/expression#-event- Event object is available as `$event`})
*
* @example
<example>
......@@ -18294,7 +18692,7 @@ forEach(
* @element ANY
* @priority 0
* @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon
* mouseup. (Event object is available as `$event`)
* mouseup. ({@link guide/expression#-event- Event object is available as `$event`})
*
* @example
<example>
......@@ -18317,7 +18715,7 @@ forEach(
* @element ANY
* @priority 0
* @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon
* mouseover. (Event object is available as `$event`)
* mouseover. ({@link guide/expression#-event- Event object is available as `$event`})
*
* @example
<example>
......@@ -18341,7 +18739,7 @@ forEach(
* @element ANY
* @priority 0
* @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon
* mouseenter. (Event object is available as `$event`)
* mouseenter. ({@link guide/expression#-event- Event object is available as `$event`})
*
* @example
<example>
......@@ -18365,7 +18763,7 @@ forEach(
* @element ANY
* @priority 0
* @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon
* mouseleave. (Event object is available as `$event`)
* mouseleave. ({@link guide/expression#-event- Event object is available as `$event`})
*
* @example
<example>
......@@ -18389,7 +18787,7 @@ forEach(
* @element ANY
* @priority 0
* @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon
* mousemove. (Event object is available as `$event`)
* mousemove. ({@link guide/expression#-event- Event object is available as `$event`})
*
* @example
<example>
......@@ -18456,7 +18854,8 @@ forEach(
*
* @element ANY
* @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon
* keypress. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
* keypress. ({@link guide/expression#-event- Event object is available as `$event`}
* and can be interrogated for keyCode, altKey, etc.)
*
* @example
<example>
......@@ -18481,7 +18880,8 @@ forEach(
*
* @element form
* @priority 0
* @param {expression} ngSubmit {@link guide/expression Expression} to eval. (Event object is available as `$event`)
* @param {expression} ngSubmit {@link guide/expression Expression} to eval.
* ({@link guide/expression#-event- Event object is available as `$event`})
*
* @example
<example>
......@@ -18532,7 +18932,7 @@ forEach(
* @element window, input, select, textarea, a
* @priority 0
* @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon
* focus. (Event object is available as `$event`)
* focus. ({@link guide/expression#-event- Event object is available as `$event`})
*
* @example
* See {@link ng.directive:ngClick ngClick}
......@@ -18548,7 +18948,7 @@ forEach(
* @element window, input, select, textarea, a
* @priority 0
* @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon
* blur. (Event object is available as `$event`)
* blur. ({@link guide/expression#-event- Event object is available as `$event`})
*
* @example
* See {@link ng.directive:ngClick ngClick}
......@@ -18564,7 +18964,7 @@ forEach(
* @element window, input, select, textarea, a
* @priority 0
* @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon
* copy. (Event object is available as `$event`)
* copy. ({@link guide/expression#-event- Event object is available as `$event`})
*
* @example
<example>
......@@ -18585,7 +18985,7 @@ forEach(
* @element window, input, select, textarea, a
* @priority 0
* @param {expression} ngCut {@link guide/expression Expression} to evaluate upon
* cut. (Event object is available as `$event`)
* cut. ({@link guide/expression#-event- Event object is available as `$event`})
*
* @example
<example>
......@@ -18606,7 +19006,7 @@ forEach(
* @element window, input, select, textarea, a
* @priority 0
* @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon
* paste. (Event object is available as `$event`)
* paste. ({@link guide/expression#-event- Event object is available as `$event`})
*
* @example
<example>
......@@ -18772,7 +19172,7 @@ var ngIfDirective = ['$animate', function($animate) {
* @priority 400
*
* @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,
* make sure you wrap it in quotes, e.g. `src="'myPartialTemplate.html'"`.
* make sure you wrap it in **single** quotes, e.g. `src="'myPartialTemplate.html'"`.
* @param {string=} onload Expression to evaluate when a new partial is loaded.
*
* @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll
......@@ -18886,7 +19286,6 @@ var ngIfDirective = ['$animate', function($animate) {
/**
* @ngdoc event
* @name ngInclude#$includeContentRequested
* @eventOf ng.directive:ngInclude
* @eventType emit on the scope ngInclude was declared in
* @description
* Emitted every time the ngInclude content is requested.
......@@ -18896,7 +19295,6 @@ var ngIfDirective = ['$animate', function($animate) {
/**
* @ngdoc event
* @name ngInclude#$includeContentLoaded
* @eventOf ng.directive:ngInclude
* @eventType emit on the current ngInclude scope
* @description
* Emitted every time the ngInclude content is reloaded.
......@@ -19383,9 +19781,11 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp
* as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).
*
* @animations
* enter - when a new item is added to the list or when an item is revealed after a filter
* leave - when an item is removed from the list or when an item is filtered out
* move - when an adjacent item is filtered out causing a reorder or when the item contents are reordered
* **.enter** - when a new item is added to the list or when an item is revealed after a filter
*
* **.leave** - when an item is removed from the list or when an item is filtered out
*
* **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered
*
* @element ANY
* @scope
......@@ -19879,7 +20279,7 @@ var ngShowDirective = ['$animate', function($animate) {
* in AngularJS and sets the display style to none (using an !important flag).
* For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
*
* ```hrml
* ```html
* <!-- when $scope.myValue is truthy (element is hidden) -->
* <div ng-hide="myValue"></div>
*
......@@ -20117,7 +20517,6 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) {
* @scope
* @priority 800
* @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.
* @paramDescription
* On child elements add:
*
* * `ngSwitchWhen`: the case statement to match against. If match then this
......@@ -20366,7 +20765,7 @@ var ngTranscludeDirective = ngDirective({
* `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be
* assigned through the element's `id`, which can then be used as a directive's `templateUrl`.
*
* @param {'text/ng-template'} type Must be set to `'text/ng-template'`.
* @param {string} type Must be set to `'text/ng-template'`.
* @param {string} id Cache name of the template.
*
* @example
......@@ -20797,6 +21196,12 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
value = valueFn(scope, locals);
}
}
// Update the null option's selected property here so $render cleans it up correctly
if (optionGroupsCache[0].length > 1) {
if (optionGroupsCache[0][1].id !== key) {
optionGroupsCache[0][1].selected = false;
}
}
}
ctrl.$setViewValue(value);
});
......@@ -20934,7 +21339,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
lastElement.val(existingOption.id = option.id);
}
// lastElement.prop('selected') provided by jQuery has side-effects
if (lastElement[0].selected !== option.selected) {
if (existingOption.selected !== option.selected) {
lastElement.prop('selected', (existingOption.selected = option.selected));
}
} else {
......@@ -21038,6 +21443,12 @@ var styleDirective = valueFn({
terminal: true
});
if (window.angular.bootstrap) {
//AngularJS is already loaded, so we can return here...
console.log('WARNING: Tried to load angular more than once.');
return;
}
//try to bind to jquery now so that one can write angular.element().read()
//but we will rebind on bootstrap again.
bindJQuery();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment