vendor/assets/javascripts/angular-scenario.js in angularjs-rails-1.2.15 vs vendor/assets/javascripts/angular-scenario.js in angularjs-rails-1.2.16
- old
+ new
@@ -9788,11 +9788,11 @@
}
})( window );
/**
- * @license AngularJS v1.2.15
+ * @license AngularJS v1.2.16
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, document){
var _jQuery = window.jQuery.noConflict(true);
@@ -9858,11 +9858,11 @@
return arg;
}
return match;
});
- message = message + '\nhttp://errors.angularjs.org/1.2.15/' +
+ 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) + '=' +
encodeURIComponent(stringify(arguments[i]));
}
@@ -11145,11 +11145,11 @@
* .toBe(9);
* });
* </file>
* </example>
*
- * @param {Element} element DOM element which is the root of angular application.
+ * @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.
* See: {@link angular.module modules}
* @returns {auto.$injector} Returns the newly created injector for this app.
@@ -11379,12 +11379,12 @@
* However it's more likely that you'll just use
* {@link ng.directive:ngApp ngApp} or
* {@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 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.
*/
return function module(name, requires, configFn) {
@@ -11709,15 +11709,15 @@
* - `minor` – `{number}` – Minor version number, such as "9".
* - `dot` – `{number}` – Dot version number, such as "18".
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
*/
var version = {
- full: '1.2.15', // 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: 15,
- codeName: 'beer-underestimating'
+ dot: 16,
+ codeName: 'badger-enumeration'
};
function publishExternalAPI(angular){
extend(angular, {
@@ -12016,10 +12016,79 @@
}
return originalJqFn.apply(this, arguments);
}
}
+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> </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) {
return element;
}
@@ -12032,18 +12101,13 @@
}
return new 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> </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);
}
}
@@ -14365,11 +14429,12 @@
/**
* @ngdoc service
* @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
*
* var cache = $cacheFactory('cacheId');
* expect($cacheFactory.get('cacheId')).toBe(cache);
@@ -14397,10 +14462,50 @@
* - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
* - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
* - `{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() {
this.$get = function() {
var caches = {};
@@ -14416,12 +14521,69 @@
capacity = (options && options.capacity) || Number.MAX_VALUE,
lruHash = {},
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});
refresh(lruEntry);
@@ -14436,11 +14598,21 @@
}
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];
if (!lruEntry) return;
@@ -14450,10 +14622,20 @@
return data[key];
},
+ /**
+ * @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];
if (!lruEntry) return;
@@ -14468,26 +14650,59 @@
delete data[key];
size--;
},
+ /**
+ * @ngdoc method
+ * @name $cacheFactory.Cache#removeAll
+ * @function
+ *
+ * @description
+ * Clears the cache object of any entries.
+ */
removeAll: function() {
data = {};
size = 0;
lruHash = {};
freshEnd = staleEnd = null;
},
+ /**
+ * @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;
lruHash = null;
delete caches[cacheId];
},
+ /**
+ * @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});
}
};
@@ -14670,10 +14885,11 @@
* replace: false,
* transclude: false,
* 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 {
* pre: function preLink(scope, iElement, iAttrs, controller) { ... },
* post: function postLink(scope, iElement, iAttrs, controller) { ... }
@@ -14887,11 +15103,21 @@
* **Note:** The template instance and the link instance may be different objects if the template has
* been cloned. For this reason it is **not** safe to do anything other than DOM transformations that
* 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
* e.g. does not know about the right outer scope. Please use the transclude function that is passed
* to the link function instead.
* </div>
@@ -15108,12 +15334,11 @@
$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
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|thead|tbody|tfoot)(\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
// 'on' and be composed of only English letters.
var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
@@ -15851,11 +16076,15 @@
directiveValue = denormalizeTemplate(directiveValue);
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) {
throw $compileMinErr('tplrt',
"Template for directive '{0}' must have exactly one root element. {1}",
@@ -16250,31 +16479,10 @@
}
});
}
- 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>');
- if (/(thead|tbody|tfoot)/.test(type)) {
- return table.children(type);
- }
- table = table.children('tbody');
- if (type === 'tr') {
- return table.children('tr');
- }
- return table.children('tr').contents();
- }
- return jqLite('<div>' +
- template +
- '</div>').contents();
- }
-
-
function compileTemplateUrl(directives, $compileNode, tAttrs,
$rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {
var linkQueue = [],
afterTemplateNodeLinkFn,
afterTemplateChildLinkFn,
@@ -16295,11 +16503,15 @@
var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
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) {
throw $compileMinErr('tplrt',
"Template for directive '{0}' must have exactly one root element. {1}",
@@ -17073,11 +17285,11 @@
* The defaults can also be set at runtime via the `$http.defaults` object in the same
* fashion. For example:
*
* ```
* module.run(function($http) {
- * $http.defaults.headers.common.Authentication = 'Basic YmVlcDpib29w'
+ * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'
* });
* ```
*
* In addition, you can supply a `headers` property in the config object passed when
* calling `$http(config)`, which overrides the defaults without changing them globally.
@@ -17367,10 +17579,11 @@
* - **data** – `{string|Object}` – The response body transformed with the transform
* functions.
* - **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.<Object>} pendingRequests Array of config objects for currently pending
* requests. This is primarily meant to be used for debugging purposes.
*
*
@@ -17741,13 +17954,13 @@
cachedResp.then(removePendingReq, removePendingReq);
return cachedResp;
} 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 {
// put the promise for the non-transformed response into cache as a placeholder
cache.put(url, promise);
@@ -17767,37 +17980,38 @@
* Callback registered to $httpBackend():
* - caches the response if desired
* - 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();
}
/**
* 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);
(isSuccess(status) ? deferred.resolve : deferred.reject)({
data: response,
status: status,
headers: headersGetter(headers),
- config: config
+ config: config,
+ statusText : statusText
});
}
function removePendingReq() {
@@ -17927,11 +18141,12 @@
}
completeRequest(callback,
status || xhr.status,
response,
- responseHeaders);
+ responseHeaders,
+ xhr.statusText || '');
}
};
if (withCredentials) {
xhr.withCredentials = true;
@@ -17968,11 +18183,11 @@
status = ABORTED;
jsonpDone && jsonpDone();
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).
@@ -17981,13 +18196,14 @@
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);
}
};
function jsonpReq(url, done) {
@@ -19019,12 +19235,11 @@
* - Changes the address bar.
* - Clicks the back or forward button (or clicks a History link).
* - 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}
*/
/**
* @ngdoc provider
* @name $locationProvider
@@ -19756,11 +19971,15 @@
this.lexer = lexer;
this.$filter = $filter;
this.options = options;
};
-Parser.ZERO = function () { return 0; };
+Parser.ZERO = extend(function () {
+ return 0;
+}, {
+ constant: true
+});
Parser.prototype = {
constructor: Parser,
parse: function (text, json) {
@@ -21501,11 +21720,12 @@
*
* - `string`: Evaluated as {@link guide/expression expression}
* - `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) {
var scope = this,
get = compileToFn(watchExp, 'watch'),
@@ -21922,19 +22142,36 @@
this.$$destroyed = true;
if (this === $rootScope) return;
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; };
},
/**
* @ngdoc method
* @name $rootScope.Scope#$eval
@@ -22899,11 +23136,11 @@
* | Context | Notes |
* |---------------------|----------------|
* | `$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 constitute 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.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>
*
* Each element in these arrays must be one of the following:
@@ -24717,11 +24954,11 @@
* to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control
* ascending or descending sort order (for example, +name or -name).
* - `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
<example>
<file name="index.html">
@@ -25482,10 +25719,14 @@
* @description
* Nestable alias of {@link ng.directive:form `form`} directive. HTML
* 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.
*
*/
@@ -26138,11 +26379,10 @@
return;
}
return value;
};
ctrl.$parsers.push(validator);
- ctrl.$formatters.push(validator);
}
}
function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
var validity = element.prop('validity');
@@ -27465,11 +27705,11 @@
};
}];
function classDirective(name, selector) {
name = 'ngClass' + name;
- return function() {
+ return ['$animate', function($animate) {
return {
restrict: 'AC',
link: function(scope, element, attr) {
var oldVal;
@@ -27483,50 +27723,104 @@
if (name !== 'ngClass') {
scope.$watch('$index', function($index, old$index) {
// 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 = [];
- function flattenClasses(classVal) {
- if(isArray(classVal)) {
- return classVal.join(' ');
- } else if (isObject(classVal)) {
- var classes = [], i = 0;
- forEach(classVal, function(v, k) {
- if (v) {
- classes.push(k);
- }
- });
- return classes.join(' ');
- }
-
- return classVal;
+ 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 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) {
+ if (v) {
+ classes.push(k);
+ }
+ });
+ return classes;
+ }
+ return classVal;
+ }
+ }];
}
/**
* @ngdoc directive
* @name ngClass
@@ -28083,11 +28377,11 @@
* an element is clicked.
*
* @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>
<file name="index.html">
<button ng-click="count = count + 1" ng-init="count=0">
@@ -28164,11 +28458,11 @@
* The ngMousedown directive allows you to specify custom behavior on mousedown event.
*
* @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>
<file name="index.html">
<button ng-mousedown="count = count + 1" ng-init="count=0">
@@ -28188,11 +28482,11 @@
* Specify custom behavior on mouseup event.
*
* @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>
<file name="index.html">
<button ng-mouseup="count = count + 1" ng-init="count=0">
@@ -28211,11 +28505,11 @@
* Specify custom behavior on mouseover event.
*
* @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>
<file name="index.html">
<button ng-mouseover="count = count + 1" ng-init="count=0">
@@ -28235,11 +28529,11 @@
* Specify custom behavior on mouseenter event.
*
* @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>
<file name="index.html">
<button ng-mouseenter="count = count + 1" ng-init="count=0">
@@ -28259,11 +28553,11 @@
* Specify custom behavior on mouseleave event.
*
* @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>
<file name="index.html">
<button ng-mouseleave="count = count + 1" ng-init="count=0">
@@ -28283,11 +28577,11 @@
* Specify custom behavior on mousemove event.
*
* @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>
<file name="index.html">
<button ng-mousemove="count = count + 1" ng-init="count=0">
@@ -28350,11 +28644,12 @@
* @description
* Specify custom behavior on keypress event.
*
* @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>
<file name="index.html">
<input ng-keypress="count = count + 1" ng-init="count=0">
@@ -28375,11 +28670,12 @@
* server and reloading the current page), but only if the form does not contain `action`,
* `data-action`, or `x-action` attributes.
*
* @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>
<file name="index.html">
<script>
@@ -28426,11 +28722,11 @@
* Specify custom behavior on focus event.
*
* @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}
*/
@@ -28442,11 +28738,11 @@
* Specify custom behavior on blur event.
*
* @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}
*/
@@ -28458,11 +28754,11 @@
* Specify custom behavior on copy event.
*
* @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>
<file name="index.html">
<input ng-copy="copied=true" ng-init="copied=false; value='copy me'" ng-model="value">
@@ -28479,11 +28775,11 @@
* Specify custom behavior on cut event.
*
* @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>
<file name="index.html">
<input ng-cut="cut=true" ng-init="cut=false; value='cut me'" ng-model="value">
@@ -28500,11 +28796,11 @@
* Specify custom behavior on paste event.
*
* @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>
<file name="index.html">
<input ng-paste="paste=true" ng-init="paste=false" placeholder='paste here'>
@@ -29773,10 +30069,10 @@
* provided to the ngHide attribute. The element is shown or hidden by removing or adding
* the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
* 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>
*
* <!-- when $scope.myValue is falsy (element is visible) -->
* <div ng-hide="myValue" class="ng-hide"></div>
\ No newline at end of file