vendor/assets/javascripts/unstable/angular-scenario.js in angularjs-rails-1.2.19 vs vendor/assets/javascripts/unstable/angular-scenario.js in angularjs-rails-1.2.20
- old
+ new
@@ -9788,11 +9788,11 @@
}
})( window );
/**
- * @license AngularJS v1.3.0-beta.14
+ * @license AngularJS v1.3.0-beta.15
* (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.3.0-beta.14/' +
+ message = message + '\nhttp://errors.angularjs.org/1.3.0-beta.15/' +
(module ? module + '/' : '') + code;
for (i = 2; i < arguments.length; i++) {
message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
encodeURIComponent(stringify(arguments[i]));
}
@@ -9870,93 +9870,91 @@
return new Error(message);
};
}
/* We need to tell jshint what variables are being exported */
-/* global
- -angular,
- -msie,
- -jqLite,
- -jQuery,
- -slice,
- -push,
- -toString,
- -ngMinErr,
- -angularModule,
- -nodeName_,
- -uid,
- -REGEX_STRING_REGEXP,
- -VALIDITY_STATE_PROPERTY,
+/* global angular: true,
+ msie: true,
+ jqLite: true,
+ jQuery: true,
+ slice: true,
+ push: true,
+ toString: true,
+ ngMinErr: true,
+ angularModule: true,
+ nodeName_: true,
+ uid: true,
+ REGEX_STRING_REGEXP: true,
+ VALIDITY_STATE_PROPERTY: true,
- -lowercase,
- -uppercase,
- -manualLowercase,
- -manualUppercase,
- -nodeName_,
- -isArrayLike,
- -forEach,
- -sortedKeys,
- -forEachSorted,
- -reverseParams,
- -nextUid,
- -setHashKey,
- -extend,
- -int,
- -inherit,
- -noop,
- -identity,
- -valueFn,
- -isUndefined,
- -isDefined,
- -isObject,
- -isString,
- -isNumber,
- -isDate,
- -isArray,
- -isFunction,
- -isRegExp,
- -isWindow,
- -isScope,
- -isFile,
- -isBlob,
- -isBoolean,
- -trim,
- -isElement,
- -makeMap,
- -map,
- -size,
- -includes,
- -indexOf,
- -arrayRemove,
- -isLeafNode,
- -copy,
- -shallowCopy,
- -equals,
- -csp,
- -concat,
- -sliceArgs,
- -bind,
- -toJsonReplacer,
- -toJson,
- -fromJson,
- -startingTag,
- -tryDecodeURIComponent,
- -parseKeyValue,
- -toKeyValue,
- -encodeUriSegment,
- -encodeUriQuery,
- -angularInit,
- -bootstrap,
- -snake_case,
- -bindJQuery,
- -assertArg,
- -assertArgFn,
- -assertNotHasOwnProperty,
- -getter,
- -getBlockElements,
- -hasOwnProperty,
-
+ lowercase: true,
+ uppercase: true,
+ manualLowercase: true,
+ manualUppercase: true,
+ nodeName_: true,
+ isArrayLike: true,
+ forEach: true,
+ sortedKeys: true,
+ forEachSorted: true,
+ reverseParams: true,
+ nextUid: true,
+ setHashKey: true,
+ extend: true,
+ int: true,
+ inherit: true,
+ noop: true,
+ identity: true,
+ valueFn: true,
+ isUndefined: true,
+ isDefined: true,
+ isObject: true,
+ isString: true,
+ isNumber: true,
+ isDate: true,
+ isArray: true,
+ isFunction: true,
+ isRegExp: true,
+ isWindow: true,
+ isScope: true,
+ isFile: true,
+ isBlob: true,
+ isBoolean: true,
+ trim: true,
+ isElement: true,
+ makeMap: true,
+ map: true,
+ size: true,
+ includes: true,
+ indexOf: true,
+ arrayRemove: true,
+ isLeafNode: true,
+ copy: true,
+ shallowCopy: true,
+ equals: true,
+ csp: true,
+ concat: true,
+ sliceArgs: true,
+ bind: true,
+ toJsonReplacer: true,
+ toJson: true,
+ fromJson: true,
+ startingTag: true,
+ tryDecodeURIComponent: true,
+ parseKeyValue: true,
+ toKeyValue: true,
+ encodeUriSegment: true,
+ encodeUriQuery: true,
+ angularInit: true,
+ bootstrap: true,
+ snake_case: true,
+ bindJQuery: true,
+ assertArg: true,
+ assertArgFn: true,
+ assertNotHasOwnProperty: true,
+ getter: true,
+ getBlockElements: true,
+ hasOwnProperty: true,
*/
////////////////////////////////////
/**
@@ -10590,13 +10588,13 @@
* @param {(Object|Array)=} destination Destination into which the source is copied. If
* provided, must be of the same type as `source`.
* @returns {*} The copy or updated `destination`, if `destination` was specified.
*
* @example
- <example>
+ <example module="copyExample">
<file name="index.html">
- <div ng-controller="Controller">
+ <div ng-controller="ExampleController">
<form novalidate class="simple-form">
Name: <input type="text" ng-model="user.name" /><br />
E-mail: <input type="email" ng-model="user.email" /><br />
Gender: <input type="radio" ng-model="user.gender" value="male" />male
<input type="radio" ng-model="user.gender" value="female" />female<br />
@@ -10606,25 +10604,26 @@
<pre>form = {{user | json}}</pre>
<pre>master = {{master | json}}</pre>
</div>
<script>
- function Controller($scope) {
- $scope.master= {};
+ angular.module('copyExample')
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.master= {};
- $scope.update = function(user) {
- // Example with 1 argument
- $scope.master= angular.copy(user);
- };
+ $scope.update = function(user) {
+ // Example with 1 argument
+ $scope.master= angular.copy(user);
+ };
- $scope.reset = function() {
- // Example with 2 arguments
- angular.copy($scope.master, $scope.user);
- };
+ $scope.reset = function() {
+ // Example with 2 arguments
+ angular.copy($scope.master, $scope.user);
+ };
- $scope.reset();
- }
+ $scope.reset();
+ }]);
</script>
</file>
</example>
*/
function copy(source, destination, stackSource, stackDest) {
@@ -10960,11 +10959,11 @@
if ( keyValue ) {
key_value = keyValue.split('=');
key = tryDecodeURIComponent(key_value[0]);
if ( isDefined(key) ) {
var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
- if (!obj[key]) {
+ if (!hasOwnProperty.call(obj, key)) {
obj[key] = val;
} else if(isArray(obj[key])) {
obj[key].push(val);
} else {
obj[key] = [obj[key],val];
@@ -11758,93 +11757,92 @@
};
});
}
-/* global
- angularModule: true,
- version: true,
+/* global angularModule: true,
+ version: true,
- $LocaleProvider,
- $CompileProvider,
+ $LocaleProvider,
+ $CompileProvider,
- htmlAnchorDirective,
- inputDirective,
- inputDirective,
- formDirective,
- scriptDirective,
- selectDirective,
- styleDirective,
- optionDirective,
- ngBindDirective,
- ngBindHtmlDirective,
- ngBindTemplateDirective,
- ngClassDirective,
- ngClassEvenDirective,
- ngClassOddDirective,
- ngCspDirective,
- ngCloakDirective,
- ngControllerDirective,
- ngFormDirective,
- ngHideDirective,
- ngIfDirective,
- ngIncludeDirective,
- ngIncludeFillContentDirective,
- ngInitDirective,
- ngNonBindableDirective,
- ngPluralizeDirective,
- ngRepeatDirective,
- ngShowDirective,
- ngStyleDirective,
- ngSwitchDirective,
- ngSwitchWhenDirective,
- ngSwitchDefaultDirective,
- ngOptionsDirective,
- ngTranscludeDirective,
- ngModelDirective,
- ngListDirective,
- ngChangeDirective,
- patternDirective,
- patternDirective,
- requiredDirective,
- requiredDirective,
- minlengthDirective,
- minlengthDirective,
- maxlengthDirective,
- maxlengthDirective,
- ngValueDirective,
- ngModelOptionsDirective,
- ngAttributeAliasDirectives,
- ngEventDirectives,
+ htmlAnchorDirective,
+ inputDirective,
+ inputDirective,
+ formDirective,
+ scriptDirective,
+ selectDirective,
+ styleDirective,
+ optionDirective,
+ ngBindDirective,
+ ngBindHtmlDirective,
+ ngBindTemplateDirective,
+ ngClassDirective,
+ ngClassEvenDirective,
+ ngClassOddDirective,
+ ngCspDirective,
+ ngCloakDirective,
+ ngControllerDirective,
+ ngFormDirective,
+ ngHideDirective,
+ ngIfDirective,
+ ngIncludeDirective,
+ ngIncludeFillContentDirective,
+ ngInitDirective,
+ ngNonBindableDirective,
+ ngPluralizeDirective,
+ ngRepeatDirective,
+ ngShowDirective,
+ ngStyleDirective,
+ ngSwitchDirective,
+ ngSwitchWhenDirective,
+ ngSwitchDefaultDirective,
+ ngOptionsDirective,
+ ngTranscludeDirective,
+ ngModelDirective,
+ ngListDirective,
+ ngChangeDirective,
+ patternDirective,
+ patternDirective,
+ requiredDirective,
+ requiredDirective,
+ minlengthDirective,
+ minlengthDirective,
+ maxlengthDirective,
+ maxlengthDirective,
+ ngValueDirective,
+ ngModelOptionsDirective,
+ ngAttributeAliasDirectives,
+ ngEventDirectives,
- $AnchorScrollProvider,
- $AnimateProvider,
- $BrowserProvider,
- $CacheFactoryProvider,
- $ControllerProvider,
- $DocumentProvider,
- $ExceptionHandlerProvider,
- $FilterProvider,
- $InterpolateProvider,
- $IntervalProvider,
- $HttpProvider,
- $HttpBackendProvider,
- $LocationProvider,
- $LogProvider,
- $ParseProvider,
- $RootScopeProvider,
- $QProvider,
- $$QProvider,
- $$SanitizeUriProvider,
- $SceProvider,
- $SceDelegateProvider,
- $SnifferProvider,
- $TemplateCacheProvider,
- $TimeoutProvider,
- $$RAFProvider,
- $$AsyncCallbackProvider,
- $WindowProvider
+ $AnchorScrollProvider,
+ $AnimateProvider,
+ $BrowserProvider,
+ $CacheFactoryProvider,
+ $ControllerProvider,
+ $DocumentProvider,
+ $ExceptionHandlerProvider,
+ $FilterProvider,
+ $InterpolateProvider,
+ $IntervalProvider,
+ $HttpProvider,
+ $HttpBackendProvider,
+ $LocationProvider,
+ $LogProvider,
+ $ParseProvider,
+ $RootScopeProvider,
+ $QProvider,
+ $$QProvider,
+ $$SanitizeUriProvider,
+ $SceProvider,
+ $SceDelegateProvider,
+ $SnifferProvider,
+ $TemplateCacheProvider,
+ $TimeoutProvider,
+ $$RAFProvider,
+ $$AsyncCallbackProvider,
+ $WindowProvider
*/
/**
* @ngdoc object
@@ -11859,15 +11857,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.3.0-beta.14', // all of these placeholder strings will be replaced by grunt's
+ full: '1.3.0-beta.15', // all of these placeholder strings will be replaced by grunt's
major: 1, // package task
minor: 3,
dot: 0,
- codeName: 'harmonious-cacophonies'
+ codeName: 'unbelievable-advancement'
};
function publishExternalAPI(angular){
extend(angular, {
@@ -11995,17 +11993,15 @@
});
}
]);
}
-/* global
-
- -JQLitePrototype,
- -addEventListenerFn,
- -removeEventListenerFn,
- -BOOLEAN_ATTR,
- -ALIASED_ATTR
+/* global JQLitePrototype: true,
+ addEventListenerFn: true,
+ removeEventListenerFn: true,
+ BOOLEAN_ATTR: true,
+ ALIASED_ATTR: true,
*/
//////////////////////////////////
//JQLite
//////////////////////////////////
@@ -12240,16 +12236,20 @@
function jqLiteClone(element) {
return element.cloneNode(true);
}
-function jqLiteDealoc(element){
- jqLiteRemoveData(element);
- var childElement;
- for ( var i = 0, children = element.children, l = (children && children.length) || 0; i < l; i++) {
- childElement = children[i];
- jqLiteDealoc(childElement);
+function jqLiteDealoc(element, onlyDescendants){
+ if (!onlyDescendants) jqLiteRemoveData(element);
+
+ if (element.childNodes && element.childNodes.length) {
+ // we use querySelectorAll because documentFragments don't have getElementsByTagName
+ var descendants = element.getElementsByTagName ? element.getElementsByTagName('*') :
+ element.querySelectorAll ? element.querySelectorAll('*') : [];
+ for (var i = 0, l = descendants.length; i < l; i++) {
+ jqLiteRemoveData(descendants[i]);
+ }
}
}
function jqLiteOff(element, type, fn, unsupported) {
if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');
@@ -12427,13 +12427,11 @@
element = jqLite(node.parentNode || (node.nodeType === 11 && node.host));
}
}
function jqLiteEmpty(element) {
- for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
- jqLiteDealoc(childNodes[i]);
- }
+ jqLiteDealoc(element, true);
while (element.firstChild) {
element.removeChild(element.firstChild);
}
}
@@ -12627,13 +12625,11 @@
html: function(element, value) {
if (isUndefined(value)) {
return element.innerHTML;
}
- for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
- jqLiteDealoc(childNodes[i]);
- }
+ jqLiteDealoc(element, true);
element.innerHTML = value;
},
empty: jqLiteEmpty
}, function(fn, name){
@@ -12749,12 +12745,10 @@
// selector.
//////////////////////////////////////////
forEach({
removeData: jqLiteRemoveData,
- dealoc: jqLiteDealoc,
-
on: function onFn(element, type, fn, unsupported){
if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
// Do not add event handlers to non-elements because they will not be cleaned up.
if (!jqLiteAcceptsData(element)) {
@@ -13902,28 +13896,30 @@
*
* It also watches the `$location.hash()` and scrolls whenever it changes to match any anchor.
* This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.
*
* @example
- <example>
+ <example module="anchorScrollExample">
<file name="index.html">
- <div id="scrollArea" ng-controller="ScrollCtrl">
+ <div id="scrollArea" ng-controller="ScrollController">
<a ng-click="gotoBottom()">Go to bottom</a>
<a id="bottom"></a> You're at the bottom!
</div>
</file>
<file name="script.js">
- function ScrollCtrl($scope, $location, $anchorScroll) {
- $scope.gotoBottom = function (){
- // set the location.hash to the id of
- // the element you wish to scroll to.
- $location.hash('bottom');
+ angular.module('anchorScrollExample', [])
+ .controller('ScrollController', ['$scope', '$location', '$anchorScroll',
+ function ($scope, $location, $anchorScroll) {
+ $scope.gotoBottom = function() {
+ // set the location.hash to the id of
+ // the element you wish to scroll to.
+ $location.hash('bottom');
- // call $anchorScroll()
- $anchorScroll();
- };
- }
+ // call $anchorScroll()
+ $anchorScroll();
+ };
+ }]);
</file>
<file name="style.css">
#scrollArea {
height: 350px;
overflow: auto;
@@ -14113,10 +14109,11 @@
enter : function(element, parent, after, done) {
after
? after.after(element)
: parent.prepend(element);
async(done);
+ return noop;
},
/**
*
* @ngdoc method
@@ -14129,10 +14126,11 @@
* removed from the DOM
*/
leave : function(element, done) {
element.remove();
async(done);
+ return noop;
},
/**
*
* @ngdoc method
@@ -14152,11 +14150,11 @@
* element has been moved to its new position
*/
move : function(element, parent, after, done) {
// Do not remove element before insert. Removing will cause data associated with the
// element to be dropped. Insert will implicitly do the remove.
- this.enter(element, parent, after, done);
+ return this.enter(element, parent, after, done);
},
/**
*
* @ngdoc method
@@ -14169,17 +14167,18 @@
* @param {string} className the CSS class which will be added to the element
* @param {Function=} done the callback function (if provided) that will be fired after the
* className value has been added to the element
*/
addClass : function(element, className, done) {
- className = isString(className) ?
- className :
- isArray(className) ? className.join(' ') : '';
+ className = !isString(className)
+ ? (isArray(className) ? className.join(' ') : '')
+ : className;
forEach(element, function (element) {
jqLiteAddClass(element, className);
});
async(done);
+ return noop;
},
/**
*
* @ngdoc method
@@ -14199,10 +14198,11 @@
isArray(className) ? className.join(' ') : '';
forEach(element, function (element) {
jqLiteRemoveClass(element, className);
});
async(done);
+ return noop;
},
/**
*
* @ngdoc method
@@ -14221,10 +14221,11 @@
forEach(element, function (element) {
jqLiteAddClass(element, add);
jqLiteRemoveClass(element, remove);
});
async(done);
+ return noop;
},
enabled : noop
};
}];
@@ -15180,11 +15181,11 @@
* * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
* If no `attr` name is specified then the attribute name is assumed to be the same as the
* local name. Given `<widget my-attr="count = count + value">` and widget definition of
* `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
* a function wrapper for the `count = count + value` expression. Often it's desirable to
- * pass data from the isolated scope via an expression and to the parent scope, this can be
+ * pass data from the isolated scope via an expression to the parent scope, this can be
* done by passing a map of local variable names and values into the expression wrapper fn.
* For example, if the expression is `increment(amount)` then we can specify the amount value
* by calling the `localFn` as `localFn({amount: 22})`.
*
*
@@ -15420,14 +15421,14 @@
* <div class="alert alert-warning">
* **Note**: Typically directives are registered with `module.directive`. The example below is
* to illustrate how `$compile` works.
* </div>
*
- <example module="compile">
+ <example module="compileExample">
<file name="index.html">
<script>
- angular.module('compile', [], function($compileProvider) {
+ angular.module('compileExample', [], function($compileProvider) {
// configure new 'compile' directive by passing a directive
// factory function. The factory function injects the '$compile'
$compileProvider.directive('compile', function($compile) {
// directive factory creates a link function
return function(scope, element, attrs) {
@@ -15447,19 +15448,18 @@
// we don't get into infinite loop compiling ourselves
$compile(element.contents())(scope);
}
);
};
- })
- });
-
- function Ctrl($scope) {
+ });
+ })
+ .controller('GreeterController', ['$scope', function($scope) {
$scope.name = 'Angular';
$scope.html = 'Hello {{name}}';
- }
+ }]);
</script>
- <div ng-controller="Ctrl">
+ <div ng-controller="GreeterController">
<input ng-model="name"> <br>
<textarea ng-model="html"></textarea> <br>
<div compile="html"></div>
</div>
</file>
@@ -15883,18 +15883,11 @@
forEach(transcludeControllers, function(instance, name) {
$linkNode.data('$' + name + 'Controller', instance);
});
- // Attach scope only to non-text nodes.
- for(var i = 0, ii = $linkNode.length; i<ii; i++) {
- var node = $linkNode[i],
- nodeType = node.nodeType;
- if (nodeType === 1 /* element */ || nodeType === 9 /* document */) {
- $linkNode.eq(i).data('$scope', scope);
- }
- }
+ $linkNode.data('$scope', scope);
if (cloneConnectFn) cloneConnectFn($linkNode, scope);
if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);
return $linkNode;
};
@@ -17146,10 +17139,11 @@
* This provider allows controller registration via the
* {@link ng.$controllerProvider#register register} method.
*/
function $ControllerProvider() {
var controllers = {},
+ globals = false,
CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
/**
* @ngdoc method
@@ -17166,11 +17160,20 @@
} else {
controllers[name] = constructor;
}
};
+ /**
+ * @ngdoc method
+ * @name $controllerProvider#allowGlobals
+ * @description If called, allows `$controller` to find controller constructors on `window`
+ */
+ this.allowGlobals = function() {
+ globals = true;
+ };
+
this.$get = ['$injector', '$window', function($injector, $window) {
/**
* @ngdoc service
* @name $controller
@@ -17180,11 +17183,12 @@
* controller constructor function. Otherwise it's considered to be a string which is used
* to retrieve the controller constructor using the following steps:
*
* * check if a controller with given name is registered via `$controllerProvider`
* * check if evaluating the string on the current scope returns a constructor
- * * check `window[constructor]` on the global `window` object
+ * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
+ * `window` object (not recommended)
*
* @param {Object} locals Injection locals for Controller.
* @return {Object} Instance of given controller.
*
* @description
@@ -17200,11 +17204,12 @@
match = expression.match(CNTRL_REG),
constructor = match[1],
identifier = match[3];
expression = controllers.hasOwnProperty(constructor)
? controllers[constructor]
- : getter(locals.$scope, constructor, true) || getter($window, constructor, true);
+ : getter(locals.$scope, constructor, true) ||
+ (globals ? getter($window, constructor, true) : undefined);
assertArgFn(expression, constructor, true);
}
instance = $injector.instantiate(expression, locals, constructor);
@@ -17231,22 +17236,23 @@
*
* @description
* A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.
*
* @example
- <example>
+ <example module="documentExample">
<file name="index.html">
- <div ng-controller="MainCtrl">
+ <div ng-controller="ExampleController">
<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;
- }
+ angular.module('documentExample', [])
+ .controller('ExampleController', ['$scope', '$document', function($scope, $document) {
+ $scope.title = $document[0].title;
+ $scope.windowTitle = angular.element(window.document)[0].title;
+ }]);
</file>
</example>
*/
function $DocumentProvider(){
this.$get = ['$window', function(window){
@@ -17375,16 +17381,43 @@
function isSuccess(status) {
return 200 <= status && status < 300;
}
+/**
+ * @ngdoc provider
+ * @name $httpProvider
+ * @description
+ * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
+ * */
function $HttpProvider() {
var JSON_START = /^\s*(\[|\{[^\{])/,
JSON_END = /[\}\]]\s*$/,
PROTECTION_PREFIX = /^\)\]\}',?\n/,
CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': 'application/json;charset=utf-8'};
+ /**
+ * @ngdoc property
+ * @name $httpProvider#defaults
+ * @description
+ *
+ * Object containing default values for all {@link ng.$http $http} requests.
+ *
+ * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
+ * Defaults value is `'XSRF-TOKEN'`.
+ *
+ * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
+ * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.
+ *
+ * - **`defaults.headers`** - {Object} - Default headers for all $http requests.
+ * Refer to {@link ng.$http#setting-http-headers $http} for documentation on
+ * setting default headers.
+ * - **`defaults.headers.common`**
+ * - **`defaults.headers.post`**
+ * - **`defaults.headers.put`**
+ * - **`defaults.headers.patch`**
+ **/
var defaults = this.defaults = {
// transform incoming response data
transformResponse: [function(data) {
if (isString(data)) {
// strip json vulnerability protection prefix
@@ -17798,13 +17831,13 @@
* @property {Array.<Object>} pendingRequests Array of config objects for currently pending
* requests. This is primarily meant to be used for debugging purposes.
*
*
* @example
-<example>
+<example module="httpExample">
<file name="index.html">
- <div ng-controller="FetchCtrl">
+ <div ng-controller="FetchController">
<select ng-model="method">
<option>GET</option>
<option>JSONP</option>
</select>
<input type="text" ng-model="url" size="80"/>
@@ -17822,34 +17855,36 @@
<pre>http status code: {{status}}</pre>
<pre>http response data: {{data}}</pre>
</div>
</file>
<file name="script.js">
- function FetchCtrl($scope, $http, $templateCache) {
- $scope.method = 'GET';
- $scope.url = 'http-hello.html';
+ angular.module('httpExample', [])
+ .controller('FetchController', ['$scope', '$http', '$templateCache',
+ function($scope, $http, $templateCache) {
+ $scope.method = 'GET';
+ $scope.url = 'http-hello.html';
- $scope.fetch = function() {
- $scope.code = null;
- $scope.response = null;
+ $scope.fetch = function() {
+ $scope.code = null;
+ $scope.response = null;
- $http({method: $scope.method, url: $scope.url, cache: $templateCache}).
- success(function(data, status) {
- $scope.status = status;
- $scope.data = data;
- }).
- error(function(data, status) {
- $scope.data = data || "Request failed";
- $scope.status = status;
- });
- };
+ $http({method: $scope.method, url: $scope.url, cache: $templateCache}).
+ success(function(data, status) {
+ $scope.status = status;
+ $scope.data = data;
+ }).
+ error(function(data, status) {
+ $scope.data = data || "Request failed";
+ $scope.status = status;
+ });
+ };
- $scope.updateModel = function(method, url) {
- $scope.method = method;
- $scope.url = url;
- };
- }
+ $scope.updateModel = function(method, url) {
+ $scope.method = method;
+ $scope.url = url;
+ };
+ }]);
</file>
<file name="http-hello.html">
Hello, $http!
</file>
<file name="protractor.js" type="protractor">
@@ -17899,11 +17934,11 @@
var serverRequest = function(config) {
headers = config.headers;
var reqData = transformData(config.data, headersGetter(headers), config.transformRequest);
// strip content-type if data is undefined
- if (isUndefined(config.data)) {
+ if (isUndefined(reqData)) {
forEach(headers, function(value, header) {
if (lowercase(header) === 'content-type') {
delete headers[header];
}
});
@@ -17968,14 +18003,10 @@
reqHeaders = extend({}, config.headers),
defHeaderName, lowercaseDefHeaderName, reqHeaderName;
defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);
- // execute if header value is function
- execHeaders(defHeaders);
- execHeaders(reqHeaders);
-
// using for-in instead of forEach to avoid unecessary iteration after header has been found
defaultHeadersIteration:
for (defHeaderName in defHeaders) {
lowercaseDefHeaderName = lowercase(defHeaderName);
@@ -17986,10 +18017,12 @@
}
reqHeaders[defHeaderName] = defHeaders[defHeaderName];
}
+ // execute if header value is a function for merged headers
+ execHeaders(reqHeaders);
return reqHeaders;
function execHeaders(headers) {
var headerContent;
@@ -18893,29 +18926,31 @@
* @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
* will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
* @returns {promise} A promise which will be notified on each iteration.
*
* @example
- * <example module="time">
- * <file name="index.html">
- * <script>
- * function Ctrl2($scope,$interval) {
- * $scope.format = 'M/d/yy h:mm:ss a';
- * $scope.blood_1 = 100;
- * $scope.blood_2 = 120;
+ * <example module="intervalExample">
+ * <file name="index.html">
+ * <script>
+ * angular.module('intervalExample', [])
+ * .controller('ExampleController', ['$scope', '$interval',
+ * function($scope, $interval) {
+ * $scope.format = 'M/d/yy h:mm:ss a';
+ * $scope.blood_1 = 100;
+ * $scope.blood_2 = 120;
*
- * var stop;
- * $scope.fight = function() {
- * // Don't start a new fight if we are already fighting
- * if ( angular.isDefined(stop) ) return;
+ * var stop;
+ * $scope.fight = function() {
+ * // Don't start a new fight if we are already fighting
+ * if ( angular.isDefined(stop) ) return;
*
* stop = $interval(function() {
* if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
- * $scope.blood_1 = $scope.blood_1 - 3;
- * $scope.blood_2 = $scope.blood_2 - 4;
+ * $scope.blood_1 = $scope.blood_1 - 3;
+ * $scope.blood_2 = $scope.blood_2 - 4;
* } else {
- * $scope.stopFight();
+ * $scope.stopFight();
* }
* }, 100);
* };
*
* $scope.stopFight = function() {
@@ -18926,26 +18961,25 @@
* };
*
* $scope.resetFight = function() {
* $scope.blood_1 = 100;
* $scope.blood_2 = 120;
- * }
+ * };
*
* $scope.$on('$destroy', function() {
- * // Make sure that the interval is destroyed too
+ * // Make sure that the interval nis destroyed too
* $scope.stopFight();
* });
- * }
- *
- * angular.module('time', [])
- * // Register the 'myCurrentTime' directive factory method.
- * // We inject $interval and dateFilter service since the factory method is DI.
- * .directive('myCurrentTime', function($interval, dateFilter) {
+ * })
+ * // Register the 'myCurrentTime' directive factory method.
+ * // We inject $interval and dateFilter service since the factory method is DI.
+ * .directive('myCurrentTime', ['$interval', 'dateFilter',
+ * function($interval, dateFilter) {
* // return the directive link function. (compile function not needed)
* return function(scope, element, attrs) {
* var format, // date format
- * stopTime; // so that we can cancel the time updates
+ * stopTime; // so that we can cancel the time updates
*
* // used to update the UI
* function updateTime() {
* element.text(dateFilter(new Date(), format));
* }
@@ -18957,32 +18991,32 @@
* });
*
* stopTime = $interval(updateTime, 1000);
*
* // listen on DOM destroy (removal) event, and cancel the next UI update
- * // to prevent updating time ofter the DOM element was removed.
+ * // to prevent updating time after the DOM element was removed.
* element.on('$destroy', function() {
* $interval.cancel(stopTime);
* });
* }
* });
- * </script>
+ * </script>
*
- * <div>
- * <div ng-controller="Ctrl2">
- * Date format: <input ng-model="format"> <hr/>
- * Current time is: <span my-current-time="format"></span>
- * <hr/>
- * Blood 1 : <font color='red'>{{blood_1}}</font>
- * Blood 2 : <font color='red'>{{blood_2}}</font>
- * <button type="button" data-ng-click="fight()">Fight</button>
- * <button type="button" data-ng-click="stopFight()">StopFight</button>
- * <button type="button" data-ng-click="resetFight()">resetFight</button>
- * </div>
+ * <div>
+ * <div ng-controller="ExampleController">
+ * Date format: <input ng-model="format"> <hr/>
+ * Current time is: <span my-current-time="format"></span>
+ * <hr/>
+ * Blood 1 : <font color='red'>{{blood_1}}</font>
+ * Blood 2 : <font color='red'>{{blood_2}}</font>
+ * <button type="button" data-ng-click="fight()">Fight</button>
+ * <button type="button" data-ng-click="stopFight()">StopFight</button>
+ * <button type="button" data-ng-click="resetFight()">resetFight</button>
* </div>
+ * </div>
*
- * </file>
+ * </file>
* </example>
*/
function interval(fn, delay, count, invokeApply) {
var setInterval = $window.setInterval,
clearInterval = $window.clearInterval,
@@ -19535,18 +19569,21 @@
* of `$location` to the specified value.
*
* If the argument is a hash object containing an array of values, these values will be encoded
* as duplicate search parameters in the url.
*
- * @param {(string|Array<string>)=} paramValue If `search` is a string, then `paramValue` will
- * override only a single search property.
+ * @param {(string|Array<string>|boolean)=} paramValue If `search` is a string, then `paramValue`
+ * will override only a single search property.
*
* If `paramValue` is an array, it will override the property of the `search` component of
* `$location` specified via the first argument.
*
* If `paramValue` is `null`, the property specified via the first argument will be deleted.
*
+ * If `paramValue` is `true`, the property specified via the first argument will be added with no
+ * value nor trailing equal sign.
+ *
* @return {Object} If called with no arguments returns the parsed `search` object. If called with
* one or more arguments returns `$location` object itself.
*/
search: function(search, paramValue) {
switch (arguments.length) {
@@ -19554,10 +19591,15 @@
return this.$$search;
case 1:
if (isString(search)) {
this.$$search = parseKeyValue(search);
} else if (isObject(search)) {
+ // remove object undefined or null properties
+ forEach(search, function(value, key) {
+ if (value == null) delete search[key];
+ });
+
this.$$search = search;
} else {
throw $locationMinErr('isrcharg',
'The first argument of the `$location#search()` call must be a string or an object.');
}
@@ -19875,19 +19917,20 @@
*
* The default is to log `debug` messages. You can use
* {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.
*
* @example
- <example>
+ <example module="logExample">
<file name="script.js">
- function LogCtrl($scope, $log) {
- $scope.$log = $log;
- $scope.message = 'Hello World!';
- }
+ angular.module('logExample', [])
+ .controller('LogController', ['$scope', '$log', function($scope, $log) {
+ $scope.$log = $log;
+ $scope.message = 'Hello World!';
+ }]);
</file>
<file name="index.html">
- <div ng-controller="LogCtrl">
+ <div ng-controller="LogController">
<p>Reload this page with open console, enter text and hit the log button...</p>
Message:
<input type="text" ng-model="message"/>
<button ng-click="$log.log(message)">log</button>
<button ng-click="$log.warn(message)">warn</button>
@@ -19907,11 +19950,11 @@
function $LogProvider(){
var debug = true,
self = this;
/**
- * @ngdoc property
+ * @ngdoc method
* @name $logProvider#debugEnabled
* @description
* @param {boolean=} flag enable or disable debug level messages
* @returns {*} current value if used as getter or itself (chaining) if used as setter
*/
@@ -20896,30 +20939,10 @@
return pathVal;
};
}
-function simpleGetterFn1(key0, fullExp) {
- ensureSafeMemberName(key0, fullExp);
-
- return function simpleGetterFn1(scope, locals) {
- if (scope == null) return undefined;
- return ((locals && locals.hasOwnProperty(key0)) ? locals : scope)[key0];
- };
-}
-
-function simpleGetterFn2(key0, key1, fullExp) {
- ensureSafeMemberName(key0, fullExp);
- ensureSafeMemberName(key1, fullExp);
-
- return function simpleGetterFn2(scope, locals) {
- if (scope == null) return undefined;
- scope = ((locals && locals.hasOwnProperty(key0)) ? locals : scope)[key0];
- return scope == null ? undefined : scope[key1];
- };
-}
-
function getterFn(path, options, fullExp) {
// Check whether the cache has this getter already.
// We can use hasOwnProperty directly on the cache because we ensure,
// see below, that the cache never stores a path called 'hasOwnProperty'
if (getterFnCache.hasOwnProperty(path)) {
@@ -20928,17 +20951,12 @@
var pathKeys = path.split('.'),
pathKeysLength = pathKeys.length,
fn;
- // When we have only 1 or 2 tokens, use optimized special case closures.
// http://jsperf.com/angularjs-parse-getter/6
- if (pathKeysLength === 1) {
- fn = simpleGetterFn1(pathKeys[0], fullExp);
- } else if (pathKeysLength === 2) {
- fn = simpleGetterFn2(pathKeys[0], pathKeys[1], fullExp);
- } else if (options.csp) {
+ if (options.csp) {
if (pathKeysLength < 6) {
fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp);
} else {
fn = function(scope, locals) {
var i = 0, val;
@@ -23072,23 +23090,25 @@
* `http://srv01.assets.example.com/`, `http://srv02.assets.example.com/`, etc.
* - and you have an open redirect at `http://myapp.example.com/clickThru?...`.
*
* Here is what a secure configuration for this scenario might look like:
*
- * <pre class="prettyprint">
- * angular.module('myApp', []).config(function($sceDelegateProvider) {
- * $sceDelegateProvider.resourceUrlWhitelist([
- * // Allow same origin resource loads.
- * 'self',
- * // Allow loading from our assets domain. Notice the difference between * and **.
- * 'http://srv*.assets.example.com/**']);
+ * ```
+ * angular.module('myApp', []).config(function($sceDelegateProvider) {
+ * $sceDelegateProvider.resourceUrlWhitelist([
+ * // Allow same origin resource loads.
+ * 'self',
+ * // Allow loading from our assets domain. Notice the difference between * and **.
+ * 'http://srv*.assets.example.com/**'
+ * ]);
*
- * // The blacklist overrides the whitelist so the open redirect here is blocked.
- * $sceDelegateProvider.resourceUrlBlacklist([
- * 'http://myapp.example.com/clickThru**']);
- * });
- * </pre>
+ * // The blacklist overrides the whitelist so the open redirect here is blocked.
+ * $sceDelegateProvider.resourceUrlBlacklist([
+ * 'http://myapp.example.com/clickThru**'
+ * ]);
+ * });
+ * ```
*/
function $SceDelegateProvider() {
this.SCE_CONTEXTS = SCE_CONTEXTS;
@@ -23379,14 +23399,14 @@
* SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for
* security vulnerabilities such as XSS, clickjacking, etc. a lot easier.
*
* Here's an example of a binding in a privileged context:
*
- * <pre class="prettyprint">
- * <input ng-model="userHtml">
- * <div ng-bind-html="userHtml">
- * </pre>
+ * ```
+ * <input ng-model="userHtml">
+ * <div ng-bind-html="userHtml"></div>
+ * ```
*
* Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE
* disabled, this application allows the user to render arbitrary HTML into the DIV.
* In a more realistic example, one may be rendering user comments, blog articles, etc. via
* bindings. (HTML is just one example of a context where rendering user controlled input creates
@@ -23422,19 +23442,19 @@
*
* As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link
* ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly
* simplified):
*
- * <pre class="prettyprint">
- * var ngBindHtmlDirective = ['$sce', function($sce) {
- * return function(scope, element, attr) {
- * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
- * element.html(value || '');
- * });
- * };
- * }];
- * </pre>
+ * ```
+ * var ngBindHtmlDirective = ['$sce', function($sce) {
+ * return function(scope, element, attr) {
+ * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
+ * element.html(value || '');
+ * });
+ * };
+ * }];
+ * ```
*
* ## Impact on loading templates
*
* This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as
* `templateUrl`'s specified by {@link guide/directive directives}.
@@ -23534,90 +23554,89 @@
*
* Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.
*
* ## Show me an example using SCE.
*
- * @example
-<example module="mySceApp" deps="angular-sanitize.js">
-<file name="index.html">
- <div ng-controller="myAppController as myCtrl">
- <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
- <b>User comments</b><br>
- By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
- $sanitize is available. If $sanitize isn't available, this results in an error instead of an
- exploit.
- <div class="well">
- <div ng-repeat="userComment in myCtrl.userComments">
- <b>{{userComment.name}}</b>:
- <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span>
- <br>
- </div>
- </div>
- </div>
-</file>
-
-<file name="script.js">
- var mySceApp = angular.module('mySceApp', ['ngSanitize']);
-
- mySceApp.controller("myAppController", function myAppController($http, $templateCache, $sce) {
- var self = this;
- $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
- self.userComments = userComments;
- });
- self.explicitlyTrustedHtml = $sce.trustAsHtml(
- '<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' +
- 'sanitization."">Hover over this text.</span>');
- });
-</file>
-
-<file name="test_data.json">
-[
- { "name": "Alice",
- "htmlComment":
- "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
- },
- { "name": "Bob",
- "htmlComment": "<i>Yes!</i> Am I the only other one?"
- }
-]
-</file>
-
-<file name="protractor.js" type="protractor">
- describe('SCE doc demo', function() {
- it('should sanitize untrusted values', function() {
- expect(element(by.css('.htmlComment')).getInnerHtml())
- .toBe('<span>Is <i>anyone</i> reading this?</span>');
- });
-
- it('should NOT sanitize explicitly trusted values', function() {
- expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(
- '<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' +
- 'sanitization."">Hover over this text.</span>');
- });
- });
-</file>
-</example>
+ * <example module="mySceApp" deps="angular-sanitize.js">
+ * <file name="index.html">
+ * <div ng-controller="AppController as myCtrl">
+ * <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
+ * <b>User comments</b><br>
+ * By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
+ * $sanitize is available. If $sanitize isn't available, this results in an error instead of an
+ * exploit.
+ * <div class="well">
+ * <div ng-repeat="userComment in myCtrl.userComments">
+ * <b>{{userComment.name}}</b>:
+ * <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span>
+ * <br>
+ * </div>
+ * </div>
+ * </div>
+ * </file>
*
+ * <file name="script.js">
+ * angular.module('mySceApp', ['ngSanitize'])
+ * .controller('AppController', ['$http', '$templateCache', '$sce',
+ * function($http, $templateCache, $sce) {
+ * var self = this;
+ * $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
+ * self.userComments = userComments;
+ * });
+ * self.explicitlyTrustedHtml = $sce.trustAsHtml(
+ * '<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' +
+ * 'sanitization."">Hover over this text.</span>');
+ * }]);
+ * </file>
*
+ * <file name="test_data.json">
+ * [
+ * { "name": "Alice",
+ * "htmlComment":
+ * "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
+ * },
+ * { "name": "Bob",
+ * "htmlComment": "<i>Yes!</i> Am I the only other one?"
+ * }
+ * ]
+ * </file>
*
+ * <file name="protractor.js" type="protractor">
+ * describe('SCE doc demo', function() {
+ * it('should sanitize untrusted values', function() {
+ * expect(element.all(by.css('.htmlComment')).first().getInnerHtml())
+ * .toBe('<span>Is <i>anyone</i> reading this?</span>');
+ * });
+ *
+ * it('should NOT sanitize explicitly trusted values', function() {
+ * expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(
+ * '<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' +
+ * 'sanitization."">Hover over this text.</span>');
+ * });
+ * });
+ * </file>
+ * </example>
+ *
+ *
+ *
* ## Can I disable SCE completely?
*
* Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits
* for little coding overhead. It will be much harder to take an SCE disabled application and
* either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE
* for cases where you have a lot of existing code that was written before SCE was introduced and
* you're migrating them a module at a time.
*
* That said, here's how you can completely disable SCE:
*
- * <pre class="prettyprint">
- * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
- * // Completely disable SCE. For demonstration purposes only!
- * // Do not use in new projects.
- * $sceProvider.enabled(false);
- * });
- * </pre>
+ * ```
+ * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
+ * // Completely disable SCE. For demonstration purposes only!
+ * // Do not use in new projects.
+ * $sceProvider.enabled(false);
+ * });
+ * ```
*
*/
/* jshint maxlen: 100 */
function $SceProvider() {
@@ -24312,21 +24331,22 @@
* below, are evaluated with respect to the current scope. Therefore, there is
* no risk of inadvertently coding in a dependency on a global value in such an
* expression.
*
* @example
- <example>
+ <example module="windowExample">
<file name="index.html">
<script>
- function Ctrl($scope, $window) {
- $scope.greeting = 'Hello, World!';
- $scope.doGreeting = function(greeting) {
+ angular.module('windowExample', [])
+ .controller('ExampleController', ['$scope', '$window', function ($scope, $window) {
+ $scope.greeting = 'Hello, World!';
+ $scope.doGreeting = function(greeting) {
$window.alert(greeting);
- };
- }
+ };
+ }]);
</script>
- <div ng-controller="Ctrl">
+ <div ng-controller="ExampleController">
<input type="text" ng-model="greeting" />
<button ng-click="doGreeting(greeting)">ALERT</button>
</div>
</file>
<file name="protractor.js" type="protractor">
@@ -24340,10 +24360,21 @@
*/
function $WindowProvider(){
this.$get = valueFn(window);
}
+/* global currencyFilter: true,
+ dateFilter: true,
+ filterFilter: true,
+ jsonFilter: true,
+ limitToFilter: true,
+ lowercaseFilter: true,
+ numberFilter: true,
+ orderByFilter: true,
+ uppercaseFilter: true,
+ */
+
/**
* @ngdoc provider
* @name $filterProvider
* @description
*
@@ -24721,18 +24752,19 @@
* @param {string=} symbol Currency symbol or identifier to be displayed.
* @returns {string} Formatted number.
*
*
* @example
- <example>
+ <example module="currencyExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.amount = 1234.56;
- }
+ angular.module('currencyExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.amount = 1234.56;
+ }]);
</script>
- <div ng-controller="Ctrl">
+ <div ng-controller="ExampleController">
<input type="number" ng-model="amount"> <br>
default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br>
custom currency identifier (USD$): <span>{{amount | currency:"USD$"}}</span>
</div>
</file>
@@ -24780,18 +24812,19 @@
* If this is not provided then the fraction size is computed from the current locale's number
* formatting pattern. In the case of the default locale, it will be 3.
* @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
*
* @example
- <example>
+ <example module="numberFilterExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.val = 1234.56789;
- }
+ angular.module('numberFilterExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.val = 1234.56789;
+ }]);
</script>
- <div ng-controller="Ctrl">
+ <div ng-controller="ExampleController">
Enter number: <input ng-model='val'><br>
Default formatting: <span id='number-default'>{{val | number}}</span><br>
No fractions: <span>{{val | number:0}}</span><br>
Negative number: <span>{{-val | number:4}}</span>
</div>
@@ -25241,21 +25274,22 @@
* are copied. The `limit` will be trimmed if it exceeds `array.length`
* @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
* had less than `limit` elements.
*
* @example
- <example>
+ <example module="limitToExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.numbers = [1,2,3,4,5,6,7,8,9];
- $scope.letters = "abcdefghi";
- $scope.numLimit = 3;
- $scope.letterLimit = 3;
- }
+ angular.module('limitToExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.numbers = [1,2,3,4,5,6,7,8,9];
+ $scope.letters = "abcdefghi";
+ $scope.numLimit = 3;
+ $scope.letterLimit = 3;
+ }]);
</script>
- <div ng-controller="Ctrl">
+ <div ng-controller="ExampleController">
Limit {{numbers}} to: <input type="integer" ng-model="numLimit">
<p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
Limit {{letters}} to: <input type="integer" ng-model="letterLimit">
<p>Output letters: {{ letters | limitTo:letterLimit }}</p>
</div>
@@ -25363,24 +25397,25 @@
*
* @param {boolean=} reverse Reverse the order of the array.
* @returns {Array} Sorted copy of the source array.
*
* @example
- <example>
+ <example module="orderByExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.friends =
- [{name:'John', phone:'555-1212', age:10},
- {name:'Mary', phone:'555-9876', age:19},
- {name:'Mike', phone:'555-4321', age:21},
- {name:'Adam', phone:'555-5678', age:35},
- {name:'Julie', phone:'555-8765', age:29}]
- $scope.predicate = '-age';
- }
+ angular.module('orderByExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.friends =
+ [{name:'John', phone:'555-1212', age:10},
+ {name:'Mary', phone:'555-9876', age:19},
+ {name:'Mike', phone:'555-4321', age:21},
+ {name:'Adam', phone:'555-5678', age:35},
+ {name:'Julie', phone:'555-8765', age:29}];
+ $scope.predicate = '-age';
+ }]);
</script>
- <div ng-controller="Ctrl">
+ <div ng-controller="ExampleController">
<pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
<hr/>
[ <a href="" ng-click="predicate=''">unsorted</a> ]
<table class="friend">
<tr>
@@ -25404,11 +25439,11 @@
* desired parameters.
*
* Example:
*
* @example
- <example>
+ <example module="orderByExample">
<file name="index.html">
<div ng-controller="Ctrl">
<table class="friend">
<tr>
<th><a href="" ng-click="reverse=false;order('name', false)">Name</a>
@@ -25424,25 +25459,25 @@
</table>
</div>
</file>
<file name="script.js">
- function Ctrl($scope, $filter) {
- var orderBy = $filter('orderBy');
- $scope.friends = [
- { name: 'John', phone: '555-1212', age: 10 },
- { name: 'Mary', phone: '555-9876', age: 19 },
- { name: 'Mike', phone: '555-4321', age: 21 },
- { name: 'Adam', phone: '555-5678', age: 35 },
- { name: 'Julie', phone: '555-8765', age: 29 }
- ];
-
- $scope.order = function(predicate, reverse) {
- $scope.friends = orderBy($scope.friends, predicate, reverse);
- };
- $scope.order('-age',false);
- }
+ angular.module('orderByExample', [])
+ .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {
+ var orderBy = $filter('orderBy');
+ $scope.friends = [
+ { name: 'John', phone: '555-1212', age: 10 },
+ { name: 'Mary', phone: '555-9876', age: 19 },
+ { name: 'Mike', phone: '555-4321', age: 21 },
+ { name: 'Adam', phone: '555-5678', age: 35 },
+ { name: 'Julie', phone: '555-8765', age: 29 }
+ ];
+ $scope.order = function(predicate, reverse) {
+ $scope.friends = orderBy($scope.friends, predicate, reverse);
+ };
+ $scope.order('-age',false);
+ }]);
</file>
</example>
*/
orderByFilter.$inject = ['$parse'];
function orderByFilter($parse){
@@ -25624,11 +25659,11 @@
browser.wait(function() {
return browser.driver.getCurrentUrl().then(function(url) {
return url.match(/\/123$/);
});
- }, 1000, 'page should navigate to /123');
+ }, 5000, 'page should navigate to /123');
});
xit('should execute ng-click but not reload when href empty string and name specified', function() {
element(by.id('link-4')).click();
expect(element(by.model('value')).getAttribute('value')).toEqual('4');
@@ -25652,11 +25687,11 @@
// to use browser.driver to get the base webdriver.
browser.wait(function() {
return browser.driver.getCurrentUrl().then(function(url) {
return url.match(/\/6$/);
});
- }, 1000, 'page should navigate to /6');
+ }, 5000, 'page should navigate to /6');
});
</file>
</example>
*/
@@ -26053,10 +26088,27 @@
$animate.addClass(element, (isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);
}
/**
* @ngdoc method
+ * @name form.FormController#$rollbackViewValue
+ *
+ * @description
+ * Rollback all form controls pending updates to the `$modelValue`.
+ *
+ * Updates may be pending by a debounced event or because the input is waiting for a some future
+ * event defined in `ng-model-options`. This method is typically needed by the reset button of
+ * a form that uses `ng-model-options` to pend updates.
+ */
+ form.$rollbackViewValue = function() {
+ forEach(controls, function(control) {
+ control.$rollbackViewValue();
+ });
+ };
+
+ /**
+ * @ngdoc method
* @name form.FormController#$commitViewValue
*
* @description
* Commit all form controls pending updates to the `$modelValue`.
*
@@ -26312,16 +26364,17 @@
* color:white;
* }
* </pre>
*
* @example
- <example deps="angular-animate.js" animations="true" fixBase="true">
+ <example deps="angular-animate.js" animations="true" fixBase="true" module="formExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.userType = 'guest';
- }
+ angular.module('formExample', [])
+ .controller('FormController', ['$scope', function($scope) {
+ $scope.userType = 'guest';
+ }]);
</script>
<style>
.my-form {
-webkit-transition:all linear 0.5s;
transition:all linear 0.5s;
@@ -26329,11 +26382,11 @@
}
.my-form.ng-invalid {
background: red;
}
</style>
- <form name="myForm" ng-controller="Ctrl" class="my-form">
+ <form name="myForm" ng-controller="FormController" class="my-form">
userType: <input name="input" ng-model="userType" required>
<span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
<tt>userType = {{userType}}</tt><br>
<tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>
<tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>
@@ -26427,22 +26480,20 @@
};
var formDirective = formDirectiveFactory();
var ngFormDirective = formDirectiveFactory(true);
-/* global
-
- -VALID_CLASS,
- -INVALID_CLASS,
- -PRISTINE_CLASS,
- -DIRTY_CLASS,
- -UNTOUCHED_CLASS,
- -TOUCHED_CLASS
+/* global VALID_CLASS: true,
+ INVALID_CLASS: true,
+ PRISTINE_CLASS: true,
+ DIRTY_CLASS: true,
+ UNTOUCHED_CLASS: true,
+ TOUCHED_CLASS: true,
*/
var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
-var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*$/i;
+var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)$/;
var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/;
var MONTH_REGEXP = /^(\d{4})-(\d\d)$/;
@@ -26474,19 +26525,20 @@
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
* @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
*
* @example
- <example name="text-input-directive">
+ <example name="text-input-directive" module="textInputExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.text = 'guest';
- $scope.word = /^\s*\w*\s*$/;
- }
+ angular.module('textInputExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.text = 'guest';
+ $scope.word = /^\s*\w*\s*$/;
+ }]);
</script>
- <form name="myForm" ng-controller="Ctrl">
+ <form name="myForm" ng-controller="ExampleController">
Single word: <input type="text" name="input" ng-model="text"
ng-pattern="word" required ng-trim="false">
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.pattern">
@@ -26549,18 +26601,19 @@
* `required` when you want to data-bind to the `required` attribute.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
*
* @example
- <example name="date-input-directive">
+ <example name="date-input-directive" module="dateInputExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.value = new Date(2013, 9, 22);
- }
+ angular.module('dateInputExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.value = new Date(2013, 9, 22);
+ }]);
</script>
- <form name="myForm" ng-controller="Ctrl as dateCtrl">
+ <form name="myForm" ng-controller="DateController as dateCtrl">
Pick a date between in 2013:
<input type="date" id="exampleInput" name="input" ng-model="value"
placeholder="yyyy-MM-dd" min="2013-01-01" max="2013-12-31" required />
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
@@ -26633,18 +26686,19 @@
* `required` when you want to data-bind to the `required` attribute.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
*
* @example
- <example name="datetimelocal-input-directive">
+ <example name="datetimelocal-input-directive" module="dateExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.value = new Date(2010, 11, 28, 14, 57);
- }
+ angular.module('dateExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.value = new Date(2010, 11, 28, 14, 57);
+ }]);
</script>
- <form name="myForm" ng-controller="Ctrl as dateCtrl">
+ <form name="myForm" ng-controller="DateController as dateCtrl">
Pick a date between in 2013:
<input type="datetime-local" id="exampleInput" name="input" ng-model="value"
placeholder="yyyy-MM-ddTHH:mm" min="2001-01-01T00:00" max="2013-12-31T00:00" required />
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
@@ -26718,18 +26772,19 @@
* `required` when you want to data-bind to the `required` attribute.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
*
* @example
- <example name="time-input-directive">
+ <example name="time-input-directive" module="timeExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.value = new Date(0, 0, 1, 14, 57);
- }
+ angular.module('timeExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.value = new Date(0, 0, 1, 14, 57);
+ }]);
</script>
- <form name="myForm" ng-controller="Ctrl as dateCtrl">
+ <form name="myForm" ng-controller="DateController as dateCtrl">
Pick a between 8am and 5pm:
<input type="time" id="exampleInput" name="input" ng-model="value"
placeholder="HH:mm" min="08:00" max="17:00" required />
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
@@ -26802,18 +26857,19 @@
* `required` when you want to data-bind to the `required` attribute.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
*
* @example
- <example name="week-input-directive">
+ <example name="week-input-directive" module="weekExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.value = new Date(2013, 0, 3);
- }
+ angular.module('weekExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.value = new Date(2013, 0, 3);
+ }]);
</script>
- <form name="myForm" ng-controller="Ctrl as dateCtrl">
+ <form name="myForm" ng-controller="DateController as dateCtrl">
Pick a date between in 2013:
<input id="exampleInput" type="week" name="input" ng-model="value"
placeholder="YYYY-W##" min="2012-W32" max="2013-W52" required />
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
@@ -26885,18 +26941,19 @@
* `required` when you want to data-bind to the `required` attribute.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
*
* @example
- <example name="month-input-directive">
+ <example name="month-input-directive" module="monthExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.value = new Date(2013, 9, 1);
- }
+ angular.module('monthExample', [])
+ .controller('DateController', ['$scope', function($scope) {
+ $scope.value = new Date(2013, 9, 1);
+ }]);
</script>
- <form name="myForm" ng-controller="Ctrl as dateCtrl">
+ <form name="myForm" ng-controller="DateController as dateCtrl">
Pick a month int 2013:
<input id="exampleInput" type="month" name="input" ng-model="value"
placeholder="yyyy-MM" min="2013-01" max="2013-12" required />
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
@@ -26973,18 +27030,19 @@
* patterns defined as scope expressions.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
*
* @example
- <example name="number-input-directive">
+ <example name="number-input-directive" module="numberExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.value = 12;
- }
+ angular.module('numberExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.value = 12;
+ }]);
</script>
- <form name="myForm" ng-controller="Ctrl">
+ <form name="myForm" ng-controller="ExampleController">
Number: <input type="number" name="input" ng-model="value"
min="0" max="99" required>
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.number">
@@ -27048,18 +27106,19 @@
* patterns defined as scope expressions.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
*
* @example
- <example name="url-input-directive">
+ <example name="url-input-directive" module="urlExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.text = 'http://google.com';
- }
+ angular.module('urlExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.text = 'http://google.com';
+ }]);
</script>
- <form name="myForm" ng-controller="Ctrl">
+ <form name="myForm" ng-controller="ExampleController">
URL: <input type="url" name="input" ng-model="text" required>
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.url">
Not valid url!</span>
@@ -27124,18 +27183,19 @@
* patterns defined as scope expressions.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
*
* @example
- <example name="email-input-directive">
+ <example name="email-input-directive" module="emailExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.text = 'me@example.com';
- }
+ angular.module('emailExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.text = 'me@example.com';
+ }]);
</script>
- <form name="myForm" ng-controller="Ctrl">
+ <form name="myForm" ng-controller="ExampleController">
Email: <input type="email" name="input" ng-model="text" required>
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.email">
Not valid email!</span>
@@ -27190,22 +27250,23 @@
* interaction with the input element.
* @param {string} ngValue Angular expression which sets the value to which the expression should
* be set when selected.
*
* @example
- <example name="radio-input-directive">
+ <example name="radio-input-directive" module="radioExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.color = 'blue';
- $scope.specialValue = {
- "id": "12345",
- "value": "green"
- };
- }
+ angular.module('radioExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.color = 'blue';
+ $scope.specialValue = {
+ "id": "12345",
+ "value": "green"
+ };
+ }]);
</script>
- <form name="myForm" ng-controller="Ctrl">
+ <form name="myForm" ng-controller="ExampleController">
<input type="radio" ng-model="color" value="red"> Red <br/>
<input type="radio" ng-model="color" ng-value="specialValue"> Green <br/>
<input type="radio" ng-model="color" value="blue"> Blue <br/>
<tt>color = {{color | json}}</tt><br/>
</form>
@@ -27234,28 +27295,29 @@
* @description
* HTML checkbox.
*
* @param {string} ngModel Assignable angular expression to data-bind to.
* @param {string=} name Property name of the form under which the control is published.
- * @param {string=} ngTrueValue The value to which the expression should be set when selected.
- * @param {string=} ngFalseValue The value to which the expression should be set when not selected.
+ * @param {expression=} ngTrueValue The value to which the expression should be set when selected.
+ * @param {expression=} ngFalseValue The value to which the expression should be set when not selected.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
*
* @example
- <example name="checkbox-input-directive">
+ <example name="checkbox-input-directive" module="checkboxExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.value1 = true;
- $scope.value2 = 'YES'
- }
+ angular.module('checkboxExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.value1 = true;
+ $scope.value2 = 'YES'
+ }]);
</script>
- <form name="myForm" ng-controller="Ctrl">
+ <form name="myForm" ng-controller="ExampleController">
Value1: <input type="checkbox" ng-model="value1"> <br/>
Value2: <input type="checkbox" ng-model="value2"
- ng-true-value="YES" ng-false-value="NO"> <br/>
+ ng-true-value="'YES'" ng-false-value="'NO'"> <br/>
<tt>value1 = {{value1}}</tt><br/>
<tt>value2 = {{value2}}</tt><br/>
</form>
</file>
<file name="protractor.js" type="protractor">
@@ -27610,16 +27672,26 @@
};
attr.$observe('value', ctrl.$render);
}
-function checkboxInputType(scope, element, attr, ctrl) {
- var trueValue = attr.ngTrueValue,
- falseValue = attr.ngFalseValue;
+function parseConstantExpr($parse, context, name, expression, fallback) {
+ var parseFn;
+ if (isDefined(expression)) {
+ parseFn = $parse(expression);
+ if (!parseFn.constant) {
+ throw new minErr('ngModel')('constexpr', 'Expected constant expression for `{0}`, but saw ' +
+ '`{1}`.', name, expression);
+ }
+ return parseFn(context);
+ }
+ return fallback;
+}
- if (!isString(trueValue)) trueValue = true;
- if (!isString(falseValue)) falseValue = false;
+function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {
+ var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true);
+ var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false);
var listener = function(ev) {
scope.$apply(function() {
ctrl.$setViewValue(element[0].checked, ev && ev.type);
});
@@ -27635,11 +27707,11 @@
ctrl.$isEmpty = function(value) {
return value !== trueValue;
};
ctrl.$formatters.push(function(value) {
- return value === trueValue;
+ return equals(value, trueValue);
});
ctrl.$parsers.push(function(value) {
return value ? trueValue : falseValue;
});
@@ -27697,18 +27769,19 @@
* patterns defined as scope expressions.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
*
* @example
- <example name="input-directive">
+ <example name="input-directive" module="inputExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.user = {name: 'guest', last: 'visitor'};
- }
+ angular.module('inputExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.user = {name: 'guest', last: 'visitor'};
+ }]);
</script>
- <div ng-controller="Ctrl">
+ <div ng-controller="ExampleController">
<form name="myForm">
User name: <input type="text" name="userName" ng-model="user.name" required>
<span class="error" ng-show="myForm.userName.$error.required">
Required!</span><br>
Last name: <input type="text" name="lastName" ng-model="user.last"
@@ -27783,18 +27856,19 @@
expect(formValid.getText()).toContain('false');
});
</file>
</example>
*/
-var inputDirective = ['$browser', '$sniffer', '$filter', function($browser, $sniffer, $filter) {
+var inputDirective = ['$browser', '$sniffer', '$filter', '$parse',
+ function($browser, $sniffer, $filter, $parse) {
return {
restrict: 'E',
require: ['?ngModel'],
link: function(scope, element, attr, ctrls) {
if (ctrls[0]) {
(inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,
- $browser, $filter);
+ $browser, $filter, $parse);
}
}
};
}];
@@ -27984,10 +28058,22 @@
* @name ngModel.NgModelController#$render
*
* @description
* Called when the view needs to be updated. It is expected that the user of the ng-model
* directive will implement this method.
+ *
+ * The `$render()` method is invoked in the following situations:
+ *
+ * * `$rollbackViewValue()` is called. If we are rolling back the view value to the last
+ * committed value then `$render()` is called to update the input control.
+ * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and
+ * the `$viewValue` are different to last time.
+ *
+ * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of
+ * `$modelValue` and `$viewValue` are actually different to their previous value. If `$modelValue`
+ * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be
+ * invoked if you only change a property on the objects.
*/
this.$render = noop;
/**
* @ngdoc method
@@ -28149,11 +28235,11 @@
*
* <example name="ng-model-cancel-update" module="cancel-update-example">
* <file name="app.js">
* angular.module('cancel-update-example', [])
*
- * .controller('CancelUpdateCtrl', function($scope) {
+ * .controller('CancelUpdateController', ['$scope', function($scope) {
* $scope.resetWithCancel = function (e) {
* if (e.keyCode == 27) {
* $scope.myForm.myInput1.$rollbackViewValue();
* $scope.myValue = '';
* }
@@ -28161,14 +28247,14 @@
* $scope.resetWithoutCancel = function (e) {
* if (e.keyCode == 27) {
* $scope.myValue = '';
* }
* };
- * });
+ * }]);
* </file>
* <file name="index.html">
- * <div ng-controller="CancelUpdateCtrl">
+ * <div ng-controller="CancelUpdateController">
* <p>Try typing something in each input. See that the model only updates when you
* blur off the input.
* </p>
* <p>Now see what happens if you start typing then press the Escape key</p>
*
@@ -28197,17 +28283,28 @@
*
* @description
* Runs each of the registered validations set on the $validators object.
*/
this.$validate = function() {
- this.$$runValidators(ctrl.$modelValue, ctrl.$viewValue);
+ // ignore $validate before model initialized
+ if (ctrl.$modelValue !== ctrl.$modelValue) {
+ return;
+ }
+
+ var prev = ctrl.$modelValue;
+ ctrl.$$runValidators(ctrl.$$invalidModelValue || ctrl.$modelValue, ctrl.$viewValue);
+ if (prev !== ctrl.$modelValue) {
+ ctrl.$$writeModelToScope();
+ }
};
this.$$runValidators = function(modelValue, viewValue) {
forEach(ctrl.$validators, function(fn, name) {
ctrl.$setValidity(name, fn(modelValue, viewValue));
});
+ ctrl.$modelValue = ctrl.$valid ? modelValue : undefined;
+ ctrl.$$invalidModelValue = ctrl.$valid ? undefined : modelValue;
};
/**
* @ngdoc method
* @name ngModel.NgModelController#$commitViewValue
@@ -28242,41 +28339,61 @@
modelValue = fn(modelValue);
});
if (ctrl.$modelValue !== modelValue &&
(isUndefined(ctrl.$$invalidModelValue) || ctrl.$$invalidModelValue != modelValue)) {
-
ctrl.$$runValidators(modelValue, viewValue);
- ctrl.$modelValue = ctrl.$valid ? modelValue : undefined;
- ctrl.$$invalidModelValue = ctrl.$valid ? undefined : modelValue;
+ ctrl.$$writeModelToScope();
+ }
+ };
+ this.$$writeModelToScope = function() {
+ var getterSetter;
+
+ if (ctrl.$options && ctrl.$options.getterSetter &&
+ isFunction(getterSetter = ngModelGet($scope))) {
+
+ getterSetter(ctrl.$modelValue);
+ } else {
ngModelSet($scope, ctrl.$modelValue);
- forEach(ctrl.$viewChangeListeners, function(listener) {
- try {
- listener();
- } catch(e) {
- $exceptionHandler(e);
- }
- });
}
+ forEach(ctrl.$viewChangeListeners, function(listener) {
+ try {
+ listener();
+ } catch(e) {
+ $exceptionHandler(e);
+ }
+ });
};
/**
* @ngdoc method
* @name ngModel.NgModelController#$setViewValue
*
* @description
* Update the view value.
*
- * This method should be called when the view value changes, typically from within a DOM event handler.
- * For example {@link ng.directive:input input} and
- * {@link ng.directive:select select} directives call it.
+ * This method should be called when an input directive want to change the view value; typically,
+ * this is done from within a DOM event handler.
*
- * It will update the $viewValue, then pass this value through each of the functions in `$parsers`,
- * which includes any validators. The value that comes out of this `$parsers` pipeline, be applied to
- * `$modelValue` and the **expression** specified in the `ng-model` attribute.
+ * For example {@link ng.directive:input input} calls it when the value of the input changes and
+ * {@link ng.directive:select select} calls it when an option is selected.
*
+ * If the new `value` is an object (rather than a string or a number), we should make a copy of the
+ * object before passing it to `$setViewValue`. This is because `ngModel` does not perform a deep
+ * watch of objects, it only looks for a change of identity. If you only change the property of
+ * the object then ngModel will not realise that the object has changed and will not invoke the
+ * `$parsers` and `$validators` pipelines.
+ *
+ * For this reason, you should not change properties of the copy once it has been passed to
+ * `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly.
+ *
+ * When this method is called, the new `value` will be staged for committing through the `$parsers`
+ * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged
+ * value sent directly for processing, finally to be applied to `$modelValue` and then the
+ * **expression** specified in the `ng-model` attribute.
+ *
* Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.
*
* In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`
* and the `default` trigger is not listed, all those actions will remain pending until one of the
* `updateOn` events is triggered on the DOM element.
@@ -28323,10 +28440,14 @@
// model -> value
$scope.$watch(function ngModelWatch() {
var modelValue = ngModelGet($scope);
+ if (ctrl.$options && ctrl.$options.getterSetter && isFunction(modelValue)) {
+ modelValue = modelValue();
+ }
+
// if scope model value and ngModel value are out of sync
if (ctrl.$modelValue !== modelValue &&
(isUndefined(ctrl.$$invalidModelValue) || ctrl.$$invalidModelValue != modelValue)) {
var formatters = ctrl.$formatters,
@@ -28336,12 +28457,10 @@
while(idx--) {
viewValue = formatters[idx](viewValue);
}
ctrl.$$runValidators(modelValue, viewValue);
- ctrl.$modelValue = ctrl.$valid ? modelValue : undefined;
- ctrl.$$invalidModelValue = ctrl.$valid ? undefined : modelValue;
if (ctrl.$viewValue !== viewValue) {
ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
ctrl.$render();
}
@@ -28431,16 +28550,17 @@
* color:white;
* }
* </pre>
*
* @example
- * <example deps="angular-animate.js" animations="true" fixBase="true">
+ * <example deps="angular-animate.js" animations="true" fixBase="true" module="inputExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.val = '1';
- }
+ angular.module('inputExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.val = '1';
+ }]);
</script>
<style>
.my-input {
-webkit-transition:all linear 0.5s;
transition:all linear 0.5s;
@@ -28451,15 +28571,64 @@
background: red;
}
</style>
Update input to see transitions when valid/invalid.
Integer is a valid value.
- <form name="testForm" ng-controller="Ctrl">
+ <form name="testForm" ng-controller="ExampleController">
<input ng-model="val" ng-pattern="/^\d+$/" name="anim" class="my-input" />
</form>
</file>
* </example>
+ *
+ * ## Binding to a getter/setter
+ *
+ * Sometimes it's helpful to bind `ngModel` to a getter/setter function. A getter/setter is a
+ * function that returns a representation of the model when called with zero arguments, and sets
+ * the internal state of a model when called with an argument. It's sometimes useful to use this
+ * for models that have an internal representation that's different than what the model exposes
+ * to the view.
+ *
+ * <div class="alert alert-success">
+ * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more
+ * frequently than other parts of your code.
+ * </div>
+ *
+ * You use this behavior by adding `ng-model-options="{ getterSetter: true }"` to an element that
+ * has `ng-model` attached to it. You can also add `ng-model-options="{ getterSetter: true }"` to
+ * a `<form>`, which will enable this behavior for all `<input>`s within it. See
+ * {@link ng.directive:ngModelOptions `ngModelOptions`} for more.
+ *
+ * The following example shows how to use `ngModel` with a getter/setter:
+ *
+ * @example
+ * <example name="ngModel-getter-setter" module="getterSetterExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form name="userForm">
+ Name:
+ <input type="text" name="userName"
+ ng-model="user.name"
+ ng-model-options="{ getterSetter: true }" />
+ </form>
+ <pre>user.name = <span ng-bind="user.name()"></span></pre>
+ </div>
+ </file>
+ <file name="app.js">
+ angular.module('getterSetterExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ var _name = 'Brian';
+ $scope.user = {
+ name: function (newName) {
+ if (angular.isDefined(newName)) {
+ _name = newName;
+ }
+ return _name;
+ }
+ };
+ }]);
+ </file>
+ * </example>
*/
var ngModelDirective = function() {
return {
require: ['ngModel', '^?form', '^?ngModelOptions'],
controller: NgModelController,
@@ -28518,21 +28687,22 @@
* @element input
* @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change
* in input value.
*
* @example
- * <example name="ngChange-directive">
+ * <example name="ngChange-directive" module="changeExample">
* <file name="index.html">
* <script>
- * function Controller($scope) {
- * $scope.counter = 0;
- * $scope.change = function() {
- * $scope.counter++;
- * };
- * }
+ * angular.module('changeExample', [])
+ * .controller('ExampleController', ['$scope', function($scope) {
+ * $scope.counter = 0;
+ * $scope.change = function() {
+ * $scope.counter++;
+ * };
+ * }]);
* </script>
- * <div ng-controller="Controller">
+ * <div ng-controller="ExampleController">
* <input type="checkbox" ng-model="confirmed" ng-change="change()" id="ng-change-example1" />
* <input type="checkbox" ng-model="confirmed" id="ng-change-example2" />
* <label for="ng-change-example2">Confirmed</label><br />
* <tt>debug = {{confirmed}}</tt><br/>
* <tt>counter = {{counter}}</tt><br/>
@@ -28667,18 +28837,19 @@
* @element input
* @param {string=} ngList optional delimiter that should be used to split the value. If
* specified in form `/something/` then the value will be converted into a regular expression.
*
* @example
- <example name="ngList-directive">
+ <example name="ngList-directive" module="listExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.names = ['igor', 'misko', 'vojta'];
- }
+ angular.module('listExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.names = ['igor', 'misko', 'vojta'];
+ }]);
</script>
- <form name="myForm" ng-controller="Ctrl">
+ <form name="myForm" ng-controller="ExampleController">
List: <input name="namesInput" ng-model="names" ng-list required>
<span class="error" ng-show="myForm.namesInput.$error.required">
Required!</span>
<br>
<tt>names = {{names}}</tt><br/>
@@ -28766,19 +28937,20 @@
* @element input
* @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute
* of the `input` element
*
* @example
- <example name="ngValue-directive">
+ <example name="ngValue-directive" module="valueExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.names = ['pizza', 'unicorns', 'robots'];
- $scope.my = { favorite: 'unicorns' };
- }
+ angular.module('valueExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.names = ['pizza', 'unicorns', 'robots'];
+ $scope.my = { favorite: 'unicorns' };
+ }]);
</script>
- <form ng-controller="Ctrl">
+ <form ng-controller="ExampleController">
<h2>Which is your favorite?</h2>
<label ng-repeat="name in names" for="{{name}}">
{{name}}
<input type="radio"
ng-model="my.favorite"
@@ -28850,20 +29022,22 @@
* matches the default events belonging of the control.
* - `debounce`: integer value which contains the debounce model update value in milliseconds. A
* value of 0 triggers an immediate update. If an object is supplied instead, you can specify a
* custom value for each event. For example:
* `ngModelOptions="{ updateOn: 'default blur', debounce: {'default': 500, 'blur': 0} }"`
+ * - `getterSetter`: boolean value which determines whether or not to treat functions bound to
+ `ngModel` as getters/setters.
*
* @example
The following example shows how to override immediate updates. Changes on the inputs within the
form will update the model only when the control loses focus (blur event). If `escape` key is
pressed while the input field is focused, the value is reset to the value in the current model.
- <example name="ngModelOptions-directive-blur">
+ <example name="ngModelOptions-directive-blur" module="optionsExample">
<file name="index.html">
- <div ng-controller="Ctrl">
+ <div ng-controller="ExampleController">
<form name="userForm">
Name:
<input type="text" name="userName"
ng-model="user.name"
ng-model-options="{ updateOn: 'blur' }"
@@ -28874,19 +29048,20 @@
</form>
<pre>user.name = <span ng-bind="user.name"></span></pre>
</div>
</file>
<file name="app.js">
- function Ctrl($scope) {
- $scope.user = { name: 'say', data: '' };
+ angular.module('optionsExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.user = { name: 'say', data: '' };
- $scope.cancel = function (e) {
- if (e.keyCode == 27) {
- $scope.userForm.userName.$rollbackViewValue();
- }
- };
- }
+ $scope.cancel = function (e) {
+ if (e.keyCode == 27) {
+ $scope.userForm.userName.$rollbackViewValue();
+ }
+ };
+ }]);
</file>
<file name="protractor.js" type="protractor">
var model = element(by.binding('user.name'));
var input = element(by.model('user.name'));
var other = element(by.model('user.data'));
@@ -28911,13 +29086,13 @@
</example>
This one shows how to debounce model changes. Model will be updated only 1 sec after last change.
If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty.
- <example name="ngModelOptions-directive-debounce">
+ <example name="ngModelOptions-directive-debounce" module="optionsExample">
<file name="index.html">
- <div ng-controller="Ctrl">
+ <div ng-controller="ExampleController">
<form name="userForm">
Name:
<input type="text" name="userName"
ng-model="user.name"
ng-model-options="{ debounce: 1000 }" />
@@ -28925,15 +29100,43 @@
</form>
<pre>user.name = <span ng-bind="user.name"></span></pre>
</div>
</file>
<file name="app.js">
- function Ctrl($scope) {
- $scope.user = { name: 'say' };
- }
+ angular.module('optionsExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.user = { name: 'say' };
+ }]);
</file>
</example>
+
+ This one shows how to bind to getter/setters:
+
+ <example name="ngModelOptions-directive-getter-setter" module="getterSetterExample">
+ <file name="index.html">
+ <div ng-controller="ExampleController">
+ <form name="userForm">
+ Name:
+ <input type="text" name="userName"
+ ng-model="user.name"
+ ng-model-options="{ getterSetter: true }" />
+ </form>
+ <pre>user.name = <span ng-bind="user.name()"></span></pre>
+ </div>
+ </file>
+ <file name="app.js">
+ angular.module('getterSetterExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ var _name = 'Brian';
+ $scope.user = {
+ name: function (newName) {
+ return angular.isDefined(newName) ? (_name = newName) : _name;
+ }
+ };
+ }]);
+ </file>
+ </example>
*/
var ngModelOptionsDirective = function() {
return {
controller: ['$scope', '$attrs', function($scope, $attrs) {
var that = this;
@@ -28977,18 +29180,19 @@
* @element ANY
* @param {expression} ngBind {@link guide/expression Expression} to evaluate.
*
* @example
* Enter a name in the Live Preview text box; the greeting below the text box changes instantly.
- <example>
+ <example module="bindExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.name = 'Whirled';
- }
+ angular.module('bindExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.name = 'Whirled';
+ }]);
</script>
- <div ng-controller="Ctrl">
+ <div ng-controller="ExampleController">
Enter name: <input type="text" ng-model="name"><br>
Hello <span ng-bind="name"></span>!
</div>
</file>
<file name="protractor.js" type="protractor">
@@ -29035,19 +29239,20 @@
* @param {string} ngBindTemplate template of form
* <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.
*
* @example
* Try it here: enter text in text box and watch the greeting change.
- <example>
+ <example module="bindExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.salutation = 'Hello';
- $scope.name = 'World';
- }
+ angular.module('bindExample', [])
+ .controller('ExampleController', ['$scope', function ($scope) {
+ $scope.salutation = 'Hello';
+ $scope.name = 'World';
+ }]);
</script>
- <div ng-controller="Ctrl">
+ <div ng-controller="ExampleController">
Salutation: <input type="text" ng-model="salutation"><br>
Name: <input type="text" ng-model="name"><br>
<pre ng-bind-template="{{salutation}} {{name}}!"></pre>
</div>
</file>
@@ -29101,24 +29306,24 @@
* @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
*
* @example
Try it here: enter text in text box and watch the greeting change.
- <example module="ngBindHtmlExample" deps="angular-sanitize.js">
+ <example module="bindHtmlExample" deps="angular-sanitize.js">
<file name="index.html">
- <div ng-controller="ngBindHtmlCtrl">
+ <div ng-controller="ExampleController">
<p ng-bind-html="myHTML"></p>
</div>
</file>
<file name="script.js">
- angular.module('ngBindHtmlExample', ['ngSanitize'])
-
- .controller('ngBindHtmlCtrl', ['$scope', function ngBindHtmlCtrl($scope) {
- $scope.myHTML =
- 'I am an <code>HTML</code>string with <a href="#">links!</a> and other <em>stuff</em>';
- }]);
+ angular.module('bindHtmlExample', ['ngSanitize'])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.myHTML =
+ 'I am an <code>HTML</code>string with ' +
+ '<a href="#">links!</a> and other <em>stuff</em>';
+ }]);
</file>
<file name="protractor.js" type="protractor">
it('should check ng-bind-html', function() {
expect(element(by.binding('myHTML')).getText()).toBe(
@@ -29617,11 +29822,11 @@
* * Since there is always a `.` in the bindings, you don't have to worry about prototypal
* inheritance masking primitives.
*
* This example demonstrates the `controller as` syntax.
*
- * <example name="ngControllerAs">
+ * <example name="ngControllerAs" module="controllerAsExample">
* <file name="index.html">
* <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
* Name: <input type="text" ng-model="settings.name"/>
* [ <a href="" ng-click="settings.greet()">greet</a> ]<br/>
* Contact:
@@ -29638,10 +29843,13 @@
* <li>[ <a href="" ng-click="settings.addContact()">add</a> ]</li>
* </ul>
* </div>
* </file>
* <file name="app.js">
+ * angular.module('controllerAsExample', [])
+ * .controller('SettingsController1', SettingsController1);
+ *
* function SettingsController1() {
* this.name = "John Smith";
* this.contacts = [
* {type: 'phone', value: '408 555 1212'},
* {type: 'email', value: 'john.smith@example.org'} ];
@@ -29666,42 +29874,42 @@
* };
* </file>
* <file name="protractor.js" type="protractor">
* it('should check controller as', function() {
* var container = element(by.id('ctrl-as-exmpl'));
- * expect(container.findElement(by.model('settings.name'))
+ * expect(container.element(by.model('settings.name'))
* .getAttribute('value')).toBe('John Smith');
*
* var firstRepeat =
- * container.findElement(by.repeater('contact in settings.contacts').row(0));
+ * container.element(by.repeater('contact in settings.contacts').row(0));
* var secondRepeat =
- * container.findElement(by.repeater('contact in settings.contacts').row(1));
+ * container.element(by.repeater('contact in settings.contacts').row(1));
*
- * expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
+ * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
* .toBe('408 555 1212');
*
- * expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value'))
+ * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
* .toBe('john.smith@example.org');
*
- * firstRepeat.findElement(by.linkText('clear')).click();
+ * firstRepeat.element(by.linkText('clear')).click();
*
- * expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
+ * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
* .toBe('');
*
- * container.findElement(by.linkText('add')).click();
+ * container.element(by.linkText('add')).click();
*
- * expect(container.findElement(by.repeater('contact in settings.contacts').row(2))
- * .findElement(by.model('contact.value'))
+ * expect(container.element(by.repeater('contact in settings.contacts').row(2))
+ * .element(by.model('contact.value'))
* .getAttribute('value'))
* .toBe('yourname@example.org');
* });
* </file>
* </example>
*
* This example demonstrates the "attach to `$scope`" style of controller.
*
- * <example name="ngController">
+ * <example name="ngController" module="controllerExample">
* <file name="index.html">
* <div id="ctrl-exmpl" ng-controller="SettingsController2">
* Name: <input type="text" ng-model="name"/>
* [ <a href="" ng-click="greet()">greet</a> ]<br/>
* Contact:
@@ -29718,10 +29926,13 @@
* <li>[ <a href="" ng-click="addContact()">add</a> ]</li>
* </ul>
* </div>
* </file>
* <file name="app.js">
+ * angular.module('controllerExample', [])
+ * .controller('SettingsController2', ['$scope', SettingsController2]);
+ *
* function SettingsController2($scope) {
* $scope.name = "John Smith";
* $scope.contacts = [
* {type:'phone', value:'408 555 1212'},
* {type:'email', value:'john.smith@example.org'} ];
@@ -29747,32 +29958,32 @@
* </file>
* <file name="protractor.js" type="protractor">
* it('should check controller', function() {
* var container = element(by.id('ctrl-exmpl'));
*
- * expect(container.findElement(by.model('name'))
+ * expect(container.element(by.model('name'))
* .getAttribute('value')).toBe('John Smith');
*
* var firstRepeat =
- * container.findElement(by.repeater('contact in contacts').row(0));
+ * container.element(by.repeater('contact in contacts').row(0));
* var secondRepeat =
- * container.findElement(by.repeater('contact in contacts').row(1));
+ * container.element(by.repeater('contact in contacts').row(1));
*
- * expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
+ * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
* .toBe('408 555 1212');
- * expect(secondRepeat.findElement(by.model('contact.value')).getAttribute('value'))
+ * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
* .toBe('john.smith@example.org');
*
- * firstRepeat.findElement(by.linkText('clear')).click();
+ * firstRepeat.element(by.linkText('clear')).click();
*
- * expect(firstRepeat.findElement(by.model('contact.value')).getAttribute('value'))
+ * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
* .toBe('');
*
- * container.findElement(by.linkText('add')).click();
+ * container.element(by.linkText('add')).click();
*
- * expect(container.findElement(by.repeater('contact in contacts').row(2))
- * .findElement(by.model('contact.value'))
+ * expect(container.element(by.repeater('contact in contacts').row(2))
+ * .element(by.model('contact.value'))
* .getAttribute('value'))
* .toBe('yourname@example.org');
* });
* </file>
*</example>
@@ -30139,25 +30350,26 @@
* @priority 0
* @param {expression} ngSubmit {@link guide/expression Expression} to eval.
* ({@link guide/expression#-event- Event object is available as `$event`})
*
* @example
- <example>
+ <example module="submitExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.list = [];
- $scope.text = 'hello';
- $scope.submit = function() {
- if ($scope.text) {
- $scope.list.push(this.text);
- $scope.text = '';
- }
- };
- }
+ angular.module('submitExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.list = [];
+ $scope.text = 'hello';
+ $scope.submit = function() {
+ if ($scope.text) {
+ $scope.list.push(this.text);
+ $scope.text = '';
+ }
+ };
+ }]);
</script>
- <form ng-submit="submit()" ng-controller="Ctrl">
+ <form ng-submit="submit()" ng-controller="ExampleController">
Enter text and hit enter:
<input type="text" ng-model="text" name="text" />
<input type="submit" id="submit" value="Submit" />
<pre>list={{list}}</pre>
</form>
@@ -30165,11 +30377,11 @@
<file name="protractor.js" type="protractor">
it('should check ng-submit', function() {
expect(element(by.binding('list')).getText()).toBe('list=[]');
element(by.css('#submit')).click();
expect(element(by.binding('list')).getText()).toContain('hello');
- expect(element(by.input('text')).getAttribute('value')).toBe('');
+ expect(element(by.model('text')).getAttribute('value')).toBe('');
});
it('should ignore empty strings', function() {
expect(element(by.binding('list')).getText()).toBe('list=[]');
element(by.css('#submit')).click();
element(by.css('#submit')).click();
@@ -30438,13 +30650,13 @@
* - If the attribute is not set, disable scrolling.
* - If the attribute is set without value, enable scrolling.
* - Otherwise enable scrolling only if the expression evaluates to truthy value.
*
* @example
- <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <example module="includeExample" deps="angular-animate.js" animations="true">
<file name="index.html">
- <div ng-controller="Ctrl">
+ <div ng-controller="ExampleController">
<select ng-model="template" ng-options="t.name for t in templates">
<option value="">(blank)</option>
</select>
url of the template: <tt>{{template.url}}</tt>
<hr/>
@@ -30452,16 +30664,17 @@
<div class="slide-animate" ng-include="template.url"></div>
</div>
</div>
</file>
<file name="script.js">
- function Ctrl($scope) {
- $scope.templates =
- [ { name: 'template1.html', url: 'template1.html'},
- { name: 'template2.html', url: 'template2.html'} ];
- $scope.template = $scope.templates[0];
- }
+ angular.module('includeExample', ['ngAnimate'])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.templates =
+ [ { name: 'template1.html', url: 'template1.html'},
+ { name: 'template2.html', url: 'template2.html'} ];
+ $scope.template = $scope.templates[0];
+ }]);
</file>
<file name="template1.html">
Content of template1.html
</file>
<file name="template2.html">
@@ -30520,21 +30733,21 @@
// Firefox can't handle using selects
// See https://github.com/angular/protractor/issues/480
return;
}
templateSelect.click();
- templateSelect.element.all(by.css('option')).get(2).click();
+ templateSelect.all(by.css('option')).get(2).click();
expect(includeElem.getText()).toMatch(/Content of template2.html/);
});
it('should change to blank', function() {
if (browser.params.browser == 'firefox') {
// Firefox can't handle using selects
return;
}
templateSelect.click();
- templateSelect.element.all(by.css('option')).get(0).click();
+ templateSelect.all(by.css('option')).get(0).click();
expect(includeElem.isPresent()).toBe(false);
});
</file>
</example>
*/
@@ -30558,12 +30771,11 @@
*/
/**
* @ngdoc event
- * @name ng.directive:ngInclude#$includeContentError
- * @eventOf ng.directive:ngInclude
+ * @name ngInclude#$includeContentError
* @eventType emit on the scope ngInclude was declared in
* @description
* Emitted when a template HTTP request yields an erronous response (status < 200 || status > 299)
*/
var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$animate', '$sce',
@@ -30695,18 +30907,19 @@
*
* @element ANY
* @param {expression} ngInit {@link guide/expression Expression} to eval.
*
* @example
- <example>
+ <example module="initExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.list = [['a', 'b'], ['c', 'd']];
- }
+ angular.module('initExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.list = [['a', 'b'], ['c', 'd']];
+ }]);
</script>
- <div ng-controller="Ctrl">
+ <div ng-controller="ExampleController">
<div ng-repeat="innerList in list" ng-init="outerIndex = $index">
<div ng-repeat="value in innerList" ng-init="innerIndex = $index">
<span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>
</div>
</div>
@@ -30855,20 +31068,21 @@
* @param {string|expression} count The variable to be bound to.
* @param {string} when The mapping between plural category to its corresponding strings.
* @param {number=} offset Offset to deduct from the total number.
*
* @example
- <example>
+ <example module="pluralizeExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.person1 = 'Igor';
- $scope.person2 = 'Misko';
- $scope.personCount = 1;
- }
+ angular.module('pluralizeExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.person1 = 'Igor';
+ $scope.person2 = 'Misko';
+ $scope.personCount = 1;
+ }]);
</script>
- <div ng-controller="Ctrl">
+ <div ng-controller="ExampleController">
Person 1:<input type="text" ng-model="person1" value="Igor" /><br/>
Person 2:<input type="text" ng-model="person2" value="Misko" /><br/>
Number of People:<input type="text" ng-model="personCount" value="1" /><br/>
<!--- Example with simple pluralization rules for en locale --->
@@ -31796,13 +32010,13 @@
* are multiple default cases, all of them will be displayed when no other
* case match.
*
*
* @example
- <example module="ngAnimate" deps="angular-animate.js" animations="true">
+ <example module="switchExample" deps="angular-animate.js" animations="true">
<file name="index.html">
- <div ng-controller="Ctrl">
+ <div ng-controller="ExampleController">
<select ng-model="selection" ng-options="item for item in items">
</select>
<tt>selection={{selection}}</tt>
<hr/>
<div class="animate-switch-container"
@@ -31812,14 +32026,15 @@
<div class="animate-switch" ng-switch-default>default</div>
</div>
</div>
</file>
<file name="script.js">
- function Ctrl($scope) {
- $scope.items = ['settings', 'home', 'other'];
- $scope.selection = $scope.items[0];
- }
+ angular.module('switchExample', ['ngAnimate'])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.items = ['settings', 'home', 'other'];
+ $scope.selection = $scope.items[0];
+ }]);
</file>
<file name="animations.css">
.animate-switch-container {
position:relative;
background:white;
@@ -31858,15 +32073,15 @@
it('should start in settings', function() {
expect(switchElem.getText()).toMatch(/Settings Div/);
});
it('should change to home', function() {
- select.element.all(by.css('option')).get(1).click();
+ select.all(by.css('option')).get(1).click();
expect(switchElem.getText()).toMatch(/Home Span/);
});
it('should select default', function() {
- select.element.all(by.css('option')).get(2).click();
+ select.all(by.css('option')).get(2).click();
expect(switchElem.getText()).toMatch(/default/);
});
</file>
</example>
*/
@@ -31954,32 +32169,31 @@
* Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.
*
* @element ANY
*
* @example
- <example module="transclude">
+ <example module="transcludeExample">
<file name="index.html">
<script>
- function Ctrl($scope) {
- $scope.title = 'Lorem Ipsum';
- $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
- }
-
- angular.module('transclude', [])
+ angular.module('transcludeExample', [])
.directive('pane', function(){
return {
restrict: 'E',
transclude: true,
scope: { title:'@' },
template: '<div style="border: 1px solid black;">' +
'<div style="background-color: gray">{{title}}</div>' +
'<div ng-transclude></div>' +
'</div>'
};
- });
+ })
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.title = 'Lorem Ipsum';
+ $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
+ }]);
</script>
- <div ng-controller="Ctrl">
+ <div ng-controller="ExampleController">
<input ng-model="title"><br>
<textarea ng-model="text"></textarea> <br/>
<pane title="{{title}}">{{text}}</pane>
</div>
</file>
@@ -32134,25 +32348,26 @@
* * `trackexpr`: Used when working with an array of objects. The result of this expression will be
* used to identify the objects in the array. The `trackexpr` will most likely refer to the
* `value` variable (e.g. `value.propertyName`).
*
* @example
- <example>
+ <example module="selectExample">
<file name="index.html">
<script>
- function MyCntrl($scope) {
- $scope.colors = [
- {name:'black', shade:'dark'},
- {name:'white', shade:'light'},
- {name:'red', shade:'dark'},
- {name:'blue', shade:'dark'},
- {name:'yellow', shade:'light'}
- ];
- $scope.myColor = $scope.colors[2]; // red
- }
+ angular.module('selectExample', [])
+ .controller('ExampleController', ['$scope', function($scope) {
+ $scope.colors = [
+ {name:'black', shade:'dark'},
+ {name:'white', shade:'light'},
+ {name:'red', shade:'dark'},
+ {name:'blue', shade:'dark'},
+ {name:'yellow', shade:'light'}
+ ];
+ $scope.myColor = $scope.colors[2]; // red
+ }]);
</script>
- <div ng-controller="MyCntrl">
+ <div ng-controller="ExampleController">
<ul>
<li ng-repeat="color in colors">
Name: <input ng-model="color.name">
[<a href ng-click="colors.splice($index, 1)">X</a>]
</li>
@@ -32185,11 +32400,11 @@
</div>
</file>
<file name="protractor.js" type="protractor">
it('should check ng-options', function() {
expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');
- element.all(by.select('myColor')).first().click();
+ element.all(by.model('myColor')).first().click();
element.all(by.css('select[ng-model="myColor"] option')).first().click();
expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');
element(by.css('.nullable select[ng-model="myColor"]')).click();
element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click();
expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');
@@ -32225,18 +32440,24 @@
nullOption = nullOption_;
unknownOption = unknownOption_;
};
- self.addOption = function(value) {
+ self.addOption = function(value, element) {
assertNotHasOwnProperty(value, '"option value"');
optionsMap[value] = true;
if (ngModelCtrl.$viewValue == value) {
$element.val(value);
if (unknownOption.parent()) unknownOption.remove();
}
+ // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459
+ // Adding an <option selected="selected"> element to a <select required="required"> should
+ // automatically select the new element
+ if (element[0].hasAttribute('selected')) {
+ element[0].selected = true;
+ }
};
self.removeOption = function(value) {
if (this.hasOption(value)) {
@@ -32686,13 +32907,13 @@
scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {
attr.$set('value', newVal);
if (oldVal !== newVal) {
selectCtrl.removeOption(oldVal);
}
- selectCtrl.addOption(newVal);
+ selectCtrl.addOption(newVal, element);
});
} else {
- selectCtrl.addOption(attr.value);
+ selectCtrl.addOption(attr.value, element);
}
element.on('$destroy', function() {
selectCtrl.removeOption(attr.value);
});
\ No newline at end of file